summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-x.gitignore17
-rw-r--r--INFO.yaml9
-rw-r--r--adaptors/LICENSE.txt22
-rw-r--r--adaptors/README.md8
-rwxr-xr-xadaptors/aai-service/.gitignore35
-rwxr-xr-xadaptors/aai-service/README.md0
-rwxr-xr-xadaptors/aai-service/installer/pom.xml143
-rw-r--r--adaptors/aai-service/installer/src/assembly/assemble_installer_zip.xml59
-rw-r--r--adaptors/aai-service/installer/src/assembly/assemble_mvnrepo_zip.xml49
-rw-r--r--adaptors/aai-service/installer/src/main/resources/scripts/install-feature.sh39
-rwxr-xr-xadaptors/aai-service/pom.xml24
-rwxr-xr-xadaptors/aai-service/provider/pom.xml148
-rwxr-xr-xadaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/AAIClient.java91
-rwxr-xr-xadaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/AAIClientRESTExecutor.java781
-rwxr-xr-xadaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/AAIDeclarations.java2041
-rwxr-xr-xadaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/AAIExecutorInterface.java33
-rwxr-xr-xadaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/AAIRequest.java493
-rwxr-xr-xadaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/AAIService.java1547
-rwxr-xr-xadaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/AAIServiceException.java89
-rwxr-xr-xadaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/AAIServiceProvider.java226
-rwxr-xr-xadaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/AAIServiceUtils.java394
-rwxr-xr-xadaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/AAITrinityService.java39
-rwxr-xr-xadaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/CustomQueryRequest.java138
-rwxr-xr-xadaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/EchoRequest.java97
-rwxr-xr-xadaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/GenericQueryRequest.java128
-rwxr-xr-xadaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/GenericRequest.java265
-rwxr-xr-xadaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/HttpMethod.java13
-rwxr-xr-xadaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/NodesQueryRequest.java129
-rwxr-xr-xadaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/PathRequest.java91
-rwxr-xr-xadaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/RelationshipListRequest.java65
-rwxr-xr-xadaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/RelationshipRequest.java67
-rwxr-xr-xadaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/SelfLinkRequest.java109
-rwxr-xr-xadaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/UpdateRequest.java152
-rwxr-xr-xadaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/UtilsProvider.java36
-rw-r--r--adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/data/AAIDatum.java26
-rw-r--r--adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/data/EchoResponse.java76
-rw-r--r--adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/data/ErrorResponse.java78
-rw-r--r--adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/data/RequestError.java78
-rw-r--r--adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/data/ResourceVersion.java28
-rw-r--r--adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/data/ResponseMessage.java122
-rw-r--r--adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/data/ResponseMessages.java78
-rw-r--r--adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/data/ServiceException.java126
-rw-r--r--adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/data/SubInterface.java171
-rw-r--r--adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/data/Variables.java78
-rw-r--r--adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/data/notify/KeyDatum.java99
-rw-r--r--adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/data/notify/NotifyEvent.java170
-rw-r--r--adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/query/FormattedQueryRequestData.java83
-rwxr-xr-xadaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/query/FormattedQueryResultList.java60
-rwxr-xr-xadaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/query/InstanceFilter.java205
-rw-r--r--adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/query/InstanceFilters.java78
-rwxr-xr-xadaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/query/Result.java278
-rw-r--r--adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/update/Action.java101
-rw-r--r--adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/update/ActionDatum.java99
-rw-r--r--adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/update/Update.java124
-rw-r--r--adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/update/UpdateNodeKey.java99
-rwxr-xr-xadaptors/aai-service/provider/src/main/resources/OSGI-INF/blueprint/aaiservice-blueprint.xml39
-rwxr-xr-xadaptors/aai-service/provider/src/main/resources/aai-path.properties353
-rwxr-xr-xadaptors/aai-service/provider/src/main/resources/aai-schema-bindings.xjb11
-rw-r--r--adaptors/aai-service/provider/src/main/resources/aai_schema_v21.xsd14837
-rwxr-xr-xadaptors/aai-service/provider/src/main/resources/aaiclient.properties76
-rwxr-xr-xadaptors/aai-service/provider/src/main/resources/org/opendaylight/blueprint/aaiservice-blueprint.xml39
-rw-r--r--adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/AAIClientRESTExecutorTest.java126
-rw-r--r--adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/AAIServiceProviderTest.java31
-rwxr-xr-xadaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/AAIServiceTest.java212
-rwxr-xr-xadaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/ActionUpdateTest.java44
-rwxr-xr-xadaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/AutoGeneratedRegressionTest.java906
-rw-r--r--adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/CustomQueryRequestTest.java117
-rwxr-xr-xadaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/EchoRequestTest.java136
-rwxr-xr-xadaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/GenericRequestTest.java190
-rw-r--r--adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/GenericVnfRequestTest.java117
-rwxr-xr-xadaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/GenericVnfTest.java243
-rw-r--r--adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/NodesQueryRequestTest.java88
-rwxr-xr-xadaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/PathCreationTest.java204
-rwxr-xr-xadaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/RegressionTest.java422
-rw-r--r--adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/RelationshipRequestTest.java118
-rwxr-xr-xadaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/RequestPathTest.java76
-rw-r--r--adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/data/ErrorResponseTest.java51
-rw-r--r--adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/data/RequestErrorTest.java51
-rw-r--r--adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/data/ResponseMessageTest.java68
-rw-r--r--adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/data/ResponseMessagesTest.java55
-rw-r--r--adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/data/ServiceExceptionTest.java71
-rw-r--r--adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/data/SubInterfaceTest.java94
-rw-r--r--adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/data/VariablesTest.java56
-rw-r--r--adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/data/notify/KeyDatumTest.java38
-rw-r--r--adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/data/notify/NotifyEventTest.java53
-rw-r--r--adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/query/FormattedQueryRequestDataTest.java53
-rw-r--r--adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/query/FormattedQueryResultListTest.java49
-rw-r--r--adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/query/InstanceFilterTest.java124
-rw-r--r--adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/query/InstanceFiltersTest.java55
-rw-r--r--adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/query/ResultTest.java159
-rw-r--r--adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/update/ActionDatumTest.java58
-rw-r--r--adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/update/ActionTest.java64
-rw-r--r--adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/update/UpdateNodeKeyTest.java53
-rw-r--r--adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/update/UpdateTest.java75
-rwxr-xr-xadaptors/aai-service/provider/src/test/resources/aaiclient.properties80
-rwxr-xr-xadaptors/aai-service/provider/src/test/resources/json/linterfaceJson.txt43
-rwxr-xr-xadaptors/aai-service/provider/src/test/resources/json/pserverJson.txt97
-rw-r--r--adaptors/aai-service/provider/src/test/resources/testCommands.txt1
-rw-r--r--adaptors/ansible-adapter/.pydevproject5
-rw-r--r--adaptors/ansible-adapter/ansible-adapter-bundle/.gitignore25
-rw-r--r--adaptors/ansible-adapter/ansible-adapter-bundle/pom.xml131
-rw-r--r--adaptors/ansible-adapter/ansible-adapter-bundle/src/main/java/org/onap/ccsdk/sli/adaptors/ansible/AnsibleAdapter.java55
-rwxr-xr-xadaptors/ansible-adapter/ansible-adapter-bundle/src/main/java/org/onap/ccsdk/sli/adaptors/ansible/AnsibleAdapterPropertiesProvider.java28
-rw-r--r--adaptors/ansible-adapter/ansible-adapter-bundle/src/main/java/org/onap/ccsdk/sli/adaptors/ansible/impl/AnsibleAdapterImpl.java460
-rwxr-xr-xadaptors/ansible-adapter/ansible-adapter-bundle/src/main/java/org/onap/ccsdk/sli/adaptors/ansible/impl/AnsibleAdapterPropertiesProviderImpl.java191
-rw-r--r--adaptors/ansible-adapter/ansible-adapter-bundle/src/main/java/org/onap/ccsdk/sli/adaptors/ansible/impl/ConnectionBuilder.java205
-rw-r--r--adaptors/ansible-adapter/ansible-adapter-bundle/src/main/java/org/onap/ccsdk/sli/adaptors/ansible/model/AnsibleMessageParser.java332
-rw-r--r--adaptors/ansible-adapter/ansible-adapter-bundle/src/main/java/org/onap/ccsdk/sli/adaptors/ansible/model/AnsibleResult.java81
-rw-r--r--adaptors/ansible-adapter/ansible-adapter-bundle/src/main/java/org/onap/ccsdk/sli/adaptors/ansible/model/AnsibleResultCodes.java93
-rw-r--r--adaptors/ansible-adapter/ansible-adapter-bundle/src/main/java/org/onap/ccsdk/sli/adaptors/ansible/model/AnsibleServerEmulator.java137
-rwxr-xr-xadaptors/ansible-adapter/ansible-adapter-bundle/src/main/resources/OSGI-INF/blueprint/ansible-adapter-blueprint.xml39
-rw-r--r--adaptors/ansible-adapter/ansible-adapter-bundle/src/main/resources/ansible-adapter.properties48
-rwxr-xr-xadaptors/ansible-adapter/ansible-adapter-bundle/src/main/resources/org/opendaylight/blueprint/ansible-adapter-blueprint.xml39
-rw-r--r--adaptors/ansible-adapter/ansible-adapter-bundle/src/test/java/org/onap/ccsdk/adapter/ansible/impl/TestAnsibleAdapterImpl.java147
-rw-r--r--adaptors/ansible-adapter/ansible-adapter-bundle/src/test/java/org/onap/ccsdk/adapter/ansible/impl/TestAnsibleAdapterPropertiesProviderImpl.java53
-rw-r--r--adaptors/ansible-adapter/ansible-adapter-bundle/src/test/java/org/onap/ccsdk/adapter/ansible/impl/TestConnectionBuilder.java155
-rw-r--r--adaptors/ansible-adapter/ansible-adapter-bundle/src/test/java/org/onap/ccsdk/adapter/ansible/model/TestAnsibleAdapter.java81
-rw-r--r--adaptors/ansible-adapter/ansible-adapter-bundle/src/test/java/org/onap/ccsdk/test/ExecutorHarness.java181
-rw-r--r--adaptors/ansible-adapter/ansible-adapter-bundle/src/test/java/org/onap/ccsdk/test/InterceptLogger.java454
-rw-r--r--adaptors/ansible-adapter/ansible-adapter-bundle/src/test/resources/cert125
-rw-r--r--adaptors/ansible-adapter/ansible-adapter-bundle/src/test/resources/org/onap/ccsdk/default.properties111
-rw-r--r--adaptors/ansible-adapter/ansible-adapter-installer/pom.xml151
-rw-r--r--adaptors/ansible-adapter/ansible-adapter-installer/src/assembly/assemble_installer_zip.xml62
-rw-r--r--adaptors/ansible-adapter/ansible-adapter-installer/src/assembly/assemble_mvnrepo_zip.xml50
-rw-r--r--adaptors/ansible-adapter/ansible-adapter-installer/src/main/resources/scripts/install-feature.sh42
-rw-r--r--adaptors/ansible-adapter/pom.xml191
-rwxr-xr-xadaptors/artifacts/pom.xml146
-rw-r--r--adaptors/base/http/installer/pom.xml127
-rw-r--r--adaptors/base/http/installer/src/assembly/assemble_installer_zip.xml59
-rw-r--r--adaptors/base/http/installer/src/assembly/assemble_mvnrepo_zip.xml49
-rw-r--r--adaptors/base/http/installer/src/main/resources/scripts/install-feature.sh39
-rw-r--r--adaptors/base/http/pom.xml21
-rw-r--r--adaptors/base/http/provider/pom.xml39
-rw-r--r--adaptors/base/http/provider/src/main/java/org/onap/ccsdk/sli/adaptors/base/http/AbstractHttpAdapter.java114
-rw-r--r--adaptors/base/http/provider/src/main/java/org/onap/ccsdk/sli/adaptors/base/http/BasicAuthFilter.java22
-rw-r--r--adaptors/base/http/provider/src/test/java/org/onap/ccsdk/sli/adaptors/base/http/AbstractHttpAdapterTest.java44
-rw-r--r--adaptors/base/http/provider/src/test/java/org/onap/ccsdk/sli/adaptors/base/http/BasicAuthFilterTest.java20
-rw-r--r--adaptors/base/http/provider/src/test/resources/testprops.properties1
-rw-r--r--adaptors/base/pom.xml20
-rw-r--r--adaptors/features/ccsdk-aai-service/pom.xml42
-rw-r--r--adaptors/features/ccsdk-ansible-adapter/pom.xml48
-rw-r--r--adaptors/features/ccsdk-base-http/pom.xml26
-rw-r--r--adaptors/features/ccsdk-mdsal-resource/pom.xml41
-rwxr-xr-xadaptors/features/ccsdk-messagerouter-consumer/pom.xml28
-rwxr-xr-xadaptors/features/ccsdk-messagerouter-publisher/pom.xml28
-rw-r--r--adaptors/features/ccsdk-netbox-client/pom.xml65
-rw-r--r--adaptors/features/ccsdk-resource-assignment/pom.xml51
-rw-r--r--adaptors/features/ccsdk-saltstack-adapter/pom.xml44
-rw-r--r--adaptors/features/ccsdk-sli-adaptors-all/pom.xml84
-rw-r--r--adaptors/features/ccsdk-sql-resource/pom.xml48
-rw-r--r--adaptors/features/features-sli-adaptors/pom.xml33
-rwxr-xr-xadaptors/features/installer/pom.xml265
-rwxr-xr-xadaptors/features/installer/src/assembly/assemble_installer_zip.xml39
-rwxr-xr-xadaptors/features/installer/src/assembly/assemble_mvnrepo_zip.xml29
-rw-r--r--adaptors/features/installer/src/main/resources/scripts/install-feature.sh18
-rwxr-xr-xadaptors/features/pom.xml34
-rwxr-xr-xadaptors/mdsal-resource/.gitignore34
-rwxr-xr-xadaptors/mdsal-resource/installer/pom.xml127
-rw-r--r--adaptors/mdsal-resource/installer/src/assembly/assemble_installer_zip.xml59
-rw-r--r--adaptors/mdsal-resource/installer/src/assembly/assemble_mvnrepo_zip.xml49
-rw-r--r--adaptors/mdsal-resource/installer/src/main/resources/scripts/install-feature.sh39
-rwxr-xr-xadaptors/mdsal-resource/pom.xml24
-rwxr-xr-xadaptors/mdsal-resource/provider/pom.xml81
-rw-r--r--adaptors/mdsal-resource/provider/src/main/java/org/onap/ccsdk/sli/adaptors/resource/mdsal/ConfigResource.java153
-rwxr-xr-xadaptors/mdsal-resource/provider/src/main/java/org/onap/ccsdk/sli/adaptors/resource/mdsal/MdsalResourcePropertiesProvider.java28
-rwxr-xr-xadaptors/mdsal-resource/provider/src/main/java/org/onap/ccsdk/sli/adaptors/resource/mdsal/MdsalResourcePropertiesProviderImpl.java186
-rw-r--r--adaptors/mdsal-resource/provider/src/main/java/org/onap/ccsdk/sli/adaptors/resource/mdsal/OperationalResource.java147
-rw-r--r--adaptors/mdsal-resource/provider/src/main/java/org/onap/ccsdk/sli/adaptors/resource/mdsal/RestService.java184
-rwxr-xr-xadaptors/mdsal-resource/provider/src/main/resources/IPV4_ADDRESS_POOL.csv9
-rwxr-xr-xadaptors/mdsal-resource/provider/src/main/resources/OSGI-INF/blueprint/mdsal-resource-blueprint.xml49
-rwxr-xr-xadaptors/mdsal-resource/provider/src/main/resources/VLAN_ID_POOL.csv22
-rw-r--r--adaptors/mdsal-resource/provider/src/main/resources/crtables.sql70
-rw-r--r--adaptors/mdsal-resource/provider/src/main/resources/mdsal-resource.properties27
-rwxr-xr-xadaptors/mdsal-resource/provider/src/main/resources/org/opendaylight/blueprint/mdsal-resource-blueprint.xml49
-rw-r--r--adaptors/mdsal-resource/provider/src/main/resources/svclogic.properties26
-rw-r--r--adaptors/mdsal-resource/provider/src/test/java/org/onap/ccsdk/sli/adaptors/resource/mdsal/ConfigResourceTest.java43
-rw-r--r--adaptors/mdsal-resource/provider/src/test/java/org/onap/ccsdk/sli/adaptors/resource/mdsal/TestConfigResource.java31
-rw-r--r--adaptors/mdsal-resource/provider/src/test/java/org/onap/ccsdk/sli/adaptors/resource/mdsal/TestMdsalResourcePropertiesProviderImpl.java64
-rw-r--r--adaptors/mdsal-resource/provider/src/test/java/org/onap/ccsdk/sli/adaptors/resource/mdsal/TestOperationalResource.java31
-rwxr-xr-xadaptors/message-router/README.md7
-rwxr-xr-xadaptors/message-router/consumer/README.md7
-rwxr-xr-xadaptors/message-router/consumer/api/pom.xml27
-rwxr-xr-xadaptors/message-router/consumer/api/src/main/java/org/onap/ccsdk/sli/adaptors/messagerouter/consumer/api/ConsumerApi.java6
-rwxr-xr-xadaptors/message-router/consumer/api/src/main/java/org/onap/ccsdk/sli/adaptors/messagerouter/consumer/api/PollingConsumer.java7
-rwxr-xr-xadaptors/message-router/consumer/api/src/main/java/org/onap/ccsdk/sli/adaptors/messagerouter/consumer/api/PullingConsumer.java7
-rwxr-xr-xadaptors/message-router/consumer/api/src/main/java/org/onap/ccsdk/sli/adaptors/messagerouter/consumer/api/RequestHandler.java5
-rwxr-xr-xadaptors/message-router/consumer/installer/pom.xml128
-rwxr-xr-xadaptors/message-router/consumer/installer/src/assembly/assemble_installer_zip.xml59
-rwxr-xr-xadaptors/message-router/consumer/installer/src/assembly/assemble_mvnrepo_zip.xml47
-rwxr-xr-xadaptors/message-router/consumer/installer/src/main/resources/scripts/install-feature.sh39
-rwxr-xr-xadaptors/message-router/consumer/pom.xml19
-rwxr-xr-xadaptors/message-router/consumer/provider/pom.xml43
-rwxr-xr-xadaptors/message-router/consumer/provider/src/main/java/org/onap/ccsdk/sli/adaptors/messagerouter/consumer/provider/impl/AbstractBaseConsumer.java207
-rwxr-xr-xadaptors/message-router/consumer/provider/src/main/java/org/onap/ccsdk/sli/adaptors/messagerouter/consumer/provider/impl/ConsumerFactory.java202
-rw-r--r--adaptors/message-router/consumer/provider/src/main/java/org/onap/ccsdk/sli/adaptors/messagerouter/consumer/provider/impl/PollingConsumerImpl.java100
-rwxr-xr-xadaptors/message-router/consumer/provider/src/main/java/org/onap/ccsdk/sli/adaptors/messagerouter/consumer/provider/impl/PullingConsumerImpl.java39
-rw-r--r--adaptors/message-router/consumer/provider/src/test/java/org/onap/ccsdk/sli/adaptors/messagerouter/consumer/provider/impl/AbstractBaseConsumerTest.java91
-rw-r--r--adaptors/message-router/consumer/provider/src/test/java/org/onap/ccsdk/sli/adaptors/messagerouter/consumer/provider/impl/ConsumerFactoryTest.java164
-rwxr-xr-xadaptors/message-router/pom.xml33
-rwxr-xr-xadaptors/message-router/publisher/README.md8
-rwxr-xr-xadaptors/message-router/publisher/api/pom.xml27
-rwxr-xr-xadaptors/message-router/publisher/api/src/main/java/org/onap/ccsdk/sli/adaptors/messagerouter/publisher/api/PublisherApi.java5
-rw-r--r--adaptors/message-router/publisher/installer/pom.xml133
-rw-r--r--adaptors/message-router/publisher/installer/src/assembly/assemble_installer_zip.xml59
-rw-r--r--adaptors/message-router/publisher/installer/src/assembly/assemble_mvnrepo_zip.xml49
-rw-r--r--adaptors/message-router/publisher/installer/src/main/resources/scripts/install-feature.sh39
-rwxr-xr-xadaptors/message-router/publisher/pom.xml20
-rwxr-xr-xadaptors/message-router/publisher/provider/pom.xml39
-rwxr-xr-xadaptors/message-router/publisher/provider/src/main/java/org/onap/ccsdk/sli/adaptors/messagerouter/publisher/provider/impl/PublisherApiImpl.java178
-rwxr-xr-xadaptors/message-router/publisher/provider/src/main/resources/OSGI-INF/blueprint/blueprint.xml14
-rw-r--r--adaptors/message-router/publisher/provider/src/test/java/org/onap/ccsdk/sli/adaptors/messagerouter/publisher/provider/impl/PublisherApiImplTest.java51
-rwxr-xr-xadaptors/message-router/publisher/sample.client/pom.xml39
-rwxr-xr-xadaptors/message-router/publisher/sample.client/src/main/java/org/onap/ccsdk/sli/adaptors/messagerouter/publisher/client/impl/ClientImpl.java58
-rwxr-xr-xadaptors/message-router/publisher/sample.client/src/main/resources/OSGI-INF/blueprint/blueprint.xml16
-rw-r--r--adaptors/message-router/publisher/sample.client/src/test/java/org/onap/ccsdk/sli/adaptors/messagerouter/publisher/client/impl/ClientImplTest.java29
-rwxr-xr-xadaptors/netbox-client/installer/pom.xml146
-rw-r--r--adaptors/netbox-client/installer/src/assembly/assemble_installer_zip.xml53
-rw-r--r--adaptors/netbox-client/installer/src/assembly/assemble_mvnrepo_zip.xml43
-rw-r--r--adaptors/netbox-client/installer/src/main/resources/scripts/install-feature.sh34
-rw-r--r--adaptors/netbox-client/pom.xml40
-rw-r--r--adaptors/netbox-client/provider/pom.xml137
-rw-r--r--adaptors/netbox-client/provider/src/main/java/org/onap/ccsdk/sli/adaptors/netbox/api/IpamException.java27
-rw-r--r--adaptors/netbox-client/provider/src/main/java/org/onap/ccsdk/sli/adaptors/netbox/api/NetboxClient.java59
-rw-r--r--adaptors/netbox-client/provider/src/main/java/org/onap/ccsdk/sli/adaptors/netbox/impl/NetboxClientImpl.java267
-rw-r--r--adaptors/netbox-client/provider/src/main/java/org/onap/ccsdk/sli/adaptors/netbox/impl/NetboxHttpClient.java94
-rw-r--r--adaptors/netbox-client/provider/src/main/java/org/onap/ccsdk/sli/adaptors/netbox/model/IPAddress.java56
-rw-r--r--adaptors/netbox-client/provider/src/main/java/org/onap/ccsdk/sli/adaptors/netbox/model/IPStatus.java5
-rw-r--r--adaptors/netbox-client/provider/src/main/java/org/onap/ccsdk/sli/adaptors/netbox/model/Identifiable.java29
-rw-r--r--adaptors/netbox-client/provider/src/main/java/org/onap/ccsdk/sli/adaptors/netbox/model/Prefix.java20
-rw-r--r--adaptors/netbox-client/provider/src/main/java/org/onap/ccsdk/sli/adaptors/netbox/property/NetboxProperties.java86
-rw-r--r--adaptors/netbox-client/provider/src/main/resources/OSGI-INF/blueprint/netbox-client.xml37
-rw-r--r--adaptors/netbox-client/provider/src/main/resources/netbox.properties19
-rw-r--r--adaptors/netbox-client/provider/src/main/resources/org/opendaylight/blueprint/netbox-client.xml37
-rw-r--r--adaptors/netbox-client/provider/src/test/java/org/onap/ccsdk/sli/adaptors/netbox/impl/NetboxClientImplTest.java313
-rw-r--r--adaptors/netbox-client/provider/src/test/java/org/onap/ccsdk/sli/adaptors/netbox/impl/NetboxHttpClientTest.java89
-rw-r--r--adaptors/netbox-client/provider/src/test/resources/badResponse.json4
-rw-r--r--adaptors/netbox-client/provider/src/test/resources/nextAvailableIpResponse.json13
-rw-r--r--adaptors/releases/0.5.0.yaml5
-rw-r--r--adaptors/releases/0.5.1.yaml5
-rw-r--r--adaptors/releases/0.5.2.yaml5
-rw-r--r--adaptors/releases/0.6.0.yaml5
-rw-r--r--adaptors/releases/0.6.1.yaml5
-rw-r--r--adaptors/releases/0.7.0.yaml5
-rw-r--r--adaptors/releases/0.7.1.yaml5
-rw-r--r--adaptors/releases/1.0.0.yaml5
-rw-r--r--adaptors/releases/1.0.1.yaml5
-rw-r--r--adaptors/releases/1.1.0.yaml5
-rwxr-xr-xadaptors/resource-assignment/.gitignore34
-rwxr-xr-xadaptors/resource-assignment/.sonar/checkstyle.xml1
-rwxr-xr-xadaptors/resource-assignment/.sonar/pmd.xml67
-rwxr-xr-xadaptors/resource-assignment/installer/pom.xml128
-rw-r--r--adaptors/resource-assignment/installer/src/assembly/assemble_installer_zip.xml59
-rw-r--r--adaptors/resource-assignment/installer/src/assembly/assemble_mvnrepo_zip.xml49
-rw-r--r--adaptors/resource-assignment/installer/src/main/resources/scripts/install-feature.sh39
-rwxr-xr-xadaptors/resource-assignment/pom.xml24
-rwxr-xr-xadaptors/resource-assignment/provider/pom.xml91
-rw-r--r--adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/lock/comp/LockHelper.java39
-rw-r--r--adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/lock/comp/LockHelperImpl.java206
-rw-r--r--adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/lock/comp/ResourceLockedException.java43
-rw-r--r--adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/lock/comp/SynchronizedFunction.java58
-rw-r--r--adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/lock/dao/ResourceLockDao.java42
-rw-r--r--adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/lock/dao/ResourceLockDaoImpl.java103
-rw-r--r--adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/lock/data/ResourceLock.java34
-rw-r--r--adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/ra/ResourceAllocator.java583
-rw-r--r--adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/ra/ResourceLockNode.java101
-rw-r--r--adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/ra/alloc/DbAllocationRule.java256
-rw-r--r--adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/ra/comp/AllocationData.java11
-rw-r--r--adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/ra/comp/AllocationRule.java30
-rw-r--r--adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/ra/comp/EndPointAllocator.java39
-rw-r--r--adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/ra/comp/EndPointAllocatorImpl.java368
-rw-r--r--adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/ra/comp/ResourceData.java37
-rw-r--r--adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/ra/comp/ResourceEntity.java32
-rw-r--r--adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/ra/comp/ResourceRequest.java54
-rw-r--r--adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/ra/comp/ResourceResponse.java13
-rw-r--r--adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/ra/comp/ResourceTarget.java31
-rw-r--r--adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/ra/rule/dao/RangeRuleDao.java30
-rw-r--r--adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/ra/rule/dao/RangeRuleDaoImpl.java87
-rw-r--r--adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/ra/rule/dao/ResourceRuleDao.java32
-rw-r--r--adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/ra/rule/dao/ResourceRuleDaoImpl.java110
-rw-r--r--adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/ra/rule/data/RangeRule.java36
-rw-r--r--adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/ra/rule/data/ResourceRule.java39
-rw-r--r--adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/ra/rule/data/ResourceThreshold.java28
-rw-r--r--adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/ra/rule/data/ThresholdStatus.java32
-rw-r--r--adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/comp/AllocationFunction.java433
-rw-r--r--adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/comp/ReleaseFunction.java149
-rw-r--r--adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/comp/ResourceLoader.java39
-rw-r--r--adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/comp/ResourceManager.java44
-rw-r--r--adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/comp/ResourceManagerImpl.java148
-rw-r--r--adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/dao/ResourceDao.java46
-rw-r--r--adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/dao/jdbc/AllocationItem.java37
-rw-r--r--adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/dao/jdbc/AllocationItemJdbcDao.java37
-rw-r--r--adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/dao/jdbc/AllocationItemJdbcDaoImpl.java146
-rw-r--r--adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/dao/jdbc/Resource.java34
-rw-r--r--adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/dao/jdbc/ResourceDaoImpl.java462
-rw-r--r--adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/dao/jdbc/ResourceJdbcDao.java45
-rw-r--r--adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/dao/jdbc/ResourceJdbcDaoImpl.java183
-rw-r--r--adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/dao/jdbc/ResourceLoad.java33
-rw-r--r--adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/dao/jdbc/ResourceLoadJdbcDao.java36
-rw-r--r--adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/dao/jdbc/ResourceLoadJdbcDaoImpl.java112
-rw-r--r--adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/AllocationAction.java26
-rw-r--r--adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/AllocationItem.java36
-rw-r--r--adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/AllocationOutcome.java28
-rw-r--r--adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/AllocationRequest.java37
-rw-r--r--adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/AllocationStatus.java27
-rw-r--r--adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/InitAction.java36
-rw-r--r--adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/LabelAllocationItem.java27
-rw-r--r--adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/LabelAllocationOutcome.java28
-rw-r--r--adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/LabelAllocationRequest.java29
-rw-r--r--adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/LabelResource.java30
-rw-r--r--adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/LimitAllocationItem.java27
-rw-r--r--adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/LimitAllocationOutcome.java29
-rw-r--r--adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/LimitAllocationRequest.java31
-rw-r--r--adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/LimitResource.java27
-rw-r--r--adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/MultiAssetAllocationOutcome.java30
-rw-r--r--adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/MultiAssetAllocationRequest.java32
-rw-r--r--adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/MultiResourceAllocationOutcome.java29
-rw-r--r--adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/MultiResourceAllocationRequest.java30
-rw-r--r--adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/Range.java28
-rw-r--r--adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/RangeAllocationItem.java29
-rw-r--r--adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/RangeAllocationOutcome.java30
-rw-r--r--adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/RangeAllocationRequest.java40
-rw-r--r--adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/RangeResource.java29
-rw-r--r--adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/ReleaseRequest.java46
-rw-r--r--adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/Resource.java32
-rw-r--r--adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/ResourceKey.java50
-rw-r--r--adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/ResourceLoad.java32
-rw-r--r--adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/ResourceType.java26
-rw-r--r--adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/util/LabelUtil.java99
-rw-r--r--adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/util/LimitUtil.java355
-rw-r--r--adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/util/RangeUtil.java160
-rw-r--r--adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/util/ResourceUtil.java57
-rw-r--r--adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/util/db/CachedDataSourceWrap.java156
-rw-r--r--adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/util/db/ConnectionWrap.java338
-rw-r--r--adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/util/db/DataSourceWrap.java98
-rw-r--r--adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/util/expr/ExpressionEvaluator.java271
-rw-r--r--adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/util/speed/SpeedUtil.java57
-rw-r--r--adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/util/str/StrUtil.java306
-rwxr-xr-xadaptors/resource-assignment/provider/src/main/resources/OSGI-INF/blueprint/resource-assignment-blueprint.xml33
-rwxr-xr-xadaptors/resource-assignment/provider/src/main/resources/OSGI-INF/blueprint/resource-assignment.xml129
-rwxr-xr-xadaptors/resource-assignment/provider/src/main/resources/org/opendaylight/blueprint/resource-assignment-blueprint.xml33
-rwxr-xr-xadaptors/resource-assignment/provider/src/main/resources/org/opendaylight/blueprint/resource-assignment.xml129
-rw-r--r--adaptors/resource-assignment/provider/src/test/java/jtest/org/onap/ccsdk/sli/adaptors/ra/DataSetup.java108
-rw-r--r--adaptors/resource-assignment/provider/src/test/java/jtest/org/onap/ccsdk/sli/adaptors/ra/TestGetResource.java222
-rw-r--r--adaptors/resource-assignment/provider/src/test/java/jtest/org/onap/ccsdk/sli/adaptors/ra/TestLockHelper.java61
-rw-r--r--adaptors/resource-assignment/provider/src/test/java/jtest/org/onap/ccsdk/sli/adaptors/ra/TestQueryResource.java157
-rw-r--r--adaptors/resource-assignment/provider/src/test/java/jtest/org/onap/ccsdk/sli/adaptors/ra/TestRelease.java420
-rw-r--r--adaptors/resource-assignment/provider/src/test/java/jtest/org/onap/ccsdk/sli/adaptors/ra/TestReserve.java964
-rw-r--r--adaptors/resource-assignment/provider/src/test/java/jtest/org/onap/ccsdk/sli/adaptors/ra/TestResourceLockNode.java39
-rw-r--r--adaptors/resource-assignment/provider/src/test/java/jtest/org/onap/ccsdk/sli/adaptors/rm/util/LabelUtilTest.java45
-rw-r--r--adaptors/resource-assignment/provider/src/test/java/jtest/util/org/onap/ccsdk/sli/adaptors/ra/TestDb.java37
-rw-r--r--adaptors/resource-assignment/provider/src/test/java/jtest/util/org/onap/ccsdk/sli/adaptors/ra/TestTable.java135
-rw-r--r--adaptors/resource-assignment/provider/src/test/resources/log4j.properties26
-rw-r--r--adaptors/resource-assignment/provider/src/test/resources/sql/data.sql180
-rw-r--r--adaptors/resource-assignment/provider/src/test/resources/sql/schema.sql201
-rw-r--r--adaptors/resource-assignment/provider/src/test/resources/test-context.xml153
-rw-r--r--adaptors/saltstack-adapter/.pydevproject5
-rw-r--r--adaptors/saltstack-adapter/README.md137
-rw-r--r--adaptors/saltstack-adapter/pom.xml199
-rw-r--r--adaptors/saltstack-adapter/saltstack-adapter-installer/pom.xml165
-rw-r--r--adaptors/saltstack-adapter/saltstack-adapter-installer/src/assembly/assemble_installer_zip.xml61
-rw-r--r--adaptors/saltstack-adapter/saltstack-adapter-installer/src/assembly/assemble_mvnrepo_zip.xml50
-rw-r--r--adaptors/saltstack-adapter/saltstack-adapter-installer/src/main/resources/scripts/install-feature.sh42
-rw-r--r--adaptors/saltstack-adapter/saltstack-adapter-provider/.gitignore25
-rw-r--r--adaptors/saltstack-adapter/saltstack-adapter-provider/pom.xml120
-rw-r--r--adaptors/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/SaltstackAdapter.java59
-rwxr-xr-xadaptors/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/SaltstackAdapterPropertiesProvider.java32
-rw-r--r--adaptors/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/impl/ConnectionBuilder.java172
-rw-r--r--adaptors/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/impl/SaltstackAdapterImpl.java446
-rwxr-xr-xadaptors/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/impl/SaltstackAdapterPropertiesProviderImpl.java192
-rw-r--r--adaptors/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/impl/SshConnection.java217
-rw-r--r--adaptors/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/Constants.java93
-rw-r--r--adaptors/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/JsonParser.java89
-rw-r--r--adaptors/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/SaltstackMessageParser.java412
-rw-r--r--adaptors/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/SaltstackResult.java102
-rw-r--r--adaptors/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/SaltstackResultCodes.java100
-rw-r--r--adaptors/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/SaltstackServerEmulator.java93
-rw-r--r--adaptors/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/SshException.java37
-rwxr-xr-xadaptors/saltstack-adapter/saltstack-adapter-provider/src/main/resources/OSGI-INF/blueprint/saltstack-adapter-blueprint.xml42
-rwxr-xr-xadaptors/saltstack-adapter/saltstack-adapter-provider/src/main/resources/org/opendaylight/blueprint/saltstack-adapter-blueprint.xml42
-rw-r--r--adaptors/saltstack-adapter/saltstack-adapter-provider/src/main/resources/saltstack-adapter.properties43
-rw-r--r--adaptors/saltstack-adapter/saltstack-adapter-provider/src/test/java/org/onap/ccsdk/adapter/impl/TestConnectionBuilder.java184
-rw-r--r--adaptors/saltstack-adapter/saltstack-adapter-provider/src/test/java/org/onap/ccsdk/adapter/impl/TestSaltstackAdapterImpl.java1051
-rw-r--r--adaptors/saltstack-adapter/saltstack-adapter-provider/src/test/java/org/onap/ccsdk/adapter/impl/TestSaltstackAdapterPropertiesProviderImpl.java310
-rw-r--r--adaptors/saltstack-adapter/saltstack-adapter-provider/src/test/java/org/onap/ccsdk/adapter/model/TestJsonParser.java76
-rw-r--r--adaptors/saltstack-adapter/saltstack-adapter-provider/src/test/resources/config.sls2
-rw-r--r--adaptors/saltstack-adapter/saltstack-adapter-provider/src/test/resources/org/onap/ccsdk/default.properties102
-rw-r--r--adaptors/saltstack-adapter/saltstack-adapter-provider/src/test/resources/test30
-rw-r--r--adaptors/saltstack-adapter/saltstack-adapter-provider/src/test/resources/test-invalid.json29
-rw-r--r--adaptors/saltstack-adapter/saltstack-adapter-provider/src/test/resources/test-sls.json35
-rw-r--r--adaptors/saltstack-adapter/saltstack-adapter-provider/src/test/resources/test.json30
-rw-r--r--adaptors/saltstack-adapter/saltstack-adapter-provider/src/test/resources/test.sls30
-rw-r--r--adaptors/saltstack-adapter/saltstack-adapter-provider/src/test/resources/test.txt30
-rw-r--r--adaptors/saltstack-adapter/saltstack-directed-graphs-sample/reqExecCommand/APPC_saltstack-adapter-1.0-exe-nonSLS.json203
-rw-r--r--adaptors/saltstack-adapter/saltstack-directed-graphs-sample/reqExecCommand/APPC_saltstack-adapter-1.0-exe-nonSLS.xml50
-rw-r--r--adaptors/saltstack-adapter/saltstack-directed-graphs-sample/reqExecCommand/APPC_saltstack-adapter-1.0-exec-SLSFile.json350
-rw-r--r--adaptors/saltstack-adapter/saltstack-directed-graphs-sample/reqExecCommand/APPC_saltstack-adapter-1.0-exec-SLSFile.xml112
-rw-r--r--adaptors/saltstack-adapter/saltstack-directed-graphs-sample/reqExecCommand/APPC_saltstack-adapter-1.0-exec-multi-sls.json399
-rw-r--r--adaptors/saltstack-adapter/saltstack-directed-graphs-sample/reqExecCommand/APPC_saltstack-adapter-1.0-exec-multi-sls.xml129
-rw-r--r--adaptors/saltstack-adapter/saltstack-directed-graphs-sample/reqExecCommand/APPC_saltstack-adapter-1.0-exec-single-SLSComm.json203
-rw-r--r--adaptors/saltstack-adapter/saltstack-directed-graphs-sample/reqExecCommand/APPC_saltstack-adapter-1.0-exec-single-SLSComm.xml51
-rw-r--r--adaptors/saltstack-adapter/saltstack-directed-graphs-sample/reqExecSLS/APPC_saltstack-adapter-1.0 IDEAL.json214
-rw-r--r--adaptors/saltstack-adapter/saltstack-directed-graphs-sample/reqExecSLS/APPC_saltstack-adapter-1.0 IDEAL.xml52
-rw-r--r--adaptors/saltstack-adapter/saltstack-directed-graphs-sample/reqExecSLS/APPC_saltstack-adapter-1.0-exec-SLS-applyTo.json372
-rw-r--r--adaptors/saltstack-adapter/saltstack-directed-graphs-sample/reqExecSLS/APPC_saltstack-adapter-1.0-exec-SLS-applyTo.xml112
-rw-r--r--adaptors/saltstack-adapter/saltstack-directed-graphs-sample/reqExecSLSFile/APPC_saltstack-adapter-1.0-SLSFILE.json214
-rw-r--r--adaptors/saltstack-adapter/saltstack-directed-graphs-sample/reqExecSLSFile/APPC_saltstack-adapter-1.0-SLSFILE.xml48
-rw-r--r--adaptors/saltstack-adapter/saltstack-directed-graphs-sample/reqExecSLSFile/APPC_saltstack-adapter-1.0-exec-SLSFile-applyTo.json372
-rw-r--r--adaptors/saltstack-adapter/saltstack-directed-graphs-sample/reqExecSLSFile/APPC_saltstack-adapter-1.0-exec-SLSFile-applyTo.xml112
-rwxr-xr-xadaptors/sql-resource/.gitignore34
-rwxr-xr-xadaptors/sql-resource/installer/pom.xml128
-rw-r--r--adaptors/sql-resource/installer/src/assembly/assemble_installer_zip.xml59
-rw-r--r--adaptors/sql-resource/installer/src/assembly/assemble_mvnrepo_zip.xml49
-rw-r--r--adaptors/sql-resource/installer/src/main/resources/scripts/install-feature.sh39
-rwxr-xr-xadaptors/sql-resource/pom.xml24
-rwxr-xr-xadaptors/sql-resource/provider/pom.xml83
-rwxr-xr-xadaptors/sql-resource/provider/src/main/java/org/onap/ccsdk/sli/adaptors/resource/sql/SqlResource.java551
-rwxr-xr-xadaptors/sql-resource/provider/src/main/java/org/onap/ccsdk/sli/adaptors/resource/sql/SqlResourcePropertiesProvider.java28
-rwxr-xr-xadaptors/sql-resource/provider/src/main/java/org/onap/ccsdk/sli/adaptors/resource/sql/SqlResourcePropertiesProviderImpl.java186
-rwxr-xr-xadaptors/sql-resource/provider/src/main/resources/OSGI-INF/blueprint/sql-resource-blueprint.xml41
-rwxr-xr-xadaptors/sql-resource/provider/src/main/resources/org/opendaylight/blueprint/sql-resource-blueprint.xml41
-rwxr-xr-xadaptors/sql-resource/provider/src/main/resources/sql-resource.properties23
-rw-r--r--adaptors/sql-resource/provider/src/main/resources/svclogic.properties34
-rwxr-xr-xadaptors/sql-resource/provider/src/test/java/org/onap/ccsdk/sli/adaptors/resource/sql/ITCaseSqlResource.java231
-rwxr-xr-xadaptors/sql-resource/provider/src/test/java/org/onap/ccsdk/sli/adaptors/resource/sql/SqlResourceProviderTest.java38
-rwxr-xr-xadaptors/sql-resource/provider/src/test/resources/delete.tests2
-rwxr-xr-xadaptors/sql-resource/provider/src/test/resources/query.tests5
-rwxr-xr-xadaptors/sql-resource/provider/src/test/resources/save.tests13
-rw-r--r--adaptors/sql-resource/provider/src/test/resources/simplelogger.properties22
-rwxr-xr-xadaptors/sql-resource/provider/src/test/resources/sql-resource.properties23
-rw-r--r--adaptors/sql-resource/provider/src/test/resources/svclogic.properties35
-rw-r--r--core/LICENSE.txt22
-rw-r--r--core/README.md7
-rwxr-xr-xcore/artifacts/pom.xml152
-rwxr-xr-xcore/dblib/.gitignore34
-rwxr-xr-xcore/dblib/README.md6
-rwxr-xr-xcore/dblib/installer/pom.xml128
-rwxr-xr-xcore/dblib/installer/src/assembly/assemble_installer_zip.xml39
-rwxr-xr-xcore/dblib/installer/src/assembly/assemble_mvnrepo_zip.xml29
-rw-r--r--core/dblib/installer/src/main/resources/scripts/install-feature.sh18
-rwxr-xr-xcore/dblib/pom.xml27
-rwxr-xr-xcore/dblib/provider/pom.xml64
-rwxr-xr-xcore/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/CachedDataSource.java593
-rw-r--r--core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/CachedDataSourceFactory.java46
-rw-r--r--core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/DBConfigException.java47
-rwxr-xr-xcore/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/DBLIBResourceProvider.java165
-rw-r--r--core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/DBLibConnection.java387
-rw-r--r--core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/DBLibException.java39
-rwxr-xr-xcore/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/DBResourceManager.java983
-rw-r--r--core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/DBResourceObserver.java27
-rw-r--r--core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/DataAccessor.java34
-rw-r--r--core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/DataSourceComparator.java33
-rw-r--r--core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/DbLibService.java50
-rw-r--r--core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/DblibConfigurationException.java45
-rw-r--r--core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/NoAvailableConnectionsException.java36
-rwxr-xr-xcore/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/TerminatingCachedDataSource.java59
-rwxr-xr-xcore/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/config/BaseDBConfiguration.java258
-rw-r--r--core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/config/DbConfigPool.java63
-rw-r--r--core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/config/JDBCConfiguration.java31
-rwxr-xr-xcore/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/config/TerminatingConfiguration.java33
-rw-r--r--core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/factory/DBConfigFactory.java105
-rwxr-xr-xcore/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/jdbc/JdbcDBCachedDataSource.java201
-rw-r--r--core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/pm/PollingWorker.java259
-rw-r--r--core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/pm/SQLExecutionMonitor.java222
-rw-r--r--core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/pm/SQLExecutionMonitorObserver.java37
-rwxr-xr-xcore/dblib/provider/src/main/resources/OSGI-INF/blueprint/dblib-blueprint.xml18
-rwxr-xr-xcore/dblib/provider/src/main/resources/dblib.properties14
-rwxr-xr-xcore/dblib/provider/src/main/resources/org/opendaylight/blueprint/dblib-blueprint.xml24
-rw-r--r--core/dblib/provider/src/test/java/org/onap/ccsdk/sli/core/dblib/CachedDataSourceTest.java121
-rw-r--r--core/dblib/provider/src/test/java/org/onap/ccsdk/sli/core/dblib/DBConfigExceptionTest.java19
-rw-r--r--core/dblib/provider/src/test/java/org/onap/ccsdk/sli/core/dblib/DblibConfigurationExceptionTest.java24
-rw-r--r--core/dblib/provider/src/test/java/org/onap/ccsdk/sli/core/dblib/NoAvailableConnectionsExceptionTest.java16
-rw-r--r--core/dblib/provider/src/test/java/org/onap/ccsdk/sli/core/dblib/TerminatingCachedDataSourceTest.java94
-rw-r--r--core/dblib/provider/src/test/java/org/onap/ccsdk/sli/core/dblib/TestDBResourceManager.java70
-rw-r--r--core/dblib/provider/src/test/java/org/onap/ccsdk/sli/core/dblib/TestDBResourceManager2.java95
-rw-r--r--core/dblib/provider/src/test/resources/dblib.properties38
-rw-r--r--core/features/ccsdk-dblib/pom.xml63
-rw-r--r--core/features/ccsdk-dblib/src/main/feature/feature.xml13
-rw-r--r--core/features/ccsdk-filters/pom.xml45
-rw-r--r--core/features/ccsdk-sli-core-all/pom.xml82
-rw-r--r--core/features/ccsdk-sli/pom.xml54
-rw-r--r--core/features/ccsdk-sliPluginUtils/pom.xml36
-rw-r--r--core/features/ccsdk-sliapi/pom.xml36
-rw-r--r--core/features/ccsdk-slicore-utils/pom.xml29
-rw-r--r--core/features/features-sli-core/pom.xml29
-rwxr-xr-xcore/features/installer/pom.xml214
-rwxr-xr-xcore/features/installer/src/assembly/assemble_installer_zip.xml39
-rwxr-xr-xcore/features/installer/src/assembly/assemble_mvnrepo_zip.xml29
-rw-r--r--core/features/installer/src/main/resources/scripts/install-feature.sh18
-rwxr-xr-xcore/features/pom.xml30
-rwxr-xr-xcore/filters/.gitignore34
-rwxr-xr-xcore/filters/.sonar/checkstyle.xml1
-rwxr-xr-xcore/filters/.sonar/pmd.xml67
-rwxr-xr-xcore/filters/README14
-rwxr-xr-xcore/filters/installer/pom.xml126
-rw-r--r--core/filters/installer/src/assembly/assemble_installer_zip.xml61
-rw-r--r--core/filters/installer/src/assembly/assemble_mvnrepo_zip.xml49
-rw-r--r--core/filters/installer/src/main/resources/scripts/install-feature.sh39
-rw-r--r--core/filters/pom.xml27
-rwxr-xr-xcore/filters/provider/pom.xml29
-rw-r--r--core/filters/provider/src/main/java/org/onap/ccsdk/sli/core/filters/ControllerAuditLogFilter.java40
-rw-r--r--core/filters/provider/src/main/java/org/onap/ccsdk/sli/core/filters/ControllerPayloadLoggingFilter.java7
-rw-r--r--core/filters/provider/src/test/java/org/onap/ccsdk/sli/core/filters/ControllerAuditLogFilterTest.java23
-rw-r--r--core/releases/0.5.0.yaml5
-rw-r--r--core/releases/0.5.1.yaml5
-rw-r--r--core/releases/0.5.2.yaml5
-rw-r--r--core/releases/0.6.0.yaml5
-rw-r--r--core/releases/0.6.1.yaml5
-rw-r--r--core/releases/0.7.0.yaml5
-rw-r--r--core/releases/0.7.1.yaml5
-rw-r--r--core/releases/1.0.0.yaml5
-rw-r--r--core/releases/1.0.1.yaml5
-rw-r--r--core/releases/1.1.0.yaml5
-rwxr-xr-xcore/sli/.gitignore38
-rwxr-xr-xcore/sli/common/pom.xml129
-rwxr-xr-xcore/sli/common/src/main/antlr4/org/onap/ccsdk/sli/core/sli/ExprGrammar.g467
-rw-r--r--core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/ActivationEntry.java41
-rw-r--r--core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/BreakNodeException.java46
-rw-r--r--core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/CheckSumHelper.java51
-rw-r--r--core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/CommonConstants.java38
-rw-r--r--core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/ConfigurationException.java45
-rw-r--r--core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/DuplicateValueException.java45
-rw-r--r--core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/ErrorLogger.java100
-rwxr-xr-xcore/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/ExitNodeException.java46
-rw-r--r--core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/MessageWriter.java281
-rwxr-xr-xcore/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/MetricLogger.java165
-rw-r--r--core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SecurePrinter.java123
-rw-r--r--core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicAdaptor.java42
-rw-r--r--core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicAtom.java170
-rw-r--r--core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicBinaryExpression.java151
-rw-r--r--core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicConstants.java7
-rw-r--r--core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicContext.java438
-rw-r--r--core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicCrawler.java92
-rw-r--r--core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicDblibStore.java332
-rw-r--r--core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicException.java46
-rw-r--r--core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicExprListener.java271
-rw-r--r--core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicExprParserErrorListener.java44
-rw-r--r--core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicExpression.java52
-rw-r--r--core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicExpressionFactory.java75
-rw-r--r--core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicFunctionCall.java80
-rw-r--r--core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicGraph.java199
-rw-r--r--core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicJavaPlugin.java30
-rw-r--r--core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicJdbcStore.java574
-rw-r--r--core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicLoader.java178
-rw-r--r--core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicNode.java457
-rw-r--r--core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicParser.java615
-rw-r--r--core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicParserException.java43
-rw-r--r--core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicRecorder.java30
-rw-r--r--core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicResource.java52
-rw-r--r--core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicStore.java36
-rw-r--r--core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicStoreFactory.java100
-rw-r--r--core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicVariableTerm.java77
-rwxr-xr-xcore/sli/common/src/main/resources/svclogic.xsd339
-rw-r--r--core/sli/common/src/test/java/org/onap/ccsdk/sli/core/sli/ConfigurationExceptionTestt.java30
-rw-r--r--core/sli/common/src/test/java/org/onap/ccsdk/sli/core/sli/DuplicatevalueExceptionTest.java28
-rw-r--r--core/sli/common/src/test/java/org/onap/ccsdk/sli/core/sli/ErrorLoggerTest.java56
-rw-r--r--core/sli/common/src/test/java/org/onap/ccsdk/sli/core/sli/ExitNodeExceptionTest.java27
-rw-r--r--core/sli/common/src/test/java/org/onap/ccsdk/sli/core/sli/ITCaseSvcLogicParser.java284
-rw-r--r--core/sli/common/src/test/java/org/onap/ccsdk/sli/core/sli/SvcLogicContextTest.java400
-rw-r--r--core/sli/common/src/test/java/org/onap/ccsdk/sli/core/sli/SvcLogicExpressionParserTest.java66
-rw-r--r--core/sli/common/src/test/java/org/onap/ccsdk/sli/core/sli/SvcLogicParserExceptionTest.java34
-rwxr-xr-xcore/sli/common/src/test/java/org/onap/ccsdk/sli/core/sli/TestMetricLogger.java85
-rw-r--r--core/sli/common/src/test/java/org/onap/ccsdk/sli/core/sli/TestSvcLogicLoader.java38
-rw-r--r--core/sli/common/src/test/resources/2dArray.json4
-rw-r--r--core/sli/common/src/test/resources/3dArray.json4
-rw-r--r--core/sli/common/src/test/resources/ArrayMenu.json41
-rw-r--r--core/sli/common/src/test/resources/EmbeddedEscapedJson.json16
-rw-r--r--core/sli/common/src/test/resources/EscapedJson.json1
-rw-r--r--core/sli/common/src/test/resources/EvcActivateSvcLogic_v100.xml70
-rw-r--r--core/sli/common/src/test/resources/EvcPortSvcLogic_v100.xml263
-rw-r--r--core/sli/common/src/test/resources/JsonObject.json5
-rw-r--r--core/sli/common/src/test/resources/ObjectMenu.json43
-rw-r--r--core/sli/common/src/test/resources/QuotedValues.json43
-rw-r--r--core/sli/common/src/test/resources/ReleasePortSvcLogic_v101.xml89
-rw-r--r--core/sli/common/src/test/resources/Widget.json27
-rw-r--r--core/sli/common/src/test/resources/bad_neutron_logic_v11.xml61
-rwxr-xr-xcore/sli/common/src/test/resources/dblib.properties14
-rwxr-xr-xcore/sli/common/src/test/resources/expression.tests19
-rw-r--r--core/sli/common/src/test/resources/graphs/sliapi/graph.versions1
-rw-r--r--core/sli/common/src/test/resources/graphs/sliapi/sli_healthcheck.xml27
-rw-r--r--core/sli/common/src/test/resources/l3sdn_logic_v10.xml208
-rw-r--r--core/sli/common/src/test/resources/log4j2.properties39
-rw-r--r--core/sli/common/src/test/resources/mergetest.xml54
-rw-r--r--core/sli/common/src/test/resources/neutron_logic_v10.xml56
-rw-r--r--core/sli/common/src/test/resources/nonsense.xml24
-rwxr-xr-xcore/sli/common/src/test/resources/parser-bad.tests3
-rwxr-xr-xcore/sli/common/src/test/resources/parser-good.tests3
-rw-r--r--core/sli/common/src/test/resources/simplelogger.properties24
-rw-r--r--core/sli/common/src/test/resources/svclogic.properties27
-rw-r--r--core/sli/common/src/test/resources/svclogic.sh32
-rwxr-xr-xcore/sli/installer/pom.xml144
-rw-r--r--core/sli/installer/src/assembly/assemble_installer_zip.xml59
-rw-r--r--core/sli/installer/src/assembly/assemble_mvnrepo_zip.xml42
-rw-r--r--core/sli/installer/src/main/resources/scripts/install-feature.sh39
-rwxr-xr-xcore/sli/model/pom.xml27
-rwxr-xr-xcore/sli/model/src/main/yang/sliapi.yang123
-rwxr-xr-xcore/sli/model/src/main/yang/test-model@2019-07-23.yang210
-rwxr-xr-xcore/sli/pom.xml30
-rw-r--r--core/sli/provider-base/pom.xml63
-rw-r--r--core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/AbstractSvcLogicNodeExecutor.java121
-rw-r--r--core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/BlockNodeExecutor.java71
-rw-r--r--core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/BreakNodeExecutor.java42
-rw-r--r--core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/CallNodeExecutor.java170
-rw-r--r--core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/ConfigureNodeExecutor.java242
-rw-r--r--core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/DeleteNodeExecutor.java75
-rw-r--r--core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/ExecuteNodeExecutor.java127
-rw-r--r--core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/ExistsNodeExecutor.java76
-rw-r--r--core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/ExitNodeExecutor.java42
-rw-r--r--core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/ForNodeExecutor.java110
-rw-r--r--core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/GetResourceNodeExecutor.java100
-rw-r--r--core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/HashMapResolver.java52
-rw-r--r--core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/InMemorySvcLogicStore.java66
-rw-r--r--core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/IsAvailableNodeExecutor.java72
-rw-r--r--core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/NotifyNodeExecutor.java75
-rw-r--r--core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/RecordNodeExecutor.java65
-rw-r--r--core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/ReleaseNodeExecutor.java74
-rw-r--r--core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/ReserveNodeExecutor.java88
-rw-r--r--core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/ReturnNodeExecutor.java77
-rw-r--r--core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/SaveNodeExecutor.java94
-rw-r--r--core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/SetNodeExecutor.java179
-rw-r--r--core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/SvcLogicExpressionResolver.java603
-rw-r--r--core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/SvcLogicPropertiesProvider.java28
-rw-r--r--core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/SvcLogicResolver.java17
-rw-r--r--core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/SvcLogicServiceBase.java80
-rw-r--r--core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/SvcLogicServiceImplBase.java180
-rw-r--r--core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/SwitchNodeExecutor.java63
-rw-r--r--core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/UpdateNodeExecutor.java89
-rw-r--r--core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/WhileNodeExecutor.java75
-rw-r--r--core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/recording/FileRecorder.java113
-rw-r--r--core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/recording/Slf4jRecorder.java160
-rw-r--r--core/sli/provider-base/src/test/java/org/onap/ccsdk/sli/core/sli/provider/base/BadPlugin.java56
-rw-r--r--core/sli/provider-base/src/test/java/org/onap/ccsdk/sli/core/sli/provider/base/ExecuteNodeExecutorTest.java64
-rw-r--r--core/sli/provider-base/src/test/java/org/onap/ccsdk/sli/core/sli/provider/base/GraphTests.java61
-rw-r--r--core/sli/provider-base/src/test/java/org/onap/ccsdk/sli/core/sli/provider/base/HashMapResolverTest.java51
-rw-r--r--core/sli/provider-base/src/test/java/org/onap/ccsdk/sli/core/sli/provider/base/InMemorySvcLogicStoreTest.java35
-rw-r--r--core/sli/provider-base/src/test/java/org/onap/ccsdk/sli/core/sli/provider/base/LunchSelectorPlugin.java78
-rw-r--r--core/sli/provider-base/src/test/java/org/onap/ccsdk/sli/core/sli/provider/base/PluginTest.java113
-rw-r--r--core/sli/provider-base/src/test/java/org/onap/ccsdk/sli/core/sli/provider/base/SetNodeExecutorTest.java220
-rw-r--r--core/sli/provider-base/src/test/java/org/onap/ccsdk/sli/core/sli/provider/base/SvcLogicExpressionResolverTest.java280
-rw-r--r--core/sli/provider-base/src/test/java/org/onap/ccsdk/sli/core/sli/recording/TestFileRecorder.java49
-rw-r--r--core/sli/provider-base/src/test/java/org/onap/ccsdk/sli/core/sli/recording/TestSlf4jRecorder.java33
-rw-r--r--core/sli/provider-base/src/test/resources/breakGraph.xml26
-rw-r--r--core/sli/provider-base/src/test/resources/clearMultipleArrayValues.xml23
-rw-r--r--core/sli/provider-base/src/test/resources/clearNestedSubArrayValues.xml27
-rw-r--r--core/sli/provider-base/src/test/resources/clearSingleArrayValues.xml23
-rw-r--r--core/sli/provider-base/src/test/resources/clearSingleSubArrayValues.xml27
-rw-r--r--core/sli/provider-base/src/test/resources/clearSubArrayValues.xml24
-rw-r--r--core/sli/provider-base/src/test/resources/clearValues.xml22
-rw-r--r--core/sli/provider-base/src/test/resources/copyValues.xml16
-rw-r--r--core/sli/provider-base/src/test/resources/expression.tests24
-rwxr-xr-xcore/sli/provider-base/src/test/resources/expressions.xml55
-rw-r--r--core/sli/provider-base/src/test/resources/simplelogger.properties22
-rwxr-xr-xcore/sli/provider/pom.xml144
-rwxr-xr-xcore/sli/provider/src/main/java/org/onap/ccsdk/sli/core/sli/provider/MdsalHelper.java1274
-rw-r--r--core/sli/provider/src/main/java/org/onap/ccsdk/sli/core/sli/provider/PrintYangToProp.java1355
-rw-r--r--core/sli/provider/src/main/java/org/onap/ccsdk/sli/core/sli/provider/SvcLogicClassResolver.java98
-rw-r--r--core/sli/provider/src/main/java/org/onap/ccsdk/sli/core/sli/provider/SvcLogicPropertiesProviderImpl.java189
-rw-r--r--core/sli/provider/src/main/java/org/onap/ccsdk/sli/core/sli/provider/SvcLogicService.java52
-rwxr-xr-xcore/sli/provider/src/main/java/org/onap/ccsdk/sli/core/sli/provider/SvcLogicServiceImpl.java90
-rw-r--r--core/sli/provider/src/main/resources/OSGI-INF/blueprint/sli-blueprint.xml36
-rw-r--r--core/sli/provider/src/main/resources/org/opendaylight/blueprint/sli-blueprint.xml36
-rw-r--r--core/sli/provider/src/test/java/org/onap/ccsdk/sli/core/sli/provider/ITCaseSvcLogicGraphExecutor.java265
-rwxr-xr-xcore/sli/provider/src/test/java/org/onap/ccsdk/sli/core/sli/provider/MdsalHelperTest.java763
-rw-r--r--core/sli/provider/src/test/java/org/onap/ccsdk/sli/core/sli/provider/MdsalHelperTesterUtil.java37
-rw-r--r--core/sli/provider/src/test/java/org/onap/ccsdk/sli/core/sli/provider/PrintYangToPropTest.java142
-rw-r--r--core/sli/provider/src/test/java/org/opendaylight/yang/gen/v1/test/CosModelType.java51
-rwxr-xr-xcore/sli/provider/src/test/java/org/opendaylight/yang/gen/v1/test/TestObject.java17
-rwxr-xr-xcore/sli/provider/src/test/java/org/opendaylight/yang/gen/v1/test/TestObjectBuilder.java134
-rw-r--r--core/sli/provider/src/test/java/org/opendaylight/yang/gen/v1/test/WrapperObj.java10
-rw-r--r--core/sli/provider/src/test/resources/EnumerationMapping.properties1
-rwxr-xr-xcore/sli/provider/src/test/resources/executor.tests8
-rw-r--r--core/sli/provider/src/test/resources/l3sdn.properties66
-rw-r--r--core/sli/provider/src/test/resources/l3sdn_logic_v10.xml227
-rwxr-xr-xcore/sli/provider/src/test/resources/l3vpnyang/ietf-l3vpn-svc-part@2017-09-21.yang68
-rw-r--r--core/sli/provider/src/test/resources/simplelogger.properties22
-rw-r--r--core/sli/provider/src/test/resources/svclogic.properties27
-rwxr-xr-xcore/sliPluginUtils/.gitignore34
-rwxr-xr-xcore/sliPluginUtils/.sonar/checkstyle.xml1
-rwxr-xr-xcore/sliPluginUtils/.sonar/pmd.xml67
-rwxr-xr-xcore/sliPluginUtils/installer/pom.xml147
-rw-r--r--core/sliPluginUtils/installer/src/assembly/assemble_installer_zip.xml59
-rw-r--r--core/sliPluginUtils/installer/src/assembly/assemble_mvnrepo_zip.xml49
-rw-r--r--core/sliPluginUtils/installer/src/main/resources/scripts/install-feature.sh39
-rwxr-xr-xcore/sliPluginUtils/pom.xml24
-rwxr-xr-xcore/sliPluginUtils/provider/pom.xml72
-rw-r--r--core/sliPluginUtils/provider/src/main/java/org/onap/ccsdk/sli/core/slipluginutils/SliPluginUtils.java1178
-rw-r--r--core/sliPluginUtils/provider/src/main/java/org/onap/ccsdk/sli/core/slipluginutils/SliStringUtils.java559
-rw-r--r--core/sliPluginUtils/provider/src/main/java/org/onap/ccsdk/sli/core/slipluginutils/SvcLogicContextList.java210
-rw-r--r--core/sliPluginUtils/provider/src/main/java/org/onap/ccsdk/sli/core/slipluginutils/SvcLogicContextObject.java28
-rw-r--r--core/sliPluginUtils/provider/src/main/java/org/onap/ccsdk/sli/core/slipluginutils/commondatastructures/YesNo.java51
-rw-r--r--core/sliPluginUtils/provider/src/main/java/org/onap/ccsdk/sli/core/slipluginutils/commondatastructures/package-info.java28
-rw-r--r--core/sliPluginUtils/provider/src/main/resources/OSGI-INF/blueprint/slipluginutils-blueprint.xml13
-rw-r--r--core/sliPluginUtils/provider/src/main/resources/org/opendaylight/blueprint/slipluginutils-blueprint.xml13
-rw-r--r--core/sliPluginUtils/provider/src/test/java/org/onap/ccsdk/sli/core/slipluginutils/SliPluginUtils_StaticFunctionsTest.java591
-rw-r--r--core/sliPluginUtils/provider/src/test/java/org/onap/ccsdk/sli/core/slipluginutils/SliPluginUtils_checkParametersTest.java117
-rw-r--r--core/sliPluginUtils/provider/src/test/java/org/onap/ccsdk/sli/core/slipluginutils/SliPluginUtils_ctxSortList.java149
-rw-r--r--core/sliPluginUtils/provider/src/test/java/org/onap/ccsdk/sli/core/slipluginutils/SliPluginUtils_ctxSortListTest.java97
-rw-r--r--core/sliPluginUtils/provider/src/test/java/org/onap/ccsdk/sli/core/slipluginutils/SliStringUtilsTest.java398
-rw-r--r--core/sliPluginUtils/provider/src/test/java/org/onap/ccsdk/sli/core/slipluginutils/SvcLogicContextListTest.java307
-rw-r--r--core/sliPluginUtils/provider/src/test/resources/2dArray.json4
-rw-r--r--core/sliPluginUtils/provider/src/test/resources/3dArray.json4
-rw-r--r--core/sliPluginUtils/provider/src/test/resources/ArrayMenu.json41
-rw-r--r--core/sliPluginUtils/provider/src/test/resources/EmbeddedEscapedJson.json16
-rw-r--r--core/sliPluginUtils/provider/src/test/resources/EscapedJson.json1
-rw-r--r--core/sliPluginUtils/provider/src/test/resources/JsonObject.json5
-rw-r--r--core/sliPluginUtils/provider/src/test/resources/ObjectMenu.json43
-rw-r--r--core/sliPluginUtils/provider/src/test/resources/Widget.json27
-rwxr-xr-xcore/sliapi/.gitignore38
-rwxr-xr-xcore/sliapi/README.txt35
-rwxr-xr-xcore/sliapi/installer/pom.xml164
-rw-r--r--core/sliapi/installer/src/assembly/assemble_installer_zip.xml59
-rw-r--r--core/sliapi/installer/src/assembly/assemble_mvnrepo_zip.xml49
-rw-r--r--core/sliapi/installer/src/main/resources/scripts/install-feature.sh39
-rwxr-xr-xcore/sliapi/model/pom.xml24
-rw-r--r--core/sliapi/model/src/main/resources/sli-api.20161110.yaml254
-rw-r--r--core/sliapi/model/swagger/pom.xml222
-rw-r--r--core/sliapi/model/swagger/src/main/json/sliapi.json1
-rw-r--r--core/sliapi/model/swagger/src/main/yaml/sliapi.yaml378
-rwxr-xr-xcore/sliapi/model/yang/pom.xml27
-rw-r--r--core/sliapi/model/yang/src/main/resources/sli-api.20161110.json554
-rw-r--r--core/sliapi/model/yang/src/main/resources/sli-api.20161110.yaml254
-rwxr-xr-xcore/sliapi/model/yang/src/main/yang/sliapi.yang117
-rwxr-xr-xcore/sliapi/pom.xml28
-rwxr-xr-xcore/sliapi/provider/pom.xml112
-rw-r--r--core/sliapi/provider/src/main/java/org/onap/ccsdk/sli/core/sliapi/SliapiHelper.java40
-rw-r--r--core/sliapi/provider/src/main/java/org/onap/ccsdk/sli/core/sliapi/SliapiProvider.java676
-rw-r--r--core/sliapi/provider/src/main/resources/OSGI-INF/blueprint/sliapi-blueprint.xml28
-rw-r--r--core/sliapi/provider/src/main/resources/org/opendaylight/blueprint/sliapi-blueprint.xml28
-rw-r--r--core/sliapi/provider/src/test/java/org/onap/ccsdk/sli/core/sliapi/SliapiHelperTest.java35
-rw-r--r--core/sliapi/provider/src/test/java/org/onap/ccsdk/sli/core/sliapi/TestSliapiProvider.java209
-rw-r--r--core/sliapi/provider/src/test/resources/simplelogger.properties23
-rw-r--r--core/sliapi/provider/src/test/resources/sli_healthcheck.xml27
-rw-r--r--core/sliapi/provider/src/test/resources/svclogic.properties27
-rw-r--r--core/src/site/apt/nodes.apt953
-rw-r--r--core/src/site/site.xml31
-rwxr-xr-xcore/utils/installer/pom.xml129
-rwxr-xr-xcore/utils/installer/src/assembly/assemble_installer_zip.xml39
-rwxr-xr-xcore/utils/installer/src/assembly/assemble_mvnrepo_zip.xml29
-rw-r--r--core/utils/installer/src/main/resources/scripts/install-feature.sh18
-rwxr-xr-xcore/utils/pom.xml27
-rw-r--r--core/utils/provider/pom.xml49
-rw-r--r--core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/DefaultFileResolver.java61
-rwxr-xr-xcore/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/EnvVarFileResolver.java76
-rwxr-xr-xcore/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/JREFileResolver.java111
-rw-r--r--core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/KarafRootFileResolver.java63
-rw-r--r--core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/PathValidator.java17
-rw-r--r--core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/PropertiesFileResolver.java45
-rwxr-xr-xcore/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/common/BundleContextFileResolver.java82
-rwxr-xr-xcore/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/common/CoreDefaultFileResolver.java41
-rwxr-xr-xcore/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/common/SdncConfigEnvVarFileResolver.java38
-rwxr-xr-xcore/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/dblib/DblibDefaultFileResolver.java25
-rw-r--r--core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/dblib/DblibEnvVarFileResolver.java23
-rw-r--r--core/utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/JREFileResolverTest.java14
-rw-r--r--core/utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/KarafRootFileResolverTest.java13
-rw-r--r--core/utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/common/BundleContexFileResolverTest.java16
-rw-r--r--core/utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/common/CoreDefaultFileResolverTest.java25
-rw-r--r--core/utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/common/SdncConfigEnvVarFileResolverTest.java24
-rw-r--r--core/utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/dblib/DblibDefaultFileResolverTest.java25
-rw-r--r--core/utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/dblib/DblibEnvVarFileResolverTest.java24
-rw-r--r--plugins/LICENSE.txt22
-rw-r--r--plugins/README.md20
-rwxr-xr-xplugins/artifacts/pom.xml105
-rw-r--r--plugins/features/ccsdk-gr-toolkit/pom.xml37
-rw-r--r--plugins/features/ccsdk-properties-node/pom.xml29
-rw-r--r--plugins/features/ccsdk-restapi-call-node/pom.xml38
-rw-r--r--plugins/features/ccsdk-restconf-client/pom.xml32
-rw-r--r--plugins/features/ccsdk-sli-plugins-all/pom.xml60
-rw-r--r--plugins/features/ccsdk-sshapi-call-node/pom.xml36
-rw-r--r--plugins/features/ccsdk-template-node/pom.xml27
-rw-r--r--plugins/features/features-sli-plugins/pom.xml68
-rwxr-xr-xplugins/features/installer/pom.xml213
-rwxr-xr-xplugins/features/installer/src/assembly/assemble_installer_zip.xml39
-rwxr-xr-xplugins/features/installer/src/assembly/assemble_mvnrepo_zip.xml29
-rw-r--r--plugins/features/installer/src/main/resources/scripts/install-feature.sh18
-rwxr-xr-xplugins/features/pom.xml30
-rwxr-xr-xplugins/grToolkit/.gitignore38
-rwxr-xr-xplugins/grToolkit/README.md316
-rwxr-xr-xplugins/grToolkit/installer/pom.xml129
-rwxr-xr-xplugins/grToolkit/installer/src/assembly/assemble_installer_zip.xml56
-rwxr-xr-xplugins/grToolkit/installer/src/assembly/assemble_mvnrepo_zip.xml45
-rwxr-xr-xplugins/grToolkit/installer/src/main/resources/scripts/install-feature.sh39
-rwxr-xr-xplugins/grToolkit/model/.gitignore1
-rwxr-xr-xplugins/grToolkit/model/pom.xml27
-rwxr-xr-xplugins/grToolkit/model/scripts/python/yang2props.py78
-rwxr-xr-xplugins/grToolkit/model/src/main/yang/gr-toolkit.yang199
-rwxr-xr-xplugins/grToolkit/pom.xml40
-rwxr-xr-xplugins/grToolkit/provider/.gitignore1
-rwxr-xr-xplugins/grToolkit/provider/pom.xml122
-rwxr-xr-xplugins/grToolkit/provider/src/main/java/org/onap/ccsdk/sli/plugins/grtoolkit/GrToolkitProvider.java765
-rw-r--r--plugins/grToolkit/provider/src/main/java/org/onap/ccsdk/sli/plugins/grtoolkit/connection/ConnectionManager.java157
-rw-r--r--plugins/grToolkit/provider/src/main/java/org/onap/ccsdk/sli/plugins/grtoolkit/connection/ConnectionResponse.java43
-rw-r--r--plugins/grToolkit/provider/src/main/java/org/onap/ccsdk/sli/plugins/grtoolkit/data/AdminHealth.java58
-rw-r--r--plugins/grToolkit/provider/src/main/java/org/onap/ccsdk/sli/plugins/grtoolkit/data/ClusterActor.java222
-rw-r--r--plugins/grToolkit/provider/src/main/java/org/onap/ccsdk/sli/plugins/grtoolkit/data/ClusterHealth.java49
-rw-r--r--plugins/grToolkit/provider/src/main/java/org/onap/ccsdk/sli/plugins/grtoolkit/data/DatabaseHealth.java44
-rw-r--r--plugins/grToolkit/provider/src/main/java/org/onap/ccsdk/sli/plugins/grtoolkit/data/FailoverStatus.java64
-rw-r--r--plugins/grToolkit/provider/src/main/java/org/onap/ccsdk/sli/plugins/grtoolkit/data/Health.java40
-rw-r--r--plugins/grToolkit/provider/src/main/java/org/onap/ccsdk/sli/plugins/grtoolkit/data/MemberBuilder.java88
-rw-r--r--plugins/grToolkit/provider/src/main/java/org/onap/ccsdk/sli/plugins/grtoolkit/data/PropertyKeys.java40
-rw-r--r--plugins/grToolkit/provider/src/main/java/org/onap/ccsdk/sli/plugins/grtoolkit/data/SiteHealth.java125
-rw-r--r--plugins/grToolkit/provider/src/main/java/org/onap/ccsdk/sli/plugins/grtoolkit/resolver/HealthResolver.java212
-rw-r--r--plugins/grToolkit/provider/src/main/java/org/onap/ccsdk/sli/plugins/grtoolkit/resolver/ShardResolver.java177
-rw-r--r--plugins/grToolkit/provider/src/main/java/org/onap/ccsdk/sli/plugins/grtoolkit/resolver/SingleNodeHealthResolver.java160
-rw-r--r--plugins/grToolkit/provider/src/main/java/org/onap/ccsdk/sli/plugins/grtoolkit/resolver/SixNodeHealthResolver.java316
-rw-r--r--plugins/grToolkit/provider/src/main/java/org/onap/ccsdk/sli/plugins/grtoolkit/resolver/ThreeNodeHealthResolver.java162
-rwxr-xr-xplugins/grToolkit/provider/src/main/resources/gr-toolkit.properties35
-rw-r--r--plugins/grToolkit/provider/src/main/resources/org/opendaylight/blueprint/GrToolkit.xml33
-rw-r--r--plugins/grToolkit/provider/src/test/java/org/onap/ccsdk/sli/plugins/grtoolkit/GrToolkitProviderTest.java352
-rw-r--r--plugins/grToolkit/provider/src/test/java/org/onap/ccsdk/sli/plugins/grtoolkit/connection/ConnectionManagerTest.java65
-rw-r--r--plugins/grToolkit/provider/src/test/java/org/onap/ccsdk/sli/plugins/grtoolkit/connection/ConnectionResponseTest.java42
-rw-r--r--plugins/grToolkit/provider/src/test/java/org/onap/ccsdk/sli/plugins/grtoolkit/data/AdminHealthTest.java59
-rw-r--r--plugins/grToolkit/provider/src/test/java/org/onap/ccsdk/sli/plugins/grtoolkit/data/ClusterHealthTest.java47
-rw-r--r--plugins/grToolkit/provider/src/test/java/org/onap/ccsdk/sli/plugins/grtoolkit/data/DatabaseHealthTest.java42
-rw-r--r--plugins/grToolkit/provider/src/test/java/org/onap/ccsdk/sli/plugins/grtoolkit/data/FailoverStatusTest.java60
-rw-r--r--plugins/grToolkit/provider/src/test/java/org/onap/ccsdk/sli/plugins/grtoolkit/data/HealthTest.java34
-rw-r--r--plugins/grToolkit/provider/src/test/java/org/onap/ccsdk/sli/plugins/grtoolkit/data/MemberBuilderTest.java62
-rw-r--r--plugins/grToolkit/provider/src/test/java/org/onap/ccsdk/sli/plugins/grtoolkit/data/SiteHealthTest.java108
-rw-r--r--plugins/grToolkit/provider/src/test/java/org/onap/ccsdk/sli/plugins/grtoolkit/resolver/SingleNodeHealthResolverTest.java235
-rw-r--r--plugins/grToolkit/provider/src/test/java/org/onap/ccsdk/sli/plugins/grtoolkit/resolver/SixNodeHealthResolverTest.java335
-rw-r--r--plugins/grToolkit/provider/src/test/java/org/onap/ccsdk/sli/plugins/grtoolkit/resolver/ThreeNodeHealthResolverTest.java314
-rw-r--r--plugins/grToolkit/provider/src/test/resources/akka.conf67
-rwxr-xr-xplugins/grToolkit/provider/src/test/resources/gr-toolkit.properties35
-rw-r--r--plugins/grToolkit/provider/src/test/resources/single/akka.conf67
-rw-r--r--plugins/grToolkit/provider/src/test/resources/single/cluster.json17
-rw-r--r--plugins/grToolkit/provider/src/test/resources/single/default-config.json46
-rw-r--r--plugins/grToolkit/provider/src/test/resources/single/default-operational.json46
-rwxr-xr-xplugins/grToolkit/provider/src/test/resources/single/gr-toolkit.properties34
-rw-r--r--plugins/grToolkit/provider/src/test/resources/single/shard-manager.json15
-rw-r--r--plugins/grToolkit/provider/src/test/resources/six/akka.conf67
-rw-r--r--plugins/grToolkit/provider/src/test/resources/six/cluster.json17
-rw-r--r--plugins/grToolkit/provider/src/test/resources/six/component-health.json7
-rw-r--r--plugins/grToolkit/provider/src/test/resources/six/default-config.json46
-rw-r--r--plugins/grToolkit/provider/src/test/resources/six/default-operational.json46
-rwxr-xr-xplugins/grToolkit/provider/src/test/resources/six/gr-toolkit.properties34
-rw-r--r--plugins/grToolkit/provider/src/test/resources/six/shard-manager.json15
-rw-r--r--plugins/grToolkit/provider/src/test/resources/six/site-identifier.json7
-rw-r--r--plugins/grToolkit/provider/src/test/resources/three/akka.conf67
-rw-r--r--plugins/grToolkit/provider/src/test/resources/three/cluster.json17
-rw-r--r--plugins/grToolkit/provider/src/test/resources/three/default-config.json46
-rw-r--r--plugins/grToolkit/provider/src/test/resources/three/default-operational.json46
-rwxr-xr-xplugins/grToolkit/provider/src/test/resources/three/gr-toolkit.properties34
-rw-r--r--plugins/grToolkit/provider/src/test/resources/three/shard-manager.json15
-rwxr-xr-xplugins/properties-node/.gitignore34
-rwxr-xr-xplugins/properties-node/installer/pom.xml127
-rw-r--r--plugins/properties-node/installer/src/assembly/assemble_installer_zip.xml59
-rw-r--r--plugins/properties-node/installer/src/assembly/assemble_mvnrepo_zip.xml49
-rw-r--r--plugins/properties-node/installer/src/main/resources/scripts/install-feature.sh39
-rwxr-xr-xplugins/properties-node/pom.xml24
-rwxr-xr-xplugins/properties-node/provider/pom.xml60
-rw-r--r--plugins/properties-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/prop/JsonParser.java94
-rw-r--r--plugins/properties-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/prop/Parameters.java31
-rw-r--r--plugins/properties-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/prop/PropertiesNode.java194
-rw-r--r--plugins/properties-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/prop/XmlParser.java176
-rwxr-xr-xplugins/properties-node/provider/src/main/resources/OSGI-INF/blueprint/properties-node-blueprint.xml16
-rwxr-xr-xplugins/properties-node/provider/src/main/resources/org/opendaylight/blueprint/properties-node-blueprint.xml16
-rw-r--r--plugins/properties-node/provider/src/test/java/jtest/org/onap/ccsdk/sli/plugins/prop/TestJsonParser.java73
-rw-r--r--plugins/properties-node/provider/src/test/java/jtest/org/onap/ccsdk/sli/plugins/prop/TestPropertiesNode.java608
-rw-r--r--plugins/properties-node/provider/src/test/java/jtest/org/onap/ccsdk/sli/plugins/prop/TestXmlParser.java121
-rw-r--r--plugins/properties-node/provider/src/test/resources/invalidlength.xml49
-rw-r--r--plugins/properties-node/provider/src/test/resources/test30
-rw-r--r--plugins/properties-node/provider/src/test/resources/test-invalid.json29
-rw-r--r--plugins/properties-node/provider/src/test/resources/test-invalid.xml170
-rw-r--r--plugins/properties-node/provider/src/test/resources/test.json30
-rw-r--r--plugins/properties-node/provider/src/test/resources/test.txt31
-rw-r--r--plugins/properties-node/provider/src/test/resources/test.xml182
-rw-r--r--plugins/properties-node/provider/src/test/resources/test3.xml82
-rw-r--r--plugins/releases/0.5.0.yaml5
-rw-r--r--plugins/releases/0.5.1.yaml5
-rw-r--r--plugins/releases/0.5.2.yaml5
-rw-r--r--plugins/releases/0.6.0.yaml5
-rw-r--r--plugins/releases/0.6.1.yaml5
-rw-r--r--plugins/releases/0.7.0.yaml5
-rw-r--r--plugins/releases/0.7.1.yaml5
-rw-r--r--plugins/releases/1.0.0.yaml5
-rw-r--r--plugins/releases/1.0.1.yaml5
-rw-r--r--plugins/releases/1.1.0.yaml5
-rwxr-xr-xplugins/restapi-call-node/.gitignore34
-rwxr-xr-xplugins/restapi-call-node/installer/pom.xml125
-rw-r--r--plugins/restapi-call-node/installer/src/assembly/assemble_installer_zip.xml59
-rw-r--r--plugins/restapi-call-node/installer/src/assembly/assemble_mvnrepo_zip.xml49
-rw-r--r--plugins/restapi-call-node/installer/src/main/resources/scripts/install-feature.sh39
-rwxr-xr-xplugins/restapi-call-node/pom.xml23
-rwxr-xr-xplugins/restapi-call-node/provider/pom.xml94
-rw-r--r--plugins/restapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/restapicall/AuthType.java19
-rw-r--r--plugins/restapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/restapicall/Format.java36
-rw-r--r--plugins/restapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/restapicall/HttpMethod.java43
-rw-r--r--plugins/restapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/restapicall/HttpResponse.java34
-rw-r--r--plugins/restapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/restapicall/JsonParser.java153
-rwxr-xr-xplugins/restapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/restapicall/Parameters.java56
-rwxr-xr-xplugins/restapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/restapicall/PartnerDetails.java14
-rwxr-xr-xplugins/restapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/restapicall/RestapiCallNode.java1306
-rw-r--r--plugins/restapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/restapicall/RetryException.java30
-rw-r--r--plugins/restapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/restapicall/RetryPolicy.java64
-rw-r--r--plugins/restapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/restapicall/XmlJsonUtil.java518
-rw-r--r--plugins/restapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/restapicall/XmlParser.java180
-rwxr-xr-xplugins/restapi-call-node/provider/src/main/resources/OSGI-INF/blueprint/restapi-call-node-blueprint.xml16
-rw-r--r--plugins/restapi-call-node/provider/src/main/resources/actokentemplate.json4
-rw-r--r--plugins/restapi-call-node/provider/src/main/resources/default-ueb-message.json11
-rw-r--r--plugins/restapi-call-node/provider/src/main/resources/get-multicast-data.json13
-rw-r--r--plugins/restapi-call-node/provider/src/main/resources/l2-dci-connects-template.json11
-rw-r--r--plugins/restapi-call-node/provider/src/main/resources/l3-dci-connects-template.json14
-rw-r--r--plugins/restapi-call-node/provider/src/main/resources/l3smsitetemplate.json162
-rw-r--r--plugins/restapi-call-node/provider/src/main/resources/l3smvpntemplate.json10
-rw-r--r--plugins/restapi-call-node/provider/src/main/resources/l3smvrftemplate.json14
-rw-r--r--plugins/restapi-call-node/provider/src/main/resources/northbound-api-template.json22
-rw-r--r--plugins/restapi-call-node/provider/src/main/resources/northbound-api-template.xml43
-rwxr-xr-xplugins/restapi-call-node/provider/src/main/resources/org/opendaylight/blueprint/restapi-call-node-blueprint.xml16
-rw-r--r--plugins/restapi-call-node/provider/src/main/resources/service-configuration-notification-northbound-template.json23
-rw-r--r--plugins/restapi-call-node/provider/src/main/resources/sptn-l3vpn-template.json159
-rw-r--r--plugins/restapi-call-node/provider/src/main/resources/update-vpe-data-with-apply-group.json32
-rw-r--r--plugins/restapi-call-node/provider/src/main/resources/vnf-information-update.json3
-rw-r--r--plugins/restapi-call-node/provider/src/main/resources/vpn-allocation-request.json15
-rw-r--r--plugins/restapi-call-node/provider/src/main/resources/vpn-information-update.json3
-rw-r--r--plugins/restapi-call-node/provider/src/main/resources/vrf-service-configuration-information-template.json16
-rw-r--r--plugins/restapi-call-node/provider/src/main/resources/vrf-update-vlan-status-template.json12
-rw-r--r--plugins/restapi-call-node/provider/src/main/resources/vrf-update.json56
-rw-r--r--plugins/restapi-call-node/provider/src/test/java/org/onap/ccsdk/sli/plugins/restapicall/MockCookieAuthServer.java40
-rw-r--r--plugins/restapi-call-node/provider/src/test/java/org/onap/ccsdk/sli/plugins/restapicall/MultipartServerMock.java44
-rw-r--r--plugins/restapi-call-node/provider/src/test/java/org/onap/ccsdk/sli/plugins/restapicall/TestJsonParser.java259
-rwxr-xr-xplugins/restapi-call-node/provider/src/test/java/org/onap/ccsdk/sli/plugins/restapicall/TestRestapiCallNode.java604
-rw-r--r--plugins/restapi-call-node/provider/src/test/java/org/onap/ccsdk/sli/plugins/restapicall/TestXmlJsonUtil.java321
-rw-r--r--plugins/restapi-call-node/provider/src/test/java/org/onap/ccsdk/sli/plugins/restapicall/TestXmlParser.java121
-rwxr-xr-xplugins/restapi-call-node/provider/src/test/org/onap/ccsdk/sli/plugins/restapicall/TestRestapiCallNode.java531
-rw-r--r--plugins/restapi-call-node/provider/src/test/resources/1dArray.json8
-rw-r--r--plugins/restapi-call-node/provider/src/test/resources/2dArray.json4
-rw-r--r--plugins/restapi-call-node/provider/src/test/resources/3dArray.json5
-rw-r--r--plugins/restapi-call-node/provider/src/test/resources/ArrayMenu.json41
-rw-r--r--plugins/restapi-call-node/provider/src/test/resources/EmbeddedEscapedJson.json16
-rw-r--r--plugins/restapi-call-node/provider/src/test/resources/EscapedJson.json1
-rw-r--r--plugins/restapi-call-node/provider/src/test/resources/ObjectMenu.json43
-rw-r--r--plugins/restapi-call-node/provider/src/test/resources/Widget.json27
-rw-r--r--plugins/restapi-call-node/provider/src/test/resources/actokentemplate.json4
-rw-r--r--plugins/restapi-call-node/provider/src/test/resources/invalidlength.xml49
-rw-r--r--plugins/restapi-call-node/provider/src/test/resources/l2-dci-connects-template.json11
-rw-r--r--plugins/restapi-call-node/provider/src/test/resources/l3-dci-connects-template.json14
-rw-r--r--plugins/restapi-call-node/provider/src/test/resources/l3smsitetemplate.json162
-rw-r--r--plugins/restapi-call-node/provider/src/test/resources/l3smvpntemplate.json10
-rw-r--r--plugins/restapi-call-node/provider/src/test/resources/l3smvrftemplate.json14
-rwxr-xr-xplugins/restapi-call-node/provider/src/test/resources/partners.json22
-rw-r--r--plugins/restapi-call-node/provider/src/test/resources/sdwan-site.json10
-rw-r--r--plugins/restapi-call-node/provider/src/test/resources/sdwan-vpn-topology.json23
-rw-r--r--plugins/restapi-call-node/provider/src/test/resources/test-template.json37
-rw-r--r--plugins/restapi-call-node/provider/src/test/resources/test.json30
-rw-r--r--plugins/restapi-call-node/provider/src/test/resources/test.xml182
-rw-r--r--plugins/restapi-call-node/provider/src/test/resources/test3.xml82
-rw-r--r--plugins/restapi-call-node/provider/src/test/resources/testEmbeddedTemplate.json20
-rw-r--r--plugins/restapi-call-node/provider/src/test/resources/testMultiLineEmbeddedTemplate.json20
-rw-r--r--plugins/restapi-call-node/provider/src/test/resources/test_file.txt5
-rw-r--r--plugins/restapi-call-node/provider/src/test/resources/ueb.properties6
-rwxr-xr-xplugins/restconf-client/.gitignore34
-rwxr-xr-xplugins/restconf-client/installer/pom.xml127
-rw-r--r--plugins/restconf-client/installer/src/assembly/assemble_installer_zip.xml58
-rw-r--r--plugins/restconf-client/installer/src/assembly/assemble_mvnrepo_zip.xml48
-rw-r--r--plugins/restconf-client/installer/src/main/resources/scripts/install-feature.sh38
-rwxr-xr-xplugins/restconf-client/pom.xml23
-rwxr-xr-xplugins/restconf-client/provider/pom.xml132
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/restconfapicall/RestconfApiCallNode.java484
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/restconfapicall/RestconfApiUtils.java265
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/restconfdiscovery/AdditionalHeaderWebTarget.java166
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/restconfdiscovery/EventHandler.java46
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/restconfdiscovery/EventProcessor.java76
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/restconfdiscovery/RestconfDiscoveryNode.java310
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/restconfdiscovery/SubscriptionInfo.java122
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/restconfdiscovery/SvcLogicDiscoveryPlugin.java110
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/restconfdiscovery/SvcLogicGraphInfo.java178
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/Annotation.java66
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DataFormat.java37
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DataFormatSerializer.java94
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DataFormatSerializerContext.java104
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DefaultJsonListener.java145
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DefaultJsonWalker.java141
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DefaultXmlListener.java120
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DefaultXmlWalker.java48
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DfListenerFactory.java87
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DfSerializerFactory.java87
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DfSerializerUtil.java231
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/JsonListener.java55
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/JsonSerializer.java91
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/JsonWalker.java44
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/Listener.java34
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/MdsalSerializerHelper.java297
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/PropertiesNodeJsonListener.java233
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/PropertiesNodeXmlListener.java246
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/SerializerHelper.java116
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/XmlListener.java53
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/XmlNodeType.java37
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/XmlSerializer.java104
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/XmlWalker.java44
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/YangParameters.java42
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/DataNodeChild.java27
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/DefaultPropertiesNodeListener.java105
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/DefaultPropertiesNodeWalker.java119
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/HolderNode.java59
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/InnerNode.java215
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/LeafListHolderChild.java28
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/LeafListHolderNode.java93
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/LeafNode.java122
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/ListHolderChild.java28
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/ListHolderNode.java73
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/MdsalPropertiesNodeSerializer.java227
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/MdsalPropertiesNodeUtils.java578
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/MultiInstanceNode.java32
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/Namespace.java100
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/NodeChild.java28
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/NodeType.java34
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/PropertiesNode.java280
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/PropertiesNodeListener.java61
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/PropertiesNodeSerializer.java112
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/PropertiesNodeWalker.java38
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/RootNode.java212
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/SchemaPathHolder.java77
-rw-r--r--plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/SingleInstanceNode.java33
-rwxr-xr-xplugins/restconf-client/provider/src/main/resources/OSGI-INF/blueprint/restconf-client-blueprint.xml51
-rwxr-xr-xplugins/restconf-client/provider/src/main/resources/org/opendaylight/blueprint/restconf-client-blueprint.xml51
-rw-r--r--plugins/restconf-client/provider/src/test/java/org/onap/ccsdk/sli/plugins/restconfdiscovery/SseServerMock.java68
-rw-r--r--plugins/restconf-client/provider/src/test/java/org/onap/ccsdk/sli/plugins/restconfdiscovery/TestRestconfDiscoveryNode.java175
-rw-r--r--plugins/restconf-client/provider/src/test/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DataFormatSerializerTest.java996
-rw-r--r--plugins/restconf-client/provider/src/test/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DataFormatUtilsTest.java631
-rw-r--r--plugins/restconf-client/provider/src/test/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/IdentifierValidationTest.java762
-rw-r--r--plugins/restconf-client/provider/src/test/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/IdentifierValidationUtilsTest.java469
-rw-r--r--plugins/restconf-client/provider/src/test/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/PropertiesSerializerTest.java1144
-rw-r--r--plugins/restconf-client/provider/src/test/resources/yang/execution-service.yang43
-rw-r--r--plugins/restconf-client/provider/src/test/resources/yang/identity-test.yang77
-rw-r--r--plugins/restconf-client/provider/src/test/resources/yang/identity-types-second.yang25
-rw-r--r--plugins/restconf-client/provider/src/test/resources/yang/identity-types.yang17
-rw-r--r--plugins/restconf-client/provider/src/test/resources/yang/test-augment.yang106
-rw-r--r--plugins/restconf-client/provider/src/test/resources/yang/test-yang.yang231
-rw-r--r--plugins/restconf-client/provider/src/test/resources/yang/test_augment_1_for_module.yang108
-rw-r--r--plugins/restconf-client/provider/src/test/resources/yang/test_name_of_the_module.yang231
-rwxr-xr-xplugins/sshapi-call-node/.gitignore35
-rwxr-xr-xplugins/sshapi-call-node/installer/pom.xml126
-rw-r--r--plugins/sshapi-call-node/installer/src/assembly/assemble_installer_zip.xml59
-rw-r--r--plugins/sshapi-call-node/installer/src/assembly/assemble_mvnrepo_zip.xml49
-rw-r--r--plugins/sshapi-call-node/installer/src/main/resources/scripts/install-feature.sh39
-rwxr-xr-xplugins/sshapi-call-node/pom.xml23
-rw-r--r--plugins/sshapi-call-node/provider/ReadMe.md32
-rwxr-xr-xplugins/sshapi-call-node/provider/pom.xml61
-rw-r--r--plugins/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/SshApiCallNode.java283
-rw-r--r--plugins/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/AuthType.java41
-rw-r--r--plugins/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/Format.java39
-rw-r--r--plugins/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/JsonParser.java93
-rw-r--r--plugins/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/Parameters.java45
-rw-r--r--plugins/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/ParseParam.java275
-rw-r--r--plugins/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/XmlJsonUtil.java389
-rw-r--r--plugins/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/XmlParser.java176
-rw-r--r--plugins/sshapi-call-node/provider/src/main/resources/META-INF/spring/sshapi-call-node-context.xml47
-rw-r--r--plugins/sshapi-call-node/provider/src/main/resources/META-INF/spring/sshapi-call-node-osgi-context.xml34
-rwxr-xr-xplugins/sshapi-call-node/provider/src/main/resources/OSGI-INF/blueprint/sshapi-call-node-blueprint.xml16
-rwxr-xr-xplugins/sshapi-call-node/provider/src/main/resources/org/opendaylight/blueprint/sshapi-call-node-blueprint.xml16
-rw-r--r--plugins/sshapi-call-node/provider/src/test/java/jtest/org/onap/ccsdk/sli/plugins/restapicall/TestJsonParser.java85
-rw-r--r--plugins/sshapi-call-node/provider/src/test/java/jtest/org/onap/ccsdk/sli/plugins/restapicall/TestSshApiCallNode.java330
-rw-r--r--plugins/sshapi-call-node/provider/src/test/java/jtest/org/onap/ccsdk/sli/plugins/restapicall/TestXmlJsonUtil.java264
-rw-r--r--plugins/sshapi-call-node/provider/src/test/java/jtest/org/onap/ccsdk/sli/plugins/restapicall/TestXmlParser.java123
-rw-r--r--plugins/sshapi-call-node/provider/src/test/resources/invalidlength.xml49
-rw-r--r--plugins/sshapi-call-node/provider/src/test/resources/test-template.json57
-rw-r--r--plugins/sshapi-call-node/provider/src/test/resources/test.json51
-rw-r--r--plugins/sshapi-call-node/provider/src/test/resources/test.xml184
-rw-r--r--plugins/sshapi-call-node/provider/src/test/resources/test3.xml82
-rw-r--r--plugins/template-node/installer/pom.xml125
-rw-r--r--plugins/template-node/installer/src/assembly/assemble_installer_zip.xml58
-rw-r--r--plugins/template-node/installer/src/assembly/assemble_mvnrepo_zip.xml48
-rw-r--r--plugins/template-node/installer/src/main/resources/scripts/install-feature.sh39
-rw-r--r--plugins/template-node/pom.xml20
-rw-r--r--plugins/template-node/provider/pom.xml49
-rwxr-xr-xplugins/template-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/template/TemplateNode.java114
-rw-r--r--plugins/template-node/provider/src/main/resources/OSGI-INF/blueprint/blueprint.xml10
-rw-r--r--plugins/template-node/provider/src/test/java/org/onap/ccsdk/sli/plugins/template/MockTemplateNode.java7
-rw-r--r--plugins/template-node/provider/src/test/java/org/onap/ccsdk/sli/plugins/template/TemplateNodeTest.java85
-rw-r--r--plugins/template-node/provider/src/test/resources/basic.vtl12
-rw-r--r--plugins/template-node/provider/src/test/resources/template-node.properties4
-rwxr-xr-x[-rw-r--r--]pom.xml243
-rw-r--r--version.properties10
1071 files changed, 127338 insertions, 158 deletions
diff --git a/.gitignore b/.gitignore
index 6b9838c77..42cca13bb 100755
--- a/.gitignore
+++ b/.gitignore
@@ -7,10 +7,10 @@ org.eclipse.core.resources.prefs
.settings
.idea
.externalToolBuilders
-.checkstyle
-.factorypath
maven-eclipse.xml
workspace
+.checkstyle
+.vscode
## Compilation Files ##
*.class
@@ -21,26 +21,27 @@ MANIFEST.MF
## Misc Ignores (OS specific etc) ##
bin/
-lib/
dist
*~
*.ipr
*.iml
*.iws
-*.log
classes
out/
.DS_STORE
.metadata
+.vscode
provider/src/main/java/META-INF/
provider/src/main/java/inventory/
-model/src/main/yang-gen-sal
-yang-gen-sal/
+logs/
+debug-logs/
+*.log
+*.versionsBackup
## BlackDuck generated file
-sdnc-northbound_bdio.jsonld
+ccsdk-adaptors_bdio.jsonld
blackDuckHubProjectName.txt
blackDuckHubProjectVersionName.txt
-# Generated dependencies list
+#Generated dependencies list
direct-dependencies.txt
diff --git a/INFO.yaml b/INFO.yaml
index 9fd0908e3..804281bc0 100644
--- a/INFO.yaml
+++ b/INFO.yaml
@@ -1,5 +1,5 @@
---
-project: 'ccsdk-sli-northbound'
+project: 'ccsdk-sli'
project_creation_date: '2017-06-27'
lifecycle_state: 'Mature'
project_category: ''
@@ -29,11 +29,6 @@ meetings:
time: '13:00 UTC'
committers:
- <<: *onap_releng_ptl
- - name: 'Jack Lucas'
- email: 'jflucas@research.att.com'
- company: 'ATT'
- id: 'jackl'
- timezone: 'America/New_York'
- name: 'Jun (Nicolas) Hu'
email: 'jh245g@att.com'
company: 'ATT'
@@ -65,7 +60,7 @@ committers:
id: 'ks220y'
timezone: 'America/New_York'
repositories:
- - ccsdk/sli/northbound
+ - ccsdk/sli
tsc:
approval: 'https://lists.onap.org/pipermail/onap-tsc'
changes:
diff --git a/adaptors/LICENSE.txt b/adaptors/LICENSE.txt
new file mode 100644
index 000000000..3ea5081a0
--- /dev/null
+++ b/adaptors/LICENSE.txt
@@ -0,0 +1,22 @@
+/*
+ * ============LICENSE_START==========================================
+ * ===================================================================
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ * 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.
+ * ============LICENSE_END============================================
+ *
+ * ECOMP and OpenECOMP are trademarks
+ * and service marks of AT&T Intellectual Property.
+ *
+ */
diff --git a/adaptors/README.md b/adaptors/README.md
new file mode 100644
index 000000000..c906c67da
--- /dev/null
+++ b/adaptors/README.md
@@ -0,0 +1,8 @@
+This source repository contains the code for the SDN Controller adaptors.
+To compile this code:
+
+1. Make sure your local Maven settings file ($HOME/.m2/settings.xml) contains references to the ONAP repositories and OpenDaylight repositories. See example-settings.xml for an example.
+
+2. To compile, run "mvn clean install".
+
+
diff --git a/adaptors/aai-service/.gitignore b/adaptors/aai-service/.gitignore
new file mode 100755
index 000000000..e9143ef85
--- /dev/null
+++ b/adaptors/aai-service/.gitignore
@@ -0,0 +1,35 @@
+#####standard .git ignore entries#####
+
+## IDE Specific Files ##
+org.eclipse.core.resources.prefs
+.classpath
+.project
+.settings
+.idea
+.externalToolBuilders
+maven-eclipse.xml
+workspace
+
+## Compilation Files ##
+*.class
+**/target
+target
+target-ide
+MANIFEST.MF
+AutoGenerated*.txt
+
+## Misc Ignores (OS specific etc) ##
+bin/
+dist
+*~
+*.ipr
+*.iml
+*.iws
+classes
+out/
+.DS_STORE
+.metadata
+
+## Folders which contain auto generated source code ##
+yang-gen-config
+yang-gen-sal
diff --git a/adaptors/aai-service/README.md b/adaptors/aai-service/README.md
new file mode 100755
index 000000000..e69de29bb
--- /dev/null
+++ b/adaptors/aai-service/README.md
diff --git a/adaptors/aai-service/installer/pom.xml b/adaptors/aai-service/installer/pom.xml
new file mode 100755
index 000000000..591e9bc20
--- /dev/null
+++ b/adaptors/aai-service/installer/pom.xml
@@ -0,0 +1,143 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>odlparent-lite</artifactId>
+ <version>2.1.0</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.adaptors</groupId>
+ <artifactId>aai-service-installer</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>pom</packaging>
+
+ <name>ccsdk-sli-adaptors :: aai-service :: ${project.artifactId}</name>
+
+ <properties>
+ <application.name>ccsdk-aai-service</application.name>
+ <features.boot>${application.name}</features.boot>
+ <features.repositories>mvn:org.onap.ccsdk.sli.adaptors/${features.boot}/${project.version}/xml/features</features.repositories>
+ <include.transitive.dependencies>false</include.transitive.dependencies>
+ </properties>
+
+ <dependencies>
+
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.adaptors</groupId>
+ <artifactId>${application.name}</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ <exclusions>
+ <exclusion>
+ <groupId>*</groupId>
+ <artifactId>*</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.adaptors</groupId>
+ <artifactId>aai-service-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <version>2.6</version>
+ <executions>
+ <execution>
+ <id>maven-repo-zip</id>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ <phase>package</phase>
+ <configuration>
+ <attach>true</attach>
+ <finalName>stage/${application.name}-${project.version}</finalName>
+ <descriptors>
+ <descriptor>src/assembly/assemble_mvnrepo_zip.xml</descriptor>
+ </descriptors>
+ <appendAssemblyId>true</appendAssemblyId>
+ </configuration>
+ </execution>
+ <execution>
+ <id>installer-zip</id>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ <phase>package</phase>
+ <configuration>
+ <attach>true</attach>
+ <finalName>${application.name}-${project.version}-installer</finalName>
+ <descriptors>
+ <descriptor>src/assembly/assemble_installer_zip.xml</descriptor>
+ </descriptors>
+ <appendAssemblyId>false</appendAssemblyId>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>copy-dependencies</id>
+ <goals>
+ <goal>copy-dependencies</goal>
+ </goals>
+ <phase>prepare-package</phase>
+ <configuration>
+ <transitive>false</transitive>
+ <outputDirectory>${project.build.directory}/assembly/system</outputDirectory>
+ <overWriteReleases>false</overWriteReleases>
+ <overWriteSnapshots>true</overWriteSnapshots>
+ <overWriteIfNewer>true</overWriteIfNewer>
+ <useRepositoryLayout>true</useRepositoryLayout>
+ <addParentPoms>false</addParentPoms>
+ <copyPom>false</copyPom>
+ <includeGroupIds>org.onap.ccsdk.sli.adaptors,org.jvnet.jaxb2_commons</includeGroupIds>
+ <scope>provided</scope>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <artifactId>maven-resources-plugin</artifactId>
+ <version>2.6</version>
+ <executions>
+ <execution>
+ <id>copy-version</id>
+ <goals>
+ <goal>copy-resources</goal>
+ </goals><!-- here the phase you need -->
+ <phase>validate</phase>
+ <configuration>
+ <outputDirectory>${basedir}/target/stage</outputDirectory>
+ <resources>
+ <resource>
+ <directory>src/main/resources/scripts</directory>
+ <includes>
+ <include>install-feature.sh</include>
+ </includes>
+ <filtering>true</filtering>
+ </resource>
+ </resources>
+ </configuration>
+ </execution>
+
+ </executions>
+ </plugin>
+
+ </plugins>
+ </build>
+</project>
diff --git a/adaptors/aai-service/installer/src/assembly/assemble_installer_zip.xml b/adaptors/aai-service/installer/src/assembly/assemble_installer_zip.xml
new file mode 100644
index 000000000..b6fd65582
--- /dev/null
+++ b/adaptors/aai-service/installer/src/assembly/assemble_installer_zip.xml
@@ -0,0 +1,59 @@
+<!--
+ ============LICENSE_START=======================================================
+ openECOMP : SDN-C
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property. All rights
+ reserved.
+ ================================================================================
+ 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.
+ ============LICENSE_END=========================================================
+ -->
+
+<!-- Defines how we build the .zip file which is our distribution. -->
+
+<assembly
+ xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
+ <id>installer_zip</id>
+ <formats>
+ <format>zip</format>
+ </formats>
+
+ <!-- we want "system" and related files right at the root level
+ as this file is suppose to be unzip on top of a karaf
+ distro. -->
+ <includeBaseDirectory>false</includeBaseDirectory>
+
+ <fileSets>
+ <fileSet>
+ <directory>target/stage/</directory>
+ <outputDirectory>${application.name}</outputDirectory>
+ <fileMode>755</fileMode>
+ <includes>
+ <include>*.sh</include>
+ </includes>
+ </fileSet>
+ <fileSet>
+ <directory>target/stage/</directory>
+ <outputDirectory>${application.name}</outputDirectory>
+ <fileMode>644</fileMode>
+ <excludes>
+ <exclude>*.sh</exclude>
+ </excludes>
+ </fileSet>
+ </fileSets>
+
+
+
+</assembly>
diff --git a/adaptors/aai-service/installer/src/assembly/assemble_mvnrepo_zip.xml b/adaptors/aai-service/installer/src/assembly/assemble_mvnrepo_zip.xml
new file mode 100644
index 000000000..9cdc78879
--- /dev/null
+++ b/adaptors/aai-service/installer/src/assembly/assemble_mvnrepo_zip.xml
@@ -0,0 +1,49 @@
+<!--
+ ============LICENSE_START=======================================================
+ openECOMP : SDN-C
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property. All rights
+ reserved.
+ ================================================================================
+ 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.
+ ============LICENSE_END=========================================================
+ -->
+
+<!-- Defines how we build the .zip file which is our distribution. -->
+
+<assembly
+ xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
+ <id>repo</id>
+ <formats>
+ <format>zip</format>
+ </formats>
+
+ <!-- we want "system" and related files right at the root level
+ as this file is suppose to be unzip on top of a karaf
+ distro. -->
+ <includeBaseDirectory>false</includeBaseDirectory>
+
+ <fileSets>
+ <fileSet>
+ <directory>target/assembly/</directory>
+ <outputDirectory>.</outputDirectory>
+ <excludes>
+ </excludes>
+ </fileSet>
+ </fileSets>
+
+
+
+</assembly>
diff --git a/adaptors/aai-service/installer/src/main/resources/scripts/install-feature.sh b/adaptors/aai-service/installer/src/main/resources/scripts/install-feature.sh
new file mode 100644
index 000000000..0eab001d5
--- /dev/null
+++ b/adaptors/aai-service/installer/src/main/resources/scripts/install-feature.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+
+###
+# ============LICENSE_START=======================================================
+# openECOMP : SDN-C
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights
+# reserved.
+# ================================================================================
+# 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.
+# ============LICENSE_END=========================================================
+###
+
+ODL_HOME=${ODL_HOME:-/opt/opendaylight/current}
+ODL_KARAF_CLIENT=${ODL_KARAF_CLIENT:-${ODL_HOME}/bin/client}
+INSTALLERDIR=$(dirname $0)
+
+REPOZIP=${INSTALLERDIR}/${features.boot}-${project.version}.zip
+
+if [ -f ${REPOZIP} ]
+then
+ unzip -d ${ODL_HOME} ${REPOZIP}
+else
+ echo "ERROR : repo zip ($REPOZIP) not found"
+ exit 1
+fi
+
+${ODL_KARAF_CLIENT} feature:repo-add ${features.repositories}
+${ODL_KARAF_CLIENT} feature:install ${features.boot}
diff --git a/adaptors/aai-service/pom.xml b/adaptors/aai-service/pom.xml
new file mode 100755
index 000000000..322291043
--- /dev/null
+++ b/adaptors/aai-service/pom.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>odlparent-lite</artifactId>
+ <version>2.1.0</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.adaptors</groupId>
+ <artifactId>aai-service</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>pom</packaging>
+
+ <name>ccsdk-sli-adaptors :: aai-service</name>
+ <description>The AAI Interface service exposes an interface to AAI as an OSGi service</description>
+
+ <modules>
+ <module>provider</module>
+ <module>installer</module>
+ </modules>
+</project>
diff --git a/adaptors/aai-service/provider/pom.xml b/adaptors/aai-service/provider/pom.xml
new file mode 100755
index 000000000..ca3fda288
--- /dev/null
+++ b/adaptors/aai-service/provider/pom.xml
@@ -0,0 +1,148 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>binding-parent</artifactId>
+ <version>2.1.0</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.adaptors</groupId>
+ <artifactId>aai-service-provider</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>bundle</packaging>
+
+ <name>ccsdk-sli-adaptors :: aai-service :: ${project.artifactId}</name>
+
+ <properties>
+ <ccsdk.sli.adaptors.version>${project.version}</ccsdk.sli.adaptors.version>
+ </properties>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sli-core-artifacts</artifactId>
+ <version>${ccsdk.sli.core.version}</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sli-common</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <!-- let filters project deliver this to the karaf container -->
+ <dependency>
+ <groupId>org.onap.logging-analytics</groupId>
+ <artifactId>logging-filter-base</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.core</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>javax.ws.rs</groupId>
+ <artifactId>javax.ws.rs-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-databind</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.module</groupId>
+ <artifactId>jackson-module-jaxb-annotations</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-annotations</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>commons-lang</groupId>
+ <artifactId>commons-lang</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.jsoup</groupId>
+ <artifactId>jsoup</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-core</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.httpcomponents</groupId>
+ <artifactId>httpclient</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>javax.xml.bind</groupId>
+ <artifactId>jaxb-api</artifactId>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.jvnet.jaxb2.maven2</groupId>
+ <artifactId>maven-jaxb2-plugin</artifactId>
+ <version>0.14.0</version>
+ <executions>
+ <execution>
+ <id>gen-xjc</id>
+ <goals>
+ <goal>generate</goal>
+ </goals>
+ </execution>
+ </executions>
+ <configuration>
+ <schemaDirectory>${project.basedir}/src/main/resources</schemaDirectory>
+ <schemaIncludes>
+ <value>aai_schema_v21.xsd</value>
+ </schemaIncludes>
+ <bindingIncludes>
+ <include>aai-schema-bindings.xjb</include>
+ </bindingIncludes>
+ <generateDirectory>${project.build.directory}/generated-sources/main/java</generateDirectory>
+ <generatePackage>org.onap.aai.inventory.v21</generatePackage>
+ <extension>true</extension>
+ <args>
+ <arg>-Xannotate</arg>
+ </args>
+ <plugins>
+ <plugin>
+ <groupId>org.jvnet.jaxb2_commons</groupId>
+ <artifactId>jaxb2-basics-annotate</artifactId>
+ <version>0.6.5</version>
+ </plugin>
+ </plugins>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/AAIClient.java b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/AAIClient.java
new file mode 100755
index 000000000..5390d45de
--- /dev/null
+++ b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/AAIClient.java
@@ -0,0 +1,91 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * Modifications Copyright © 2018 IBM.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+/**
+ * @author Rich Tabedzki
+ *
+ */
+package org.onap.ccsdk.sli.adaptors.aai;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Map;
+
+import org.onap.aai.inventory.v21.*;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.core.sli.SvcLogicJavaPlugin;
+import org.onap.ccsdk.sli.core.sli.SvcLogicResource;
+import org.onap.ccsdk.sli.adaptors.aai.data.notify.NotifyEvent;
+
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.databind.JsonMappingException;
+
+public interface AAIClient extends SvcLogicResource, SvcLogicJavaPlugin {
+
+ public SearchResults requestServiceInstanceURL(String svcInstanceId) throws AAIServiceException;
+
+ // VServers
+ public Vserver requestVServerData(String tenantId, String vserverId, String cloudOwner, String cloudRegionId) throws AAIServiceException;
+
+ public URL requestVserverURLNodeQuery(String vserverName) throws AAIServiceException;
+ public String getTenantIdFromVserverUrl(URL url);
+ public String getCloudOwnerFromVserverUrl(URL url);
+ public String getCloudRegionFromVserverUrl(URL url);
+ public String getVServerIdFromVserverUrl(URL url, String tennantId);
+ public Vserver requestVServerDataByURL(URL url) throws AAIServiceException;
+
+
+
+ // ----------------- Release 1510 ----------------------
+ // // GenericVNF
+ public GenericVnf requestGenericVnfData(String vnfId) throws AAIServiceException;
+ public boolean postGenericVnfData(String vnfId, GenericVnf request) throws AAIServiceException;
+
+ // Physical Link
+ public PhysicalLink requestPhysicalLinkData(String vnfId) throws AAIServiceException;
+ public boolean postPhysicalLinkData(String vnfId, PhysicalLink request) throws AAIServiceException;
+ public boolean deletePhysicalLinkData(String vnfId, String resourceVersion) throws AAIServiceException;
+
+ // UBB Notify
+ public boolean sendNotify(NotifyEvent event, String serviceInstanceId, String pathCode) throws AAIServiceException;
+
+ // Node Query - 1602
+ public SearchResults requestNodeQuery(String type, String entityIdentifier, String entityName) throws AAIServiceException;
+ public String requestDataByURL(URL url) throws AAIServiceException;
+ public GenericVnf requestGenericVnfeNodeQuery(String vnfName) throws AAIServiceException;
+
+ public QueryStatus backup(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException;
+ public QueryStatus restore(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException;
+
+ public void logKeyError(String keys);
+
+ public QueryStatus processResponseData(String rv, String resource, AAIRequest request, String prefix, SvcLogicContext ctx, Map<String, String> nameValues, String modifier) throws JsonParseException, JsonMappingException, IOException, AAIServiceException ;
+ public String getPathTemplateForResource(String resoourceName, String join, SvcLogicContext ctx) throws MalformedURLException;
+ public boolean isDeprecatedFormat(String resource, Map<String, String> nameValues);
+
+ String query(AAIRequest request) throws AAIServiceException;
+ String save(AAIRequest request) throws AAIServiceException;
+ boolean delete(AAIRequest request, String resourceVersion) throws AAIServiceException;
+ boolean update(AAIRequest request, String resourceVersion) throws AAIServiceException;
+
+}
diff --git a/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/AAIClientRESTExecutor.java b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/AAIClientRESTExecutor.java
new file mode 100755
index 000000000..446ec4b6a
--- /dev/null
+++ b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/AAIClientRESTExecutor.java
@@ -0,0 +1,781 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Modifications Copyright (C) 2018 IBM.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.aai;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.nio.charset.StandardCharsets;
+import java.security.KeyManagementException;
+import java.security.KeyStore;
+import java.security.NoSuchAlgorithmException;
+import java.text.SimpleDateFormat;
+import java.util.Properties;
+
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.SSLSocketFactory;
+
+import org.apache.commons.codec.binary.Base64;
+import org.onap.ccsdk.sli.adaptors.aai.AAIService.TransactionIdTracker;
+import org.onap.ccsdk.sli.adaptors.aai.data.AAIDatum;
+import org.onap.ccsdk.sli.adaptors.aai.data.ErrorResponse;
+import org.onap.ccsdk.sli.adaptors.aai.data.RequestError;
+import org.onap.ccsdk.sli.adaptors.aai.data.ResourceVersion;
+import org.onap.ccsdk.sli.adaptors.aai.data.ServiceException;
+import org.onap.ccsdk.sli.core.sli.MetricLogger;
+import org.onap.logging.ref.slf4j.ONAPLogConstants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.http.impl.EnglishReasonPhraseCatalog;
+
+/**
+ * The AAIClientRESTExecutor class provides CRUD API for AAI Client service.
+ * @author Rich Tabedzki
+ */
+public class AAIClientRESTExecutor implements AAIExecutorInterface {
+
+ private final String truststorePath;
+ private final String truststorePassword;
+ private final String keystorePath;
+ private final String keystorePassword;
+ private final Boolean ignoreCertificateHostError;
+ // authentication credentials
+ private String userName;
+ private String userPassword;
+ private final String applicationId;
+ private static final String HTTP_URL_CONNECTION_RESULT="HttpURLConnection result: {} : {}";
+ private static final String ENTRY_DOESNT_EXIST="Entry does not exist.";
+
+ /**
+ * class Constructor
+ * @param props - properties to initialize an instance.
+ */
+ public AAIClientRESTExecutor(Properties props) {
+ super();
+
+ userName = props.getProperty(AAIService.CLIENT_NAME);
+ userPassword = props.getProperty(AAIService.CLIENT_PWWD);
+
+ if(userName == null || userName.isEmpty()){
+ LOG.debug("Basic user name is not set");
+ }
+ if(userPassword == null || userPassword.isEmpty()) {
+ LOG.debug("Basic password is not set");
+ }
+
+ truststorePath = props.getProperty(AAIService.TRUSTSTORE_PATH);
+ truststorePassword = props.getProperty(AAIService.TRUSTSTORE_PSSWD);
+ keystorePath = props.getProperty(AAIService.KEYSTORE_PATH);
+ keystorePassword = props.getProperty(AAIService.KEYSTORE_PSSWD);
+
+ String tmpApplicationId =props.getProperty(AAIService.APPLICATION_ID);
+ if(tmpApplicationId == null || tmpApplicationId.isEmpty()) {
+ tmpApplicationId = "SDNC";
+ }
+ applicationId = tmpApplicationId;
+
+ String iche = props.getProperty(AAIService.CERTIFICATE_HOST_ERROR);
+ boolean host_error = false;
+ if(iche != null && !iche.isEmpty()) {
+ host_error = Boolean.valueOf(iche);
+ }
+
+ ignoreCertificateHostError = host_error;
+
+ HttpsURLConnection.setDefaultHostnameVerifier( (String string,SSLSession ssls) -> {
+ return ignoreCertificateHostError;
+
+ });
+
+ if(truststorePath != null && truststorePassword != null && (new File(truststorePath)).exists()) {
+ System.setProperty("javax.net.ssl.trustStore", truststorePath);
+ System.setProperty("javax.net.ssl.trustStorePassword", truststorePassword);
+ }
+
+ if(keystorePath != null && keystorePassword != null && (new File(keystorePath)).exists())
+ {
+ //both jersey and HttpURLConnection can use this
+ SSLContext ctx = null;
+ try {
+ ctx = SSLContext.getInstance("TLS");
+
+ KeyManagerFactory kmf = null;
+ try (FileInputStream fin = new FileInputStream(keystorePath)){
+ String storeType = "PKCS12";
+ String def = KeyStore.getDefaultType();
+ kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
+
+ String extension = keystorePath.substring(keystorePath.lastIndexOf(".") + 1);
+
+ if(extension != null && !extension.isEmpty() && "JKS".equalsIgnoreCase(extension)) {
+ storeType = "JKS";
+ }
+ KeyStore ks = KeyStore.getInstance(storeType);
+
+ char[] pwd = keystorePassword.toCharArray();
+ ks.load(fin, pwd);
+ kmf.init(ks, pwd);
+ } catch (Exception ex) {
+ LOG.error("AAIResource", ex);
+ }
+
+ ctx.init(kmf.getKeyManagers(), null, null);
+
+ CTX = ctx;
+ LOG.debug("SSLContext created");
+
+ } catch (KeyManagementException | NoSuchAlgorithmException exc) {
+ LOG.error("AAIResource", exc);
+ }
+ }
+
+ try {
+ Field methodsField = HttpURLConnection.class.getDeclaredField("methods");
+ methodsField.setAccessible(true);
+ // get the methods field modifiers
+ Field modifiersField = Field.class.getDeclaredField("modifiers");
+ // bypass the "private" modifier
+ modifiersField.setAccessible(true);
+
+ // remove the "final" modifier
+ modifiersField.setInt(methodsField, methodsField.getModifiers() & ~Modifier.FINAL);
+
+ /* valid HTTP methods */
+ String[] methods = {
+ "GET", "POST", "HEAD", "OPTIONS", "PUT", "DELETE", "TRACE", "PATCH"
+ };
+ // set the new methods - including patch
+ methodsField.set(null, methods);
+
+ } catch (SecurityException | IllegalArgumentException | IllegalAccessException | NoSuchFieldException e) {
+ LOG.warn("Adding PATCH method", e);
+ }
+ LOG.info("AAIResource.ctor initialized.");
+
+ }
+
+ private static final Logger LOG = LoggerFactory.getLogger(AAIService.class);
+ private static final String NOT_PROVIDED = "NOT PROVIDED";
+ private final MetricLogger ml = new MetricLogger();
+
+ private SSLContext CTX;
+
+
+ private int connection_timeout = 300000;
+
+ private int read_timeout = 300000;
+
+ /**
+ * Returns an String that contains JSON data returned from the AAI Server.
+ * <p>
+ * This method always returns immediately, whether or not the
+ * data exists.
+ *
+ * @param request an instance of AAIRequiest representing
+ * the request made by DirectedGraph node.
+ * @return the JSON based representation of data instance requested.
+ * @see String
+ */
+ @Override
+ public String get(AAIRequest request) throws AAIServiceException {
+ String response = null;
+ InputStream inputStream = null;
+ HttpURLConnection con = null;
+ URL requestUrl = null;
+
+ StringBuilder errorStringBuilder = new StringBuilder();
+
+ try {
+
+ if(request.getRequestObject() != null) {
+ requestUrl = request.getRequestUrl(HttpMethod.POST, null);
+ requestUrl = appendDepth(requestUrl, request);
+ con = getConfiguredConnection(requestUrl, HttpMethod.POST);
+ String json_text = request.toJSONString();
+ LOGwriteDateTrace("data", json_text);
+ logMetricRequest("POST "+requestUrl.getPath(), json_text, requestUrl.getPath());
+ OutputStreamWriter osw = new OutputStreamWriter(con.getOutputStream());
+ osw.write(json_text);
+ osw.flush();
+ } else {
+ requestUrl = request.getRequestUrl(HttpMethod.GET, null);
+ requestUrl = appendDepth(requestUrl, request);
+ con = getConfiguredConnection(requestUrl, HttpMethod.GET);
+ logMetricRequest("GET "+requestUrl.getPath(), "", requestUrl.getPath());
+ }
+
+ // Check for errors
+ int responseCode = con.getResponseCode();
+ if (responseCode == HttpURLConnection.HTTP_OK) {
+ inputStream = con.getInputStream();
+ } else {
+ inputStream = con.getErrorStream();
+ }
+ String responseMessage = null;
+ try {
+ responseMessage = con.getResponseMessage();
+ } catch(Exception exc) {
+ responseMessage = EnglishReasonPhraseCatalog.INSTANCE.getReason(responseCode,null);
+ } finally {
+ if(responseMessage == null)
+ responseMessage = NOT_PROVIDED;
+ }
+
+ // Process the response
+ LOG.info(HTTP_URL_CONNECTION_RESULT, responseCode, responseMessage);
+ logMetricResponse(responseCode, responseMessage);
+
+ if(inputStream == null) inputStream = new ByteArrayInputStream("".getBytes(StandardCharsets.UTF_8));
+ BufferedReader reader = new BufferedReader( new InputStreamReader( inputStream ) );
+
+ ObjectMapper mapper = AAIService.getObjectMapper();
+
+ if (responseCode == HttpURLConnection.HTTP_OK) {
+ StringBuilder stringBuilder = new StringBuilder();
+ String line = null;
+ while( ( line = reader.readLine() ) != null ) {
+ stringBuilder.append( line );
+ }
+ response = stringBuilder.toString();
+ try {
+ Object object = mapper.readValue(response, Object.class);
+ LOGwriteEndingTrace(HttpURLConnection.HTTP_OK, responseMessage, mapper.writeValueAsString(object));
+ } catch(Exception exc) {
+ LOGwriteEndingTrace(HttpURLConnection.HTTP_OK, responseMessage, mapper.writeValueAsString(response));
+ }
+ } else if (responseCode == HttpURLConnection.HTTP_NOT_FOUND) {
+ LOGwriteEndingTrace(responseCode, responseMessage, ENTRY_DOESNT_EXIST);
+ ErrorResponse errorresponse = null;
+ try {
+ errorresponse = mapper.readValue(reader, ErrorResponse.class);
+ } catch(Exception exc) {
+ errorresponse = new ErrorResponse();
+ RequestError requestError = new RequestError();
+ ServiceException serviceException = new ServiceException();
+ serviceException.setText(ENTRY_DOESNT_EXIST);
+ requestError.setServiceException(serviceException);
+ errorresponse.setRequestError(requestError );
+ }
+ throw new AAIServiceException(responseCode, errorresponse);
+ } else if (responseCode == HttpURLConnection.HTTP_UNAUTHORIZED) {
+ StringBuilder stringBuilder = new StringBuilder();
+ String line = null;
+ while( ( line = reader.readLine() ) != null ) {
+ stringBuilder.append( line );
+ }
+ LOGwriteEndingTrace(responseCode, responseMessage, stringBuilder.toString());
+ ServiceException serviceException = new ServiceException();
+ serviceException.setMessageId("HTTP_UNAUTHORIZED");
+ serviceException.setText(stringBuilder.toString());
+ RequestError requestError = new RequestError();
+ requestError.setServiceException(serviceException);
+ ErrorResponse errorresponse = new ErrorResponse();
+ errorresponse.setRequestError(requestError);
+ throw new AAIServiceException(responseCode, errorresponse);
+ } else {
+ String line = null;
+ while( ( line = reader.readLine() ) != null ) {
+ errorStringBuilder.append("\n").append( line );
+ }
+
+ ErrorResponse errorresponse = mapper.readValue(errorStringBuilder.toString(), ErrorResponse.class);
+ LOGwriteEndingTrace(responseCode, responseMessage, mapper.writeValueAsString(errorresponse));
+ throw new AAIServiceException(responseCode, errorresponse);
+ }
+
+ } catch(AAIServiceException aaiexc) {
+ throw aaiexc;
+ } catch (Exception exc) {
+ LOG.warn(errorStringBuilder.toString(), exc);
+ throw new AAIServiceException(exc);
+ } finally {
+ if(inputStream != null){
+ try {
+ inputStream.close();
+ } catch(Exception exc) {
+ LOG.warn("", exc);
+ }
+ }
+ }
+ return response;
+ }
+
+ /**
+ * Returns an String that contains JSON data returned from the AAI Server.
+ * <p>
+ * This method always returns immediately, whether or not the
+ * data exists.
+ *
+ * @param request an instance of AAIRequiest representing
+ * the request made by DirectedGraph node.
+ * @return the JSON based representation of data instance requested.
+ * @see String
+ */
+ @Override
+ public String post(AAIRequest request) throws AAIServiceException {
+ InputStream inputStream = null;
+
+ try {
+ String resourceVersion = null;
+ AAIDatum instance = request.getRequestObject();
+
+ try {
+ Method getResourceVersionMethod = instance.getClass().getMethod("getResourceVersion");
+ if(getResourceVersionMethod != null){
+ try {
+ Object object = getResourceVersionMethod.invoke(instance);
+ if(object != null)
+ resourceVersion = object.toString();
+ } catch (InvocationTargetException exc) {
+ LOG.warn("", exc);
+ }
+ }
+ } catch(Exception exc) {
+ LOG.error("", exc);
+ }
+
+ URL requestUrl = request.getRequestUrl(HttpMethod.PUT, resourceVersion);
+ HttpURLConnection con = getConfiguredConnection(requestUrl, HttpMethod.PUT);
+ ObjectMapper mapper = AAIService.getObjectMapper();
+ String jsonText = request.toJSONString();
+
+ LOGwriteDateTrace("data", jsonText);
+ logMetricRequest("PUT "+requestUrl.getPath(), jsonText, requestUrl.getPath());
+
+ OutputStreamWriter osw = new OutputStreamWriter(con.getOutputStream());
+ osw.write(jsonText);
+ osw.flush();
+
+ // Check for errors
+ int responseCode = con.getResponseCode();
+ if (responseCode == HttpURLConnection.HTTP_OK || responseCode == HttpURLConnection.HTTP_CREATED || responseCode == HttpURLConnection.HTTP_ACCEPTED || responseCode == HttpURLConnection.HTTP_NO_CONTENT) {
+ inputStream = con.getInputStream();
+ } else {
+ inputStream = con.getErrorStream();
+ }
+ String responseMessage = null;
+ try {
+ responseMessage = con.getResponseMessage();
+ } catch(Exception exc) {
+ responseMessage = EnglishReasonPhraseCatalog.INSTANCE.getReason(responseCode,null);
+ } finally {
+ if(responseMessage == null)
+ responseMessage = NOT_PROVIDED;
+ }
+
+ LOG.info(HTTP_URL_CONNECTION_RESULT, responseCode, responseMessage);
+ logMetricResponse(responseCode, responseMessage);
+
+ // Process the response
+ BufferedReader reader;
+ String line = null;
+ reader = new BufferedReader( new InputStreamReader( inputStream ) );
+ mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
+
+ if (responseCode == HttpURLConnection.HTTP_OK || responseCode == HttpURLConnection.HTTP_CREATED || responseCode == HttpURLConnection.HTTP_ACCEPTED || responseCode == HttpURLConnection.HTTP_NO_CONTENT) {
+ StringBuilder stringBuilder = new StringBuilder();
+
+ while( ( line = reader.readLine() ) != null ) {
+ stringBuilder.append( line );
+ }
+ LOGwriteEndingTrace(responseCode, responseMessage, (stringBuilder.length() > 0) ? stringBuilder.toString() : "{no-data}");
+ return stringBuilder.toString();
+ } else {
+ ErrorResponse errorresponse = mapper.readValue(reader, ErrorResponse.class);
+ LOGwriteEndingTrace(responseCode, responseMessage, mapper.writeValueAsString(errorresponse));
+
+ throw new AAIServiceException(responseCode, errorresponse);
+ }
+ } catch(AAIServiceException aaiexc) {
+ throw aaiexc;
+ } catch (Exception exc) {
+ LOG.warn("AAIRequestExecutor.post", exc);
+ throw new AAIServiceException(exc);
+ } finally {
+ try {
+ if(inputStream != null)
+ inputStream.close();
+ } catch (Exception exc) {
+ LOG.warn("AAIRequestExecutor.post", exc);
+ }
+ }
+ }
+
+ /**
+ * Returns Boolean that contains completion state of the command executed.
+ * <p>
+ * This method always returns immediately, whether or not the
+ * data exists.
+ *
+ * @param request an instance of AAIRequiest representing
+ * @param resourceVersion a resource version of the data instacne to be deleted.
+ * the request made by DirectedGraph node.
+ * @return completion state of the command.
+ * @see String
+ */
+ @Override
+ public Boolean delete(AAIRequest request, String resourceVersion) throws AAIServiceException {
+ Boolean response = null;
+ InputStream inputStream = null;
+
+ if(resourceVersion == null) {
+ throw new AAIServiceException("resource-version is required for DELETE request");
+ }
+
+ try {
+ URL requestUrl = request.getRequestUrl(HttpMethod.DELETE, resourceVersion);
+ HttpURLConnection conn = getConfiguredConnection(requestUrl, HttpMethod.DELETE);
+ logMetricRequest("DELETE "+requestUrl.getPath(), "", requestUrl.getPath());
+ conn.setDoOutput(true);
+
+ // Check for errors
+ int responseCode = conn.getResponseCode();
+ if (responseCode == HttpURLConnection.HTTP_OK || responseCode == HttpURLConnection.HTTP_NO_CONTENT) {
+ inputStream = conn.getInputStream();
+ } else {
+ inputStream = conn.getErrorStream();
+ }
+ String responseMessage = null;
+ try {
+ responseMessage = conn.getResponseMessage();
+ } catch(Exception exc) {
+ responseMessage = EnglishReasonPhraseCatalog.INSTANCE.getReason(responseCode,null);
+ } finally {
+ if(responseMessage == null)
+ responseMessage = NOT_PROVIDED;
+ }
+
+ // Process the response
+ LOG.info(HTTP_URL_CONNECTION_RESULT, responseCode, responseMessage);
+ logMetricResponse(responseCode, responseMessage);
+
+ if(inputStream == null) inputStream = new ByteArrayInputStream("".getBytes(StandardCharsets.UTF_8));
+ BufferedReader reader = new BufferedReader( new InputStreamReader( inputStream ) );
+ String line = null;
+
+ ObjectMapper mapper = AAIService.getObjectMapper();
+
+ if (responseCode == HttpURLConnection.HTTP_OK || responseCode == HttpURLConnection.HTTP_NO_CONTENT) {
+ StringBuilder stringBuilder = new StringBuilder();
+
+ while( ( line = reader.readLine() ) != null ) {
+ stringBuilder.append( line );
+ }
+ LOGwriteEndingTrace(responseCode, responseMessage, stringBuilder.toString());
+ response = true;
+ } else if(responseCode == HttpURLConnection.HTTP_NOT_FOUND ) {
+ LOGwriteEndingTrace(responseCode, responseMessage, ENTRY_DOESNT_EXIST);
+ response = false;
+ } else {
+ ErrorResponse errorresponse = mapper.readValue(reader, ErrorResponse.class);
+ LOGwriteEndingTrace(responseCode, responseMessage, mapper.writeValueAsString(errorresponse));
+ throw new AAIServiceException(responseCode, errorresponse);
+ }
+ } catch(AAIServiceException aaiexc) {
+ throw aaiexc;
+ } catch (Exception exc) {
+ LOG.warn("delete", exc);
+ throw new AAIServiceException(exc);
+ } finally {
+ if(inputStream != null){
+ try {
+ inputStream.close();
+ } catch(Exception exc) {
+ LOG.warn("delete", exc);
+ }
+ }
+ }
+ return response;
+ }
+
+ /**
+ * Returns an String that contains JSON data returned from the AAI Server.
+ * <p>
+ * This method always returns immediately, whether or not the
+ * data exists.
+ *
+ * @param request an instance of AAIRequiest representing
+ * the request made by DirectedGraph node.
+ * @param clas an definition of the class for which data will be returned
+ * @return the instance of the class with data.
+ * @see String
+ */
+ @Override
+ public Object query(AAIRequest request, Class clas) throws AAIServiceException {
+ Object response = null;
+ InputStream inputStream = null;
+
+ try {
+ URL requestUrl = request.getRequestQueryUrl(HttpMethod.GET);
+ HttpURLConnection con = getConfiguredConnection(requestUrl, HttpMethod.GET);
+ logMetricRequest("GET "+requestUrl.getPath(), "", requestUrl.getPath());
+
+ // Check for errors
+ int responseCode = con.getResponseCode();
+ if (responseCode == HttpURLConnection.HTTP_OK) {
+ inputStream = con.getInputStream();
+ } else {
+ inputStream = con.getErrorStream();
+ }
+ String responseMessage = null;
+ try {
+ responseMessage = con.getResponseMessage();
+ } catch(Exception exc) {
+ responseMessage = EnglishReasonPhraseCatalog.INSTANCE.getReason(responseCode,null);
+ } finally {
+ if(responseMessage == null)
+ responseMessage = NOT_PROVIDED;
+ }
+
+ LOG.info(HTTP_URL_CONNECTION_RESULT, responseCode, responseMessage);
+ logMetricResponse(responseCode, responseMessage);
+ ObjectMapper mapper = AAIService.getObjectMapper();
+
+ if (responseCode == HttpURLConnection.HTTP_OK) {
+ // Process the response
+ BufferedReader reader = new BufferedReader( new InputStreamReader( inputStream ) );
+ response = mapper.readValue(reader, clas);
+ LOGwriteEndingTrace(HttpURLConnection.HTTP_OK, "SUCCESS", mapper.writeValueAsString(response));
+ } else if (responseCode == HttpURLConnection.HTTP_NOT_FOUND) {
+ LOGwriteEndingTrace(responseCode, "HTTP_NOT_FOUND", ENTRY_DOESNT_EXIST);
+ return response;
+ } else {
+ BufferedReader reader = new BufferedReader( new InputStreamReader( inputStream ) );
+ ErrorResponse errorresponse = mapper.readValue(reader, ErrorResponse.class);
+ LOGwriteEndingTrace(responseCode, "FAILURE", mapper.writeValueAsString(errorresponse));
+ throw new AAIServiceException(responseCode, errorresponse);
+ }
+
+ } catch(AAIServiceException aaiexc) {
+ throw aaiexc;
+ } catch (Exception exc) {
+ LOG.warn("GET", exc);
+ throw new AAIServiceException(exc);
+ } finally {
+ if(inputStream != null){
+ try {
+ inputStream.close();
+ } catch(Exception exc) {
+ LOG.warn("GET", exc);
+ }
+ }
+ }
+ return response;
+ }
+
+ @Override
+ public Boolean patch(AAIRequest request, String resourceVersion) throws AAIServiceException {
+ InputStream inputStream = null;
+
+ try {
+ AAIDatum instance = request.getRequestObject();
+ if(instance instanceof ResourceVersion) {
+ resourceVersion = ((ResourceVersion)instance).getResourceVersion();
+ }
+
+ URL requestUrl = null;
+ requestUrl = request.getRequestUrl("PATCH", resourceVersion);
+ HttpURLConnection con = getConfiguredConnection(requestUrl, "PATCH");
+ ObjectMapper mapper = AAIService.getObjectMapper();
+ String jsonText = request.toJSONString();
+
+ LOGwriteDateTrace("data", jsonText);
+ logMetricRequest("PATCH "+requestUrl.getPath(), jsonText, requestUrl.getPath());
+
+ OutputStreamWriter osw = new OutputStreamWriter(con.getOutputStream());
+ osw.write(jsonText);
+ osw.flush();
+
+ // Check for errors
+ int responseCode = con.getResponseCode();
+ if (responseCode == HttpURLConnection.HTTP_OK || responseCode == HttpURLConnection.HTTP_CREATED || responseCode == HttpURLConnection.HTTP_ACCEPTED || responseCode == HttpURLConnection.HTTP_NO_CONTENT) {
+ inputStream = con.getInputStream();
+ } else {
+ inputStream = con.getErrorStream();
+ }
+ String responseMessage = null;
+ try {
+ responseMessage = con.getResponseMessage();
+ } catch(Exception exc) {
+ LOG.info("Exception occured", exc.getMessage());
+ responseMessage = EnglishReasonPhraseCatalog.INSTANCE.getReason(responseCode,null);
+ } finally {
+ if(responseMessage == null)
+ responseMessage = NOT_PROVIDED;
+ }
+
+ LOG.info(HTTP_URL_CONNECTION_RESULT, responseCode, responseMessage);
+ logMetricResponse(responseCode, responseMessage);
+
+ // Process the response
+ BufferedReader reader;
+ String line = null;
+ reader = new BufferedReader( new InputStreamReader( inputStream ) );
+ mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
+
+ if (responseCode == HttpURLConnection.HTTP_OK || responseCode == HttpURLConnection.HTTP_CREATED || responseCode == HttpURLConnection.HTTP_ACCEPTED || responseCode == HttpURLConnection.HTTP_NO_CONTENT) {
+ StringBuilder stringBuilder = new StringBuilder();
+
+ while( ( line = reader.readLine() ) != null ) {
+ stringBuilder.append( line );
+ }
+ LOGwriteEndingTrace(responseCode, responseMessage, (stringBuilder.length() > 0) ? stringBuilder.toString() : "{no-data}");
+ return true;
+ } else {
+ StringBuilder stringBuilder = new StringBuilder();
+
+ while( ( line = reader.readLine() ) != null ) {
+ stringBuilder.append("\n").append( line );
+ }
+ LOG.info(stringBuilder.toString());
+
+
+ ErrorResponse errorresponse = mapper.readValue(reader, ErrorResponse.class);
+ LOGwriteEndingTrace(responseCode, responseMessage, mapper.writeValueAsString(errorresponse));
+
+ throw new AAIServiceException(responseCode, errorresponse);
+ }
+ } catch(AAIServiceException aaiexc) {
+ throw aaiexc;
+ } catch (Exception exc) {
+ LOG.warn("AAIRequestExecutor.patch", exc);
+ throw new AAIServiceException(exc);
+ } finally {
+ try {
+ if(inputStream != null)
+ inputStream.close();
+ } catch (Exception exc) {
+ LOG.warn("AAIRequestExecutor.patch", exc);
+ }
+ }
+ }
+
+ /**
+ *
+ * @param httpReqUrl
+ * @param method
+ * @return
+ * @throws Exception
+ */
+ protected HttpURLConnection getConfiguredConnection(URL httpReqUrl, String method) throws Exception {
+ HttpURLConnection con = (HttpURLConnection) httpReqUrl.openConnection();
+
+ // Set up the connection properties
+ con.setRequestProperty("Connection", "close");
+ con.setDoInput(true);
+ con.setDoOutput(true);
+ con.setUseCaches(false);
+ con.setConnectTimeout(connection_timeout);
+ con.setReadTimeout(read_timeout);
+ con.setRequestMethod(method);
+ con.setRequestProperty("Accept", "application/json");
+ con.setRequestProperty("Transfer-Encoding","chunked");
+ con.setRequestProperty("Content-Type",
+ "PATCH".equalsIgnoreCase(method) ? "application/merge-patch+json" : "application/json");
+ con.setRequestProperty("X-FromAppId", applicationId);
+ con.setRequestProperty("X-TransactionId", TransactionIdTracker.getNextTransactionId());
+ String mlId = ml.getRequestID();
+ if (mlId != null && !mlId.isEmpty()) {
+ LOG.debug(String.format("MetricLogger requestId = %s", mlId));
+ con.setRequestProperty(ONAPLogConstants.MDCs.REQUEST_ID, mlId);
+ } else {
+ LOG.debug("MetricLogger requestId is null");
+ }
+
+ if (userName != null && !userName.isEmpty() && userPassword != null && !userPassword.isEmpty()) {
+ String basicAuth = "Basic " + new String(Base64.encodeBase64((userName + ":" + userPassword).getBytes()));
+ con.setRequestProperty("Authorization", basicAuth);
+ }
+
+ if (con instanceof HttpsURLConnection && CTX != null) {
+ SSLSocketFactory sockFact = CTX.getSocketFactory();
+ HttpsURLConnection.class.cast(con).setSSLSocketFactory(sockFact);
+ }
+ return con;
+ }
+
+ private URL appendDepth(URL requestUrl, AAIRequest request) throws MalformedURLException {
+
+ String depth = request.requestProperties.getProperty("depth", "1");
+ String path = requestUrl.toString();
+ if(path.contains("?depth=") || path.contains("&depth=")) {
+ return requestUrl;
+ } else {
+ if(path.contains("?")) {
+ path = String.format("%s&depth=%s", path, depth);
+ } else {
+ path = String.format("%s?depth=%s", path, depth);
+ }
+ return new URL(path);
+ }
+ }
+
+ public void logMetricRequest(String targetServiceName, String msg, String path){
+ String svcInstanceId = "";
+ String svcName = null;
+ String partnerName = null;
+ String targetEntity = "A&AI";
+ String targetVirtualEntity = null;
+
+ ml.logRequest(svcInstanceId, svcName, partnerName, targetEntity, targetServiceName, targetVirtualEntity, msg);
+ }
+
+ public void logMetricResponse(int responseCode, String responseDescription){
+ ml.logResponse(responseCode < 400 ? "COMPLETE" : "ERROR", Integer.toString(responseCode), responseDescription);
+ }
+
+ protected void LOGwriteFirstTrace(String method, String url) {
+ String time = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'").format(System.currentTimeMillis());
+ LOG.info("A&AI transaction :");
+ LOG.info("Request Time : " + time + ", Method : " + method);
+ LOG.info("Request URL : "+ url);
+ }
+
+ protected void LOGwriteDateTrace(String name, String data) {
+ LOG.info("Input - " + name + " : " + data);
+ }
+
+ protected void LOGwriteEndingTrace(int response_code, String comment, String data) {
+ LOG.info("Response code : " + response_code +", " + comment);
+ LOG.info(String.format("Response data : %s", data));
+ }
+
+}
diff --git a/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/AAIDeclarations.java b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/AAIDeclarations.java
new file mode 100755
index 000000000..6765e152b
--- /dev/null
+++ b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/AAIDeclarations.java
@@ -0,0 +1,2041 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Modifications Copyright (C) 2019 IBM.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+/**
+ * @author Rich Tabedzki
+ *
+ */
+package org.onap.ccsdk.sli.adaptors.aai;
+
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.NoSuchMethodException;
+import java.net.MalformedURLException;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.net.URLDecoder;
+import java.net.URLEncoder;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.xml.bind.annotation.XmlType;
+
+import org.apache.commons.lang.StringUtils;
+import org.onap.ccsdk.sli.adaptors.aai.data.AAIDatum;
+import org.onap.ccsdk.sli.adaptors.aai.query.FormattedQueryResultList;
+import org.onap.ccsdk.sli.adaptors.aai.query.Result;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.aai.inventory.v21.GenericVnf;
+import org.onap.aai.inventory.v21.Image;
+import org.onap.aai.inventory.v21.Metadata;
+import org.onap.aai.inventory.v21.Metadatum;
+import org.onap.aai.inventory.v21.RelatedToProperty;
+import org.onap.aai.inventory.v21.Relationship;
+import org.onap.aai.inventory.v21.RelationshipData;
+import org.onap.aai.inventory.v21.RelationshipList;
+import org.onap.aai.inventory.v21.ResultData;
+import org.onap.aai.inventory.v21.SearchResults;
+import org.onap.aai.inventory.v21.ServiceInstance;
+import org.onap.aai.inventory.v21.Vlan;
+import org.onap.aai.inventory.v21.Vlans;
+import org.onap.aai.inventory.v21.Vserver;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.databind.JsonMappingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+
+public abstract class AAIDeclarations implements AAIClient {
+
+ public static final String TRUSTSTORE_PATH = "org.onap.ccsdk.sli.adaptors.aai.ssl.trust";
+ public static final String TRUSTSTORE_PSSWD = "org.onap.ccsdk.sli.adaptors.aai.ssl.trust.psswd";
+ public static final String KEYSTORE_PATH = "org.onap.ccsdk.sli.adaptors.aai.ssl.key";
+ public static final String KEYSTORE_PSSWD = "org.onap.ccsdk.sli.adaptors.aai.ssl.key.psswd";
+
+ public static final String APPLICATION_ID = "org.onap.ccsdk.sli.adaptors.aai.application";
+
+ public static final String CLIENT_NAME = "org.onap.ccsdk.sli.adaptors.aai.client.name";
+ public static final String CLIENT_PWWD = "org.onap.ccsdk.sli.adaptors.aai.client.psswd";
+
+
+ public static final String CONNECTION_TIMEOUT = "connection.timeout";
+ public static final String READ_TIMEOUT = "read.timeout";
+
+ public static final String TARGET_URI = "org.onap.ccsdk.sli.adaptors.aai.uri";
+
+ public static final String AAI_VERSION = "org.onap.ccsdk.sli.adaptors.aai.version";
+
+ // Availability zones query
+ public static final String QUERY_PATH = "org.onap.ccsdk.sli.adaptors.aai.path.query";
+
+ // Update
+ public static final String UPDATE_PATH = "org.onap.ccsdk.sli.adaptors.aai.update";
+
+ // Service instance
+ public static final String SVC_INSTANCE_PATH = "org.onap.ccsdk.sli.adaptors.aai.path.svcinst";
+ public static final String SVC_INST_QRY_PATH = "org.onap.ccsdk.sli.adaptors.aai.path.svcinst.query";
+
+ // VServer
+ public static final String NETWORK_VSERVER_PATH = "org.onap.ccsdk.sli.adaptors.aai.path.vserver";
+
+ public static final String VNF_IMAGE_QUERY_PATH = "org.onap.ccsdk.sli.adaptors.aai.path.vnf.image.query";
+
+ public static final String PARAM_SERVICE_TYPE = "org.onap.ccsdk.sli.adaptors.aai.param.service.type";
+ public static final String CERTIFICATE_HOST_ERROR = "org.onap.ccsdk.sli.adaptors.aai.host.certificate.ignore";
+
+ // UBB Notify
+ public static final String UBB_NOTIFY_PATH = "org.onap.ccsdk.sli.adaptors.aai.path.notify";
+ public static final String SELFLINK_AVPN = "org.onap.ccsdk.sli.adaptors.aai.notify.selflink.avpn";
+ public static final String SELFLINK_FQDN = "org.onap.ccsdk.sli.adaptors.aai.notify.selflink.fqdn";
+
+ //Service
+ public static final String SERVICE_PATH = "org.onap.ccsdk.sli.adaptors.aai.path.service";
+
+ // site-pair-sets
+ public static final String SITE_PAIR_SET_PATH = "org.onap.ccsdk.sli.adaptors.aai.path.site.pair.set";
+
+ // node query (1602)
+ public static final String QUERY_NODES_PATH = "org.onap.ccsdk.sli.adaptors.aai.query.nodes";
+
+ private static final String VERSION_PATTERN = "/v$/";
+
+ private static final String AAI_SERVICE_EXCEPTION = "AAI Service Exception";
+
+ protected abstract Logger getLogger();
+ public abstract AAIExecutorInterface getExecutor();
+
+ private static final String RELATIONSHIP_DATA= "Retrofitting relationship data: ";
+
+
+ @Override
+ public QueryStatus query(String resource, boolean localOnly, String select, String key, String prefix, String orderBy, SvcLogicContext ctx)
+ throws SvcLogicException {
+
+ getLogger().debug("AAIService.query \tresource = "+resource);
+
+ String vnfId;
+ String vnfName = null;
+ HashMap<String, String> nameValues = AAIServiceUtils.keyToHashMap(key, ctx);
+ getLogger().debug("key = "+ nameValues.toString());
+
+ if(!AAIServiceUtils.isValidFormat(resource, nameValues)) {
+ ctx.setAttribute(String.format("%s.error.message", prefix), String.format("Resource %s is not supported. Key string contains invaid identifiers", resource));
+ return QueryStatus.FAILURE;
+ }
+
+ if(resource == null || resource.isEmpty() || AAIRequest.createRequest(resource, nameValues) == null) {
+ ctx.setAttribute(String.format("%s.error.message", prefix), String.format("Resource %s is not supported", resource));
+ return QueryStatus.FAILURE;
+ }
+
+ // process data using new model
+ boolean useNewModelProcessing = true;
+ // process server query by name the old way
+ if("vserver".equals(resource) || "vserver2".equals(resource)){
+ if(nameValues.containsKey("vserver_name") || nameValues.containsKey("vserver-name") || nameValues.containsKey("vserver.vserver_name") || nameValues.containsKey("vserver.vserver-name"))
+ useNewModelProcessing = false;
+ }
+ if("generic-vnf".equals(resource)){
+ if(nameValues.containsKey("vnf_name") || nameValues.containsKey("vnf-name") || nameValues.containsKey("generic_vnf.vnf_name") || nameValues.containsKey("generic-vnf.vnf-name"))
+ useNewModelProcessing = false;
+ }
+
+ // process data using new model
+ if(useNewModelProcessing && AAIRequest.createRequest(resource, nameValues) != null) {
+
+ try {
+ return newModelQuery(resource, localOnly, select, key, prefix, orderBy, ctx);
+ } catch (Exception exc) {
+ getLogger().warn("Failed query - returning FAILURE", exc);
+ return QueryStatus.FAILURE;
+ }
+ }
+
+ ObjectMapper mapper = AAIService.getObjectMapper();
+ Map<String,Object> attributes = new HashMap<>();
+
+ String modifier = null;
+
+ if(resource.contains(":")) {
+ String[] tokens = resource.split(":");
+ resource = tokens[0];
+ if(tokens.length > 1) {
+ modifier = tokens[1];
+ }
+ }
+
+ resource = resource.toLowerCase().replace("-", "_");
+
+ try {
+
+ switch(resource) {
+ case "generic_vnf":
+ vnfId = nameValues.get("vnf_id");
+ if(nameValues.containsKey("vnf_id"))
+ vnfId = nameValues.get("vnf_id");
+ else if(nameValues.containsKey("generic_vnf.vnf_name"))
+ vnfId = nameValues.get("generic_vnf.vserver_name");
+
+ if(nameValues.containsKey("vnf_name"))
+ vnfName = nameValues.get("vnf_name");
+ else if(nameValues.containsKey("generic_vnf.vnf_name"))
+ vnfName = nameValues.get("generic_vnf.vnf_name");
+
+ if(vnfId != null && !vnfId.isEmpty()) {
+ // at this point of the project this part should not be executed
+ vnfId = vnfId.trim().replace("'", "").replace("$", "").replace("'", "");
+ GenericVnf vnf = this.requestGenericVnfData(vnfId);
+ if(vnf == null) {
+ return QueryStatus.NOT_FOUND;
+ }
+
+ attributes = mapper.convertValue(vnf, attributes.getClass());
+ } else if(vnfName != null && !vnfName.isEmpty()) {
+ try {
+ vnfName = vnfName.trim().replace("'", "").replace("$", "").replace("'", "");
+ GenericVnf vnf = this.requestGenericVnfeNodeQuery(vnfName);
+ if(vnf == null) {
+ return QueryStatus.NOT_FOUND;
+ }
+ vnfId=vnf.getVnfId();
+ nameValues.put("vnf_id", vnfId);
+ attributes = mapper.convertValue(vnf, attributes.getClass());
+ } catch (AAIServiceException exc) {
+ int errorCode = exc.getReturnCode();
+ switch(errorCode) {
+ case 400:
+ case 404:
+ case 412:
+ break;
+ default:
+ getLogger().warn("Caught exception trying to refresh generic VNF", exc);
+ }
+ ctx.setAttribute(prefix + ".error.message", exc.getMessage());
+ if(errorCode >= 300) {
+ ctx.setAttribute(prefix + ".error.http.response-code",
+ Integer.toString(exc.getReturnCode()));
+ }
+ return QueryStatus.FAILURE;
+ }
+ } else {
+ getLogger().warn("No arguments are available to process generic VNF");
+ return QueryStatus.FAILURE;
+ }
+ break;
+ case "vserver":
+ case "vserver2":
+ String vserverName = null;
+ if(nameValues.containsKey("vserver_name"))
+ vserverName = nameValues.get("vserver_name");
+ else if(nameValues.containsKey("vserver.vserver_name"))
+ vserverName = nameValues.get("vserver.vserver_name");
+
+ String vserverId = null;
+ if(nameValues.containsKey("vserver_id"))
+ vserverId = nameValues.get("vserver_id");
+ if(nameValues.containsKey("vserver.vserver_id"))
+ vserverId = nameValues.get("vserver.vserver_id");
+ String tenantId = nameValues.get("teannt_id");
+
+ if(vserverName != null) vserverName = vserverName.trim().replace("'", "").replace("$", "").replace("'", "");
+ if(vserverId != null) vserverId = vserverId.trim().replace("'", "").replace("$", "").replace("'", "");
+ if(tenantId != null) tenantId = tenantId.trim().replace("'", "").replace("$", "").replace("'", "");
+
+ if (vserverName != null) {
+ URL vserverUrl = null;
+ try {
+ vserverUrl = this.requestVserverURLNodeQuery(vserverName);
+ } catch (AAIServiceException aaiexc) {
+ getLogger().warn(AAI_SERVICE_EXCEPTION, aaiexc);
+ ctx.setAttribute(prefix + ".error.message", aaiexc.getMessage());
+ if (aaiexc.getReturnCode() >= 300) {
+ ctx.setAttribute(prefix + ".error.http" + "" + ".response-code", Integer.toString(aaiexc.getReturnCode()));
+ }
+
+ if (aaiexc.getReturnCode() == 404)
+ return QueryStatus.NOT_FOUND;
+ else
+ return QueryStatus.FAILURE;
+ }
+ if (vserverUrl == null) {
+ return QueryStatus.NOT_FOUND;
+ }
+
+ tenantId = getTenantIdFromVserverUrl(vserverUrl);
+ String cloudOwner = getCloudOwnerFromVserverUrl(vserverUrl);
+ String cloudRegionId = getCloudRegionFromVserverUrl(vserverUrl);
+
+ Vserver vserver = null;
+ try {
+ vserver = this.requestVServerDataByURL(vserverUrl);
+ } catch (AAIServiceException aaiexc) {
+ getLogger().warn(AAI_SERVICE_EXCEPTION, aaiexc);
+ ctx.setAttribute(prefix + ".error.message", aaiexc.getMessage());
+ if (aaiexc.getReturnCode() >= 300) {
+ ctx.setAttribute(prefix + ".error.http" + ".response-code", Integer.toString(aaiexc.getReturnCode()));
+ }
+
+ if (aaiexc.getReturnCode() == 404)
+ return QueryStatus.NOT_FOUND;
+ else
+ return QueryStatus.FAILURE;
+ }
+ if (vserver == null) {
+ return QueryStatus.NOT_FOUND;
+ }
+ attributes = mapper.convertValue(vserver, attributes.getClass());
+ if (!attributes.containsKey("tenant-id") && tenantId != null) {
+ attributes.put("tenant-id", tenantId);
+ }
+ if (!attributes.containsKey("cloud-owner") && cloudOwner != null) {
+ attributes.put("cloud-owner", cloudOwner);
+ }
+ if (!attributes.containsKey("cloud-region-id") && cloudRegionId != null) {
+ attributes.put("cloud-region-id", cloudRegionId);
+ }
+ } else if (vserverId != null && tenantId != null) {
+ Vserver vserver = this.requestVServerData(tenantId, vserverId, "att-aic", "AAIAIC25");
+ if(vserver == null) {
+ return QueryStatus.NOT_FOUND;
+ }
+ attributes = mapper.convertValue(vserver, attributes.getClass());
+ if(!attributes.containsKey("tenant-id") && tenantId != null){
+ attributes.put("tenant-id", tenantId);
+ }
+ } else {
+ return QueryStatus.FAILURE;
+ }
+ break;
+
+ default:
+ return QueryStatus.FAILURE;
+ }
+
+ QueryStatus retval = QueryStatus.SUCCESS;
+
+ if (attributes == null || attributes.isEmpty()) {
+ retval = QueryStatus.NOT_FOUND;
+ getLogger().debug("No data found");
+ } else {
+ if (ctx != null) {
+ if (prefix != null) {
+ ArrayList<String> keys = new ArrayList<>(attributes.keySet());
+
+ int numCols = keys.size();
+
+ for (int i = 0; i < numCols; i++) {
+ String colValue;
+ String colName = keys.get(i);
+ Object object = attributes.get(colName);
+
+ if(object != null && object instanceof String) {
+ colValue = (String)object;
+
+ if (prefix != null) {
+ getLogger().debug("Setting "+prefix + "." + colName.replaceAll("_", "-")+" = "+ colValue);
+ ctx.setAttribute(prefix + "." + colName.replaceAll("_", "-"), colValue);
+ } else {
+ getLogger().debug("Setting " + colValue.replaceAll("_", "-")+" = "+colValue);
+ ctx.setAttribute(colValue.replaceAll("_", "-"), colValue);
+ }
+ } else if(object != null && object instanceof Map) {
+ if(colName.equals(modifier) || "relationship-list".equals(colName)){
+ String localNodifier = modifier;
+ if(localNodifier == null)
+ localNodifier = "relationship-list";
+ Map<String, Object> properties = (Map<String, Object>)object;
+ writeMap(properties, prefix+"."+localNodifier, ctx);
+ }
+ }
+ }
+ }
+ }
+ }
+ getLogger().debug("Query - returning " + retval);
+ return retval;
+
+ } catch (Exception exc) {
+ getLogger().warn("Failed query - returning FAILURE", exc);
+ return QueryStatus.FAILURE;
+ }
+ }
+
+
+ public void writeMap(Map<String, Object> properties, String prefix, SvcLogicContext ctx) {
+ Set<String> mapKeys = properties.keySet();
+
+ for(String mapKey : mapKeys) {
+ Object entity = properties.get(mapKey);
+ if(entity instanceof ArrayList) {
+ writeList((ArrayList<?>)entity, prefix + "." + mapKey, ctx);
+ } else
+ if(entity instanceof String || entity instanceof Long || entity instanceof Integer || entity instanceof Boolean) {
+ ctx.setAttribute(prefix + "." + mapKey, entity.toString());
+ getLogger().debug(prefix + "." + mapKey + " : " + entity.toString());
+ } else if(entity instanceof Map) {
+ String localPrefix = prefix;
+ if(mapKey != null) {
+ localPrefix = String.format("%s.%s", prefix, mapKey);
+ }
+ writeMap( (Map<String, Object>)entity, localPrefix, ctx);
+ }
+ }
+ }
+
+ private void writeList(ArrayList<?> list, String prefix, SvcLogicContext ctx) {
+ for(int i = 0; i < list.size(); i++ ) {
+ Object entity = list.get(i);
+ if(entity instanceof Map) {
+ writeMap( (Map<String, Object>)entity, prefix + "[" + i + "]", ctx);
+ } else
+ if(entity instanceof String || entity instanceof Long || entity instanceof Integer || entity instanceof Boolean) {
+ ctx.setAttribute(prefix, entity.toString());
+ getLogger().debug(prefix + " : " + entity.toString());
+ }
+ }
+
+ if(!list.isEmpty()) {
+ ctx.setAttribute(prefix + "_length", Integer.toString(list.size()));
+ getLogger().debug(prefix + "_length" + " : " + Integer.toString(list.size()));
+ }
+ }
+
+ @Override
+ public QueryStatus save(String resource, boolean force, boolean localOnly, String key, Map<String, String> params, String prefix, SvcLogicContext ctx)
+ throws SvcLogicException {
+
+ getLogger().debug("AAIService.save\tresource="+resource);
+ HashMap<String, String> nameValues = AAIServiceUtils.keyToHashMap(key, ctx);
+
+ if(!AAIServiceUtils.isValidFormat(resource, nameValues)) {
+ ctx.setAttribute(String.format("%s.error.message", prefix), String.format("Resource %s is not supported. Key string contains invaid identifiers", resource));
+ return QueryStatus.FAILURE;
+ }
+
+ if(resource == null || resource.isEmpty() || AAIRequest.createRequest(resource, nameValues) == null) {
+ getLogger().warn("AAIService.save has unspecified resource");
+ ctx.setAttribute(String.format("%s.error.message", prefix), String.format("Resource %s is not supported", resource));
+ return QueryStatus.FAILURE;
+ }
+ // keys passed
+ getLogger().debug("key = "+ Arrays.toString(nameValues.entrySet().toArray()));
+
+ // process params
+ if(params.containsKey("prefix")) {
+ Map<String, String> tmpParams = ctxGetBeginsWith(ctx, params.get("prefix"));
+ if(!tmpParams.isEmpty()) {
+ params.putAll(tmpParams);
+// params.remove("prefix");
+ }
+ }
+ // params passed
+ getLogger().debug("parms = "+ Arrays.toString(params.entrySet().toArray()));
+
+ boolean useNewModelProcessing = true;
+ // process server query by name the old way
+ if("vserver".equals(resource) || "vserver2".equals(resource)){
+ if(nameValues.containsKey("vserver-name")) {
+ useNewModelProcessing = false;
+ }
+
+ if(!params.containsKey("vserver-selflink")) {
+
+ AAIRequest request = AAIRequest.createRequest(resource, nameValues);
+ URL path = null;
+ try {
+ request.processRequestPathValues(nameValues);
+ path = request.getRequestUrl("GET", null);
+ params.put("vserver-selflink", path.toString());
+ } catch (UnsupportedEncodingException | MalformedURLException | URISyntaxException e) {
+ getLogger().warn("URL error Exception", e);
+ params.put("vserver-selflink", "/vserver");
+ }
+ }
+ }
+
+ // process data using new model
+ if(useNewModelProcessing && AAIRequest.createRequest(resource, nameValues) != null) {
+
+ try {
+ if(!resource.contains(":")){
+ return newModelSave(resource, force, key, params, prefix, ctx);
+ } else {
+ String[] tokens = resource.split(":");
+ String localResource = tokens[0];
+ String dependency = tokens[1];
+
+ AAIDatum instance = newModelObjectRequest( localResource, nameValues, prefix, ctx);
+ if(instance == null) {
+ return QueryStatus.NOT_FOUND;
+ }
+
+ switch(dependency){
+ case "relationship-list":
+ newModelProcessRelationshipList(instance, params, prefix, ctx);
+ break;
+ case "metadata":
+ newModelProcessMetadata(instance, params, prefix, ctx);
+ break;
+ }
+ // create a method to update relationship-list
+ AAIRequest request = AAIRequest.createRequest(localResource, nameValues);
+ request.setRequestObject(instance);
+ request.processRequestPathValues(nameValues);
+
+ getExecutor().post(request);
+ getLogger().debug("Save relationship list - returning SUCCESS");
+ return QueryStatus.SUCCESS;
+ }
+ } catch (Exception exc) {
+ ctx.setAttribute(prefix + ".error.message", exc.getMessage());
+ if(exc instanceof AAIServiceException) {
+ AAIServiceException aaiexc = (AAIServiceException)exc;
+ if(aaiexc.getReturnCode() >= 300) {
+ ctx.setAttribute(prefix + ".error.http" + ".response-code", Integer.toString(aaiexc.getReturnCode()));
+ }
+
+ if(aaiexc.getReturnCode() == 404) {
+ return QueryStatus.NOT_FOUND;
+ }
+ }
+ getLogger().warn("Failed save() - returning FAILURE", exc);
+ return QueryStatus.FAILURE;
+ }
+ } else {
+ getLogger().debug("Save() request for {} is not supported- returning FAILURE", resource);
+ return QueryStatus.FAILURE;
+ }
+ }
+
+ @Override
+ public QueryStatus update(String resource, String key, Map<String, String> params, String prefix, SvcLogicContext ctx) throws SvcLogicException {
+
+ resource = resource.toLowerCase();
+ HashMap<String, String> nameValues = AAIServiceUtils.keyToHashMap(key, ctx);
+ getLogger().debug("key = "+ Arrays.toString(nameValues.entrySet().toArray()));
+ if(!AAIServiceUtils.isValidFormat(resource, nameValues)) {
+ ctx.setAttribute(String.format("%s.error.message", prefix), String.format("Resource %s is not supported. Key string contains invaid identifiers", resource));
+ return QueryStatus.FAILURE;
+ }
+
+ if(resource == null || resource.isEmpty() || AAIRequest.createRequest(resource, nameValues) == null) {
+ ctx.setAttribute(String.format("%s.error.message", prefix), String.format("Resource %s is not supported", resource));
+ return QueryStatus.FAILURE;
+ }
+
+ // check if request is for groups
+ if(!AAIServiceUtils.containsResource(resource, nameValues)) {
+ ctx.setAttribute(String.format("%s.error.message", prefix), String.format("Resource %s is not permitted in 'update' operation", resource));
+ return QueryStatus.FAILURE;
+ }
+
+ getLogger().debug("parms = "+ Arrays.toString(params.entrySet().toArray()));
+
+ AAIRequest request = AAIRequest.createRequest(resource, nameValues);
+ request = new UpdateRequest(request, params);
+
+ String[] arguments = request.getArgsList();
+ for(String name : arguments) {
+ String modifiedKey = name.replaceAll("-", "_");
+ if(nameValues.containsKey(modifiedKey)) {
+ String argValue = nameValues.get(modifiedKey);
+ if(argValue != null) argValue = argValue.trim().replace("'", "").replace("$", "").replace("'", "");
+ request.addRequestProperty(name, argValue);
+ }
+ }
+
+ try {
+ QueryStatus retval = QueryStatus.SUCCESS;
+
+ retval = newModelQuery(resource, false, null, key, "tmpDelete", null, ctx);
+
+ if(retval == null || retval != QueryStatus.SUCCESS) {
+ return retval;
+ }
+
+ String resourceVersion = ctx.getAttribute("tmpDelete.resource-version");
+ if(resourceVersion == null) {
+ return QueryStatus.NOT_FOUND;
+ }
+ params.put("resource-version", resourceVersion);
+
+ request.processRequestPathValues(nameValues);
+ getExecutor().patch(request, resourceVersion);
+ } catch(AAIServiceException aaiexc) {
+ getLogger().warn(AAI_SERVICE_EXCEPTION, aaiexc);
+ if(aaiexc.getReturnCode() == 404)
+ return QueryStatus.NOT_FOUND;
+ else
+ return QueryStatus.FAILURE;
+ } catch (Exception exc) {
+ getLogger().warn("Failed update - returning FAILURE", exc);
+ return QueryStatus.FAILURE;
+ }
+
+ getLogger().debug("Update - returning SUCCESS");
+ return QueryStatus.SUCCESS;
+ }
+
+ @Override
+ public QueryStatus delete(String resource, String key, SvcLogicContext ctx) throws SvcLogicException {
+ getLogger().debug("AAIService.delete\tresource="+resource);
+ HashMap<String, String> nameValues = AAIServiceUtils.keyToHashMap(key, ctx);
+ getLogger().debug("key = "+ Arrays.toString(nameValues.entrySet().toArray()));
+
+ if(!AAIServiceUtils.isValidFormat(resource, nameValues)) {
+ ctx.setAttribute(String.format("%s.error.message", "aaiData"), String.format("Resource %s is not supported. Key string contains invaid identifiers", resource));
+ return QueryStatus.FAILURE;
+ }
+
+ if(resource == null || resource.isEmpty() || AAIRequest.createRequest(resource, nameValues) == null) {
+ ctx.setAttribute(String.format("%s.error.message", "tmpDelete"), String.format("Resource %s is not supported", resource));
+ return QueryStatus.FAILURE;
+ }
+
+ // check if request is for groups
+ if(!AAIServiceUtils.containsResource(resource, nameValues)) {
+ ctx.setAttribute(String.format("%s.error.message", "tmpDelete"), String.format("Resource %s is not permitted in 'delete' operation", resource));
+ return QueryStatus.FAILURE;
+ }
+
+ if(AAIRequest.createRequest(resource, nameValues) != null) {
+ if(resource.contains(":")) {
+ switch (resource.split(":")[1]){
+ case "relationship-list":
+ return processDeleteRelationshipList(resource, key, ctx, nameValues);
+ case "metadata":
+ return processDeleteMetadata(resource, key, ctx, nameValues);
+ }
+ }
+
+
+ try {
+ QueryStatus retval = QueryStatus.SUCCESS;
+
+ retval = newModelQuery(resource, false, null, key, "tmpDelete", null, ctx);
+
+ if(retval == null || retval != QueryStatus.SUCCESS) {
+ return retval;
+ }
+
+ String resourceVersion = ctx.getAttribute("tmpDelete.resource-version");
+ if(resourceVersion == null) {
+ return QueryStatus.NOT_FOUND;
+ }
+
+ try {
+ AAIRequest request = AAIRequest.createRequest(resource, nameValues);
+ if(request == null) {
+ return QueryStatus.FAILURE;
+ }
+
+ request.processRequestPathValues(nameValues);
+
+ if(getExecutor().delete(request, resourceVersion)) {
+ return QueryStatus.SUCCESS;
+ }
+ } catch(AAIServiceException aaiexc) {
+ getLogger().warn(AAI_SERVICE_EXCEPTION, aaiexc);
+ if(aaiexc.getReturnCode() == 404)
+ return QueryStatus.NOT_FOUND;
+ else
+ return QueryStatus.FAILURE;
+
+ } catch (Exception exc) {
+ getLogger().warn("requestGenericVnfData", exc);
+ return QueryStatus.FAILURE;
+ }
+
+ } catch (Exception exc) {
+ getLogger().warn("Failed delete - returning FAILURE", exc);
+ return QueryStatus.FAILURE;
+ }
+ } else {
+ String resourceName = resource;
+ String identifier = null;
+
+ if(resourceName.contains(":")) {
+ String[] tokens = resourceName.split(":");
+ if(tokens != null && tokens.length > 0) {
+ resourceName = tokens[0];
+ identifier = tokens[1];
+ }
+ }
+ if("relationship-list".equals(identifier) || "relationshipList".equals(identifier)) {
+// RelationshipRequest relationshipRequest = new RelationshipRequest();
+ if("generic-vnf".equals(resourceName)){
+ String vnfId = nameValues.get("vnf_id");
+ String relatedTo = nameValues.get("related_to");
+ vnfId = vnfId.trim().replace("'", "").replace("$", "").replace("'", "");
+ relatedTo = relatedTo.trim().replace("'", "").replace("$", "").replace("'", "");
+
+ GenericVnf vnf;
+ try {
+ vnf = this.requestGenericVnfData(vnfId);
+ if(vnf == null)
+ return QueryStatus.NOT_FOUND;
+ } catch (AAIServiceException exc) {
+ getLogger().warn("Failed delete - returning NOT_FOUND", exc);
+ return QueryStatus.NOT_FOUND;
+ }
+ boolean itemRemoved = false;
+ RelationshipList relationshipList = vnf.getRelationshipList();
+ List<Relationship> relationships = relationshipList.getRelationship();
+ List<Relationship> iterableList = new LinkedList<>(relationships);
+ for(Relationship relationship : iterableList) {
+ if(relationship.getRelatedTo().equals(relatedTo)) {
+ relationships.remove(relationship);
+ itemRemoved = true;
+ }
+ }
+
+ if(!itemRemoved)
+ return QueryStatus.NOT_FOUND;
+ try {
+ this.postGenericVnfData(vnf.getVnfId(), vnf);
+ } catch (AAIServiceException exc) {
+ if(exc.getReturnCode() == 404){
+ return QueryStatus.NOT_FOUND;
+ } else {
+ getLogger().warn("Failed delete - returning FAILURE", exc);
+ return QueryStatus.FAILURE;
+ }
+ }
+ return QueryStatus.SUCCESS;
+ }
+ }
+ }
+ return QueryStatus.FAILURE;
+ }
+
+ @Override
+ public QueryStatus exists(String resource, String key, String prefix, SvcLogicContext ctx) throws SvcLogicException {
+ return query(resource, false, null, key, prefix, null, ctx);
+ }
+
+ @Override
+ public QueryStatus isAvailable(String arg0, String arg1, String arg2, SvcLogicContext arg3)
+ throws SvcLogicException {
+ throw new SvcLogicException("Method AAIService.isAvailable() has not been implemented yet");
+ }
+
+ @Override
+ public QueryStatus notify(String resource, String action, String key, SvcLogicContext ctx) throws SvcLogicException {
+ throw new SvcLogicException("Method AAIService.notify() has not been implemented yet");
+ }
+
+ // @Override
+ public QueryStatus newModelQuery(String resource, boolean localOnly, String select, String key, String prefix, String orderBy, SvcLogicContext ctx) {
+
+ QueryStatus retval = QueryStatus.SUCCESS;
+ String modifier = null;
+
+ HashMap<String, String> nameValues = AAIServiceUtils.keyToHashMap(key, ctx);
+ if(resource.contains(":")) {
+ modifier = resource.split(":")[1];
+ }
+
+ try {
+ AAIRequest request = AAIRequest.createRequest(resource, nameValues);
+ if(request == null) {
+ return QueryStatus.FAILURE;
+ }
+
+ Map<String, String> params = new HashMap<>();
+
+ request.processRequestPathValues(nameValues);
+ if(nameValues.containsKey("prefix")){
+ Map<String, String> tmpParams = ctxGetBeginsWith(ctx, nameValues.get("prefix"));
+ if(!tmpParams.isEmpty()) {
+ params.putAll(tmpParams);
+ }
+ }
+ String rv = getExecutor().get(request);
+
+ retval = processResponseData(rv, resource, request, prefix, ctx, nameValues, modifier);
+
+ } catch(AAIServiceException aaiexc) {
+ getLogger().warn(AAI_SERVICE_EXCEPTION, aaiexc);
+ int errorCode = aaiexc.getReturnCode();
+ ctx.setAttribute(prefix + ".error.message", aaiexc.getMessage());
+ if(errorCode >= 300) {
+ ctx.setAttribute(prefix + ".error.http.response-code",
+ Integer.toString(aaiexc.getReturnCode()));
+ }
+
+ if(aaiexc.getReturnCode() == 404)
+ return QueryStatus.NOT_FOUND;
+
+ return QueryStatus.FAILURE;
+ } catch (Exception exc) {
+ getLogger().warn("requestGenericVnfData", exc);
+ ctx.setAttribute(prefix + ".error.message", exc.getMessage());
+ return QueryStatus.FAILURE;
+ }
+
+ return retval;
+ }
+
+ public QueryStatus processResponseData(String rv, String resource, AAIRequest request, String prefix, SvcLogicContext ctx, Map<String, String> nameValues, String modifier) throws JsonParseException, JsonMappingException, IOException, AAIServiceException
+ {
+ Object response;
+
+ if(rv == null) {
+ return QueryStatus.NOT_FOUND;
+ }
+
+ response = request.jsonStringToObject(rv);
+ if(response == null) {
+ return QueryStatus.NOT_FOUND;
+ }
+
+ if("generic-query".equals(resource)) {
+ SearchResults rd = SearchResults.class.cast(response);
+ List<ResultData> rdList = rd.getResultData();
+ if(rdList == null || rdList.isEmpty()) {
+ return QueryStatus.NOT_FOUND;
+ }
+ ResultData rDatum = rdList.get(0);
+ nameValues.put("selflink", rDatum.getResourceLink());
+ AAIRequest req2 = AAIRequest.createRequest(rDatum.getResourceType(), nameValues);
+ req2.processRequestPathValues(nameValues);
+ rv = getExecutor().get(req2);
+ if(rv == null) {
+ return QueryStatus.NOT_FOUND;
+ }
+
+ response = req2.jsonStringToObject(rv);
+ if(response == null) {
+ return QueryStatus.NOT_FOUND;
+ }
+ }
+
+ if("nodes-query".equals(resource)) {
+ SearchResults rd = SearchResults.class.cast(response);
+ List<ResultData> rdList = rd.getResultData();
+ if(rdList == null || rdList.isEmpty()) {
+ return QueryStatus.NOT_FOUND;
+ }
+ ResultData rDatum = rdList.get(0);
+ response = rDatum;
+ }
+
+ if("formatted-query".equals(resource) || "custom-query".equals(resource)) {
+ FormattedQueryResultList rd = FormattedQueryResultList.class.cast(response);
+ List<Result> iRIlist = rd.getResults();
+ if(iRIlist == null || iRIlist.isEmpty()) {
+ return QueryStatus.NOT_FOUND;
+ }
+ }
+
+ // process relationship list
+ // this is a temporary soluton to address the realationship handling changes added in Release 17.07
+ try {
+ Class<?> clazz = response.getClass();
+ Method getter = clazz.getMethod("getRelationshipList");
+ Object obj = getter.invoke(response);
+ if(obj != null && obj instanceof RelationshipList) {
+ RelationshipList list = RelationshipList.class.cast(obj);
+ AAIServiceUtils.populateRelationshipDataFromPath(list);
+ }
+ } catch(Exception exc) {
+ getLogger().debug(RELATIONSHIP_DATA + exc.getMessage());
+ }
+
+ String preFix;
+ if(prefix == null || prefix.isEmpty()) {
+ preFix = "";
+ } else {
+ preFix = prefix + ".";
+ }
+
+ Map<String,Object> props = objectToProperties(response);
+ Set<String> keys = props.keySet();
+ for(String theKey: keys) {
+ if(getLogger().isTraceEnabled())
+ getLogger().trace(theKey);
+
+ Object value = props.get(theKey);
+ if(value == null)
+ continue;
+ Object type = value.getClass();
+ if(value instanceof String) {
+ ctx.setAttribute(preFix + theKey, value.toString());
+ continue;
+ }
+ if(value instanceof Boolean) {
+ ctx.setAttribute(preFix + theKey, value.toString());
+ continue;
+ }
+ if(value instanceof Integer) {
+ ctx.setAttribute(preFix + theKey, value.toString());
+ continue;
+ }
+ if(value instanceof Long) {
+ ctx.setAttribute(preFix + theKey, value.toString());
+ continue;
+ }
+
+ if(value instanceof ArrayList) {
+ ArrayList<?> array = ArrayList.class.cast(value);
+ for(int i = 0; i < array.size(); i++) {
+ writeList(array, String.format("%s.%s", prefix, theKey), ctx);
+ }
+ continue;
+ }
+
+ if("relationship-list".equals(theKey)){
+ Map<String, Object> relationshipList = (Map<String, Object>)value;
+ // we are interested in seeing just the selected relationship
+ if(theKey.equals(modifier)) {
+ List<?> relationships = (List<?>)relationshipList.get("relationship");
+ if(relationships != null && !relationships.isEmpty()) {
+
+ List newRelationships = new LinkedList();
+ newRelationships.addAll(relationships);
+
+ for(Object obj : newRelationships){
+ if(obj instanceof Map<?, ?>) {
+ Map<?, ?> relProperties = (Map<?, ?>)obj;
+ if(relProperties.containsKey("related-to")) {
+ Object relPropsRelatedTo = relProperties.get("related-to");
+
+ String relatedTo = nameValues.get("related_to");
+ if(relatedTo != null) {
+ relatedTo = relatedTo.trim().replace("'", "").replace("$", "").replace("'", "");
+ if(!relatedTo.equals(relPropsRelatedTo)) {
+ relationships.remove(relProperties);
+ }
+ continue;
+ } else {
+ continue;
+ }
+ }
+ }
+ }
+ }
+ }
+ writeMap(relationshipList, String.format("%s.%s", prefix, theKey), ctx);
+ continue;
+ }
+
+ if(value instanceof Map) {
+ Map<String, Object> subnetsList = (Map<String, Object>)value;
+ writeMap(subnetsList, String.format("%s.%s", prefix, theKey), ctx);
+ continue;
+ }
+
+ }
+ return QueryStatus.SUCCESS;
+ }
+
+
+ public QueryStatus newModelBackupRequest(String resource, Map<String, String> params, String prefix, SvcLogicContext ctx) {
+
+ QueryStatus retval = QueryStatus.SUCCESS;
+ HashMap<String, String> nameValues = new HashMap<>();
+
+ try {
+ AAIRequest request = AAIRequest.createRequest(resource, nameValues);
+ if(request == null) {
+ return QueryStatus.FAILURE;
+ }
+
+ boolean argsFound = false;
+ String[] arguments = request.getArgsList();
+ for(String name : arguments) {
+ String tmpName = name.replaceAll("-", "_");
+ String value = params.get(tmpName);
+ if(value != null && !value.isEmpty()) {
+ value = value.trim().replace("'", "").replace("$", "").replace("'", "");
+ request.addRequestProperty(name, value);
+ argsFound = true;
+ }
+ }
+ if(!argsFound) {
+ getLogger().warn("No arguments were found. Terminating backup request.");
+ return QueryStatus.FAILURE;
+ }
+
+ String rv = getExecutor().get(request);
+ ctx.setAttribute(prefix, rv);
+ } catch(AAIServiceException aaiexc) {
+ getLogger().warn(AAI_SERVICE_EXCEPTION, aaiexc);
+ if(aaiexc.getReturnCode() == 404)
+ return QueryStatus.NOT_FOUND;
+
+ return QueryStatus.FAILURE;
+ } catch (Exception exc) {
+ getLogger().warn("newModelBackupRequest", exc);
+ return QueryStatus.FAILURE;
+ }
+
+ return retval;
+ }
+
+ public AAIDatum newModelObjectRequest(String resource, Map<String, String> params, String prefix, SvcLogicContext ctx)
+ throws AAIServiceException {
+
+ AAIDatum response = null;
+
+ try {
+ AAIRequest request = AAIRequest.createRequest(resource, params);
+ if(request == null) {
+ return null;
+ }
+
+ request.processRequestPathValues(params);
+ String rv = getExecutor().get(request);
+ response = request.jsonStringToObject(rv);
+ } catch(AAIServiceException aaiexc) {
+ throw aaiexc;
+ } catch (Exception exc) {
+ getLogger().warn("newModelBackupRequest", exc);
+ throw new AAIServiceException(exc);
+ }
+
+ return response;
+ }
+
+
+ @Override
+ public QueryStatus release(String arg0, String arg1, SvcLogicContext arg2) throws SvcLogicException {
+ throw new SvcLogicException("Method AAIService.release() has not been implemented yet");
+ }
+
+ @Override
+ public QueryStatus reserve(String arg0, String arg1, String arg2, String arg3, SvcLogicContext arg4)
+ throws SvcLogicException {
+ throw new SvcLogicException("Method AAIService.reserve() has not been implemented yet");
+ }
+
+ private QueryStatus newModelSave(String resource, boolean force, String key, Map<String, String> params, String prefix, SvcLogicContext ctx) {
+ getLogger().debug("Executing newModelSave for resource : " + resource);
+ HashMap<String, String> nameValues = AAIServiceUtils.keyToHashMap(key, ctx);
+
+ try {
+ ArrayList<String> subResources = new ArrayList<>();
+ Set<String> set = params.keySet();
+ Map<String, Method> setters = new HashMap<>();
+ Map<String, Method> getters = new HashMap<>();
+
+ // 1. find class
+ AAIRequest request = AAIRequest.createRequest(resource, nameValues);
+ Class<? extends AAIDatum> resourceClass = request.getModelClass();
+ getLogger().debug(resourceClass.getName());
+ AAIDatum instance = resourceClass.newInstance();
+
+ {
+ Annotation[] annotations = resourceClass.getAnnotations();
+ for(Annotation annotation : annotations) {
+ Class<? extends Annotation> anotationType = annotation.annotationType();
+ String annotationName = anotationType.getName();
+
+ // 2. find string property setters and getters for the lists
+ if("javax.xml.bind.annotation.XmlType".equals(annotationName)){
+ XmlType order = (XmlType)annotation;
+ String[] values = order.propOrder();
+ for(String value : values) {
+ String id = AAIServiceUtils.camelCaseToDashedString(value);
+ Field field = resourceClass.getDeclaredField(value);
+ Class<?> type = field.getType();
+
+ try {
+ if(type.getName().startsWith("java.lang") || "boolean".equals(type.getName()) || "long".equals(type.getName()) || "int".equals(type.getName())) {
+ try {
+ Method setter = resourceClass.getMethod("set"+StringUtils.capitalize(value), type);
+ Object arglist[] = new Object[1];
+ arglist[0] = params.get(id);
+
+ if(arglist[0] != null) {
+ if(!type.getName().equals("java.lang.String")) {
+// getLogger().debug(String.format("Processing %s with parameter %s", types[0].getName(), value));
+ if("java.lang.Long".equals(type.getName()) || "java.lang.Integer".equals(type.getName())) {
+ String fv = params.get(id);
+ if(fv == null || fv.isEmpty()) {
+ arglist[0] = null;
+ } else {
+ arglist[0] = valueOf(type, params.get(id));
+ }
+ } else if("boolean".equals(type.getName())) {
+ arglist[0] = valueOf(Boolean.class, params.get(id));
+ } else if("int".equals(type.getName())) {
+ arglist[0] = valueOf(Integer.class, params.get(id));
+ } else if("long".equals(type.getName())) {
+ String fv = params.get(id);
+ if(fv == null || fv.isEmpty()) {
+ arglist[0] = null;
+ } else {
+ arglist[0] = valueOf(Long.class, params.get(id));
+ }
+ } else {
+ arglist[0] = valueOf(type, params.get(id));
+ }
+ }
+ Object obj = setter.invoke(instance, arglist);
+ }
+ set.remove(id);
+
+ } catch (Exception x) {
+ Throwable cause = x.getCause();
+ getLogger().warn("Failed process for " + resourceClass.getName(), x);
+ }
+ } else if("java.util.List".equals(type.getName())) {
+ List<String> newValues = new ArrayList<>();
+ String length = id+"_length";
+ if(!params.isEmpty() && params.containsKey(length)) {
+ String tmp = params.get(length);
+ int count = Integer.parseInt(tmp);
+ for(int i=0; i<count; i++) {
+ String tmpValue = params.get(String.format("%s[%d]", id, i));
+ newValues.add(tmpValue);
+ }
+ if(!newValues.isEmpty()) {
+ Method setter = findSetterFor(resourceClass, value);
+ if(setter != null) {
+ Object o = setter.invoke(instance, newValues);
+ } else {
+ try {
+ Method listGetter = resourceClass.getMethod("get"+StringUtils.capitalize(value));
+ Object o = listGetter.invoke(instance);
+ if(o != null && o instanceof java.util.List ) {
+ List innerList = List.class.cast(o);
+ innerList.addAll(newValues);
+ }
+ } catch(NoSuchMethodException nsme) {
+ getLogger().warn(AAI_SERVICE_EXCEPTION, nsme);
+ }
+ }
+ }
+ }
+ set.remove(id);
+ } else {
+ Method setter = resourceClass.getMethod("set"+StringUtils.capitalize(value), type);
+ setters.put(id, setter);
+ }
+ } catch(Exception exc) {
+ getLogger().warn(AAI_SERVICE_EXCEPTION, exc);
+ }
+
+ Method getter;
+ try {
+ getter = resourceClass.getMethod("get"+StringUtils.capitalize(value));
+ if(!type.getName().equals("java.lang.String")) {
+ getters.put(id, getter);
+ }
+ } catch(NoSuchMethodException exc) {
+ try {
+ if(type.getName().equals("java.lang.Boolean")) {
+ getter = resourceClass.getMethod("is"+StringUtils.capitalize(value));
+ getters.put(id, getter);
+ } else {
+ getLogger().warn(AAI_SERVICE_EXCEPTION, exc);
+ }
+ } catch(Exception iexc) {
+ getLogger().warn(AAI_SERVICE_EXCEPTION, iexc);
+ }
+ } catch(Exception exc) {
+ getLogger().warn(AAI_SERVICE_EXCEPTION, exc);
+ }
+
+ }
+ subResources.addAll(Arrays.asList(values));
+ }
+ }
+ }
+
+ // remove getters that have matching setter
+ for(String setKey : setters.keySet()) {
+ if(getters.containsKey(setKey)) {
+ getters.remove(setKey);
+ }
+ }
+
+ Set<String> relationshipKeys = new TreeSet<>();
+ Set<String> vlansKeys = new TreeSet<>();
+ Set<String> metadataKeys = new TreeSet<>();
+
+ for(String attribute : set) {
+ String value = params.get(attribute);
+ if(attribute.startsWith("relationship-list")) {
+ relationshipKeys.add(attribute);
+ } else if(attribute.startsWith("vlans")) {
+ vlansKeys.add(attribute);
+ } else if(attribute.startsWith("metadata")) {
+ metadataKeys.add(attribute);
+ }
+ }
+ // 3. find list property getters
+ for(String attribute : set) {
+ String value = params.get(attribute);
+ Method method = getters.get(attribute);
+ if(method != null) {
+ try {
+ Object arglist[] = new Object[0];
+// arglist[0] = value;
+ Class<?>[] types = method.getParameterTypes();
+ if(types.length == 0){
+ Object o = method.invoke(instance, arglist);
+ if(o instanceof ArrayList) {
+ ArrayList<String> values = (ArrayList<String>)o;
+ value = value.replace("[", "").replace("]", "");
+ List<String> items = Arrays.asList(value.split("\\s*,\\s*"));
+ for(String s : items) {
+ values.add(s.trim());
+ }
+ }
+ }
+ } catch (Exception x) {
+ Throwable cause = x.getCause();
+ getLogger().warn("Failed process for " + resourceClass.getName(), x);
+ }
+ }
+ }
+ // 4. Process Relationships
+ // add relationship list
+ if( (subResources.contains("relationship-list") || subResources.contains("relationshipList")) && !relationshipKeys.isEmpty()) {
+ RelationshipList relationshipList = null;
+ Object obj = null;
+ Method getRelationshipListMethod = null;
+ try {
+ getRelationshipListMethod = resourceClass.getMethod("getRelationshipList");
+ } catch(Exception exc) {
+ getLogger().debug(RELATIONSHIP_DATA + exc.getMessage());
+ }
+
+ if(getRelationshipListMethod != null){
+ try {
+ obj = getRelationshipListMethod.invoke(instance);
+ } catch (InvocationTargetException x) {
+ Throwable cause = x.getCause();
+ }
+ }
+ if(obj != null && obj instanceof RelationshipList){
+ relationshipList = (RelationshipList)obj;
+ } else {
+ relationshipList = new RelationshipList();
+ Method setRelationshipListMethod = resourceClass.getMethod("setRelationshipList", RelationshipList.class);
+ if(setRelationshipListMethod != null){
+ try {
+ Object arglist[] = new Object[1];
+ arglist[0] = relationshipList;
+
+ obj = setRelationshipListMethod.invoke(instance, arglist);
+ } catch (InvocationTargetException x) {
+ Throwable cause = x.getCause();
+ }
+ }
+ }
+
+ List<Relationship> relationships = relationshipList.getRelationship();
+
+ int i = 0;
+ while(true){
+ String searchKey = "relationship-list.relationship[" + i + "].related-to";
+ if(!params.containsKey(searchKey))
+ break;
+ int j = 0;
+ String relatedTo = params.get(searchKey);
+ String relatedLinkKey = "relationship-list.relationship[" + i + "].related-link";
+ String relatedLink = null;
+ if(params.containsKey(relatedLinkKey)) {
+ relatedLink = params.get(relatedLinkKey);
+ }
+ Relationship relationship = new Relationship();
+ relationships.add(relationship);
+ relationship.setRelatedTo(relatedTo);
+ String relationshipLabel = "relationship-list.relationship[" + i + "].relationship-label";
+ if(params.containsKey(searchKey)) {
+ relationship.setRelationshipLabel(params.get(relationshipLabel));
+ }
+ getLogger().debug("About to process related link of {}", relatedLink);
+ if(relatedLink != null) {
+ if(relatedLink.contains("v$"))
+ relatedLink = relatedLink.replace(VERSION_PATTERN, "/v21/");
+ relationship.setRelatedLink(relatedLink);
+ } else {
+ Map<String, String> relParams = new HashMap<>();
+
+ while(true) {
+ String searchRelationshipKey = "relationship-list.relationship[" + i + "].relationship-data[" + j + "].relationship-key";
+ String searchRelationshipValue = "relationship-list.relationship[" + i + "].relationship-data[" + j + "].relationship-value";
+ if(!params.containsKey(searchRelationshipKey))
+ break;
+
+ relParams.put(params.get(searchRelationshipKey), params.get(searchRelationshipValue));
+ j++;
+ }
+ AAIRequest rlRequest = AAIRequest.createRequest(relatedTo, relParams);
+ for(Map.Entry<String,String> entry : relParams.entrySet()) {
+ rlRequest.addRequestProperty(entry.getKey(), entry.getValue());
+ }
+ String path = rlRequest.updatePathDataValues(null);
+ relationship.setRelatedLink(path);
+ }
+ {
+ int k = 0;
+ // process related to properties
+ Map<String, String> relParams = new HashMap<String, String>();
+
+ while(true) {
+ String searchRelatedToKey = "relationship-list.relationship[" + i + "].related-to-property[" + k + "].property-key";
+ String searchRelatedToValue = "relationship-list.relationship[" + i + "].related-to-property[" + k + "].property-value";
+ if(!params.containsKey(searchRelatedToKey))
+ break;
+
+ RelatedToProperty relDatum = new RelatedToProperty();
+ relDatum.setPropertyKey(params.get(searchRelatedToKey));
+ relDatum.setPropertyValue(params.get(searchRelatedToValue));
+ relationship.getRelatedToProperty().add(relDatum);
+
+ relParams.put(params.get(searchRelatedToKey), params.get(searchRelatedToValue));
+ k++;
+ }
+ }
+ i++;
+ }
+ }
+
+ // 4. vlans
+ if(subResources.contains("vlans") && !vlansKeys.isEmpty()) {
+ Object obj = null;
+ Vlans vlanList = null;
+ Method getVLansMethod = resourceClass.getMethod("getVlans");
+ if(getVLansMethod != null){
+ try {
+ obj = getVLansMethod.invoke(instance);
+ } catch (InvocationTargetException x) {
+ Throwable cause = x.getCause();
+ }
+ }
+ if(obj != null && obj instanceof Vlans){
+ vlanList = (Vlans)obj;
+ } else {
+ vlanList = new Vlans();
+ Method setVlansMethod = resourceClass.getMethod("setVlans", Vlans.class);
+ if(setVlansMethod != null){
+ try {
+ Object arglist[] = new Object[1];
+ arglist[0] = vlanList;
+
+ obj = setVlansMethod.invoke(instance, arglist);
+ } catch (InvocationTargetException x) {
+ Throwable cause = x.getCause();
+ }
+ }
+ }
+
+ int i = 0;
+ while(true){
+ String searchKey = "vlans.vlan[" + i + "].vlan-interface";
+ if(!params.containsKey(searchKey))
+ break;
+
+ String vlanInterface = params.get("vlans.vlan[" + i + "].vlan-interface");
+ String vlanIdInner = params.get("vlans.vlan[" + i + "].vlan-id-inner");
+ String vlanIdOute = params.get("vlans.vlan[" + i + "].vlan-id-outer");
+ String speedValue = params.get("vlans.vlan[" + i + "].speed-value");
+ String speedUnits = params.get("vlans.vlan[" + i + "].speed-units");
+
+ Vlan vlan = new Vlan();
+ vlan.setVlanInterface(vlanInterface);
+
+ if(vlanIdInner != null) {
+ Long iVlanIdInner = Long.parseLong(vlanIdInner);
+ vlan.setVlanIdInner(iVlanIdInner);
+ }
+
+ if(vlanIdOute != null) {
+ Long iVlanIdOuter = Long.parseLong(vlanIdOute);
+ vlan.setVlanIdOuter(iVlanIdOuter);
+ }
+
+ if(speedValue != null) {
+ vlan.setSpeedValue(speedValue);
+ vlan.setSpeedUnits(speedUnits);
+ }
+
+ vlanList.getVlan().add(vlan);
+ i++;
+ }
+ }
+
+ // 5. metadata
+ if(subResources.contains("metadata") && !metadataKeys.isEmpty()) {
+ Object obj = null;
+ Metadata metadataList = null;
+ Method getMetadataMethod = resourceClass.getMethod("getMetadata");
+ if(getMetadataMethod != null){
+ try {
+ obj = getMetadataMethod.invoke(instance);
+ } catch (InvocationTargetException x) {
+ Throwable cause = x.getCause();
+ }
+ }
+ if(obj != null && obj instanceof Metadata){
+ metadataList = (Metadata)obj;
+ } else {
+ metadataList = new Metadata();
+ Method setMetadataMethod = resourceClass.getMethod("setMetadata", Metadata.class);
+ if(setMetadataMethod != null){
+ try {
+ Object arglist[] = new Object[1];
+ arglist[0] = metadataList;
+
+ obj = setMetadataMethod.invoke(instance, arglist);
+ } catch (InvocationTargetException x) {
+ Throwable cause = x.getCause();
+ }
+ }
+ }
+
+ // process data
+ int i = 0;
+ while(true){
+ String metaKey = "metadata.metadatum[" + i + "].meta-key";
+ if(!params.containsKey(metaKey))
+ break;
+
+ String metaValue = params.get("metadata.metadatum[" + i + "].meta-value");
+
+ Metadatum vlan = new Metadatum();
+ vlan.setMetaname(metaKey);
+ vlan.setMetaval(metaValue);
+
+ metadataList.getMetadatum().add(vlan);
+ i++;
+ }
+
+ }
+
+
+ // 6. Prepare AAI request
+ String[] args = request.getArgsList();
+ for(String arg : args) {
+ String modifiedKey = arg.replaceAll("-", "_");
+ if(nameValues.containsKey(modifiedKey)) {
+ String argValue = nameValues.get(modifiedKey);
+ if(argValue != null) argValue = argValue.trim().replace("'", "").replace("$", "").replace("'", "");
+ request.addRequestProperty(arg, argValue);
+ }
+ }
+
+ request.processRequestPathValues(nameValues);
+ request.setRequestObject(instance);
+ Object response = getExecutor().post(request);
+ if(request.expectsDataFromPUTRequest()){
+ if(response != null && response instanceof String) {
+ String rv = response.toString();
+ QueryStatus retval = processResponseData(rv, resource, request, prefix, ctx, nameValues, null);
+ getLogger().debug("newModelSave - returning " + retval.toString());
+ return retval;
+ }
+ }
+
+ } catch(AAIServiceException exc){
+ ctx.setAttribute(prefix + ".error.message", exc.getMessage());
+ int returnCode = exc.getReturnCode();
+ if(returnCode >= 300) {
+ ctx.setAttribute(prefix + ".error.http.response-code",
+ Integer.toString(exc.getReturnCode()));
+ }
+
+ if(returnCode == 400 || returnCode == 412)
+ return QueryStatus.FAILURE;
+ else if(returnCode == 404)
+ return QueryStatus.NOT_FOUND;
+ else {
+ getLogger().warn("Failed newModelSave - returning FAILURE", exc);
+ return QueryStatus.FAILURE;
+ }
+ } catch(Exception exc){
+ getLogger().warn("Failed newModelSave - returning FAILURE", exc);
+ ctx.setAttribute(prefix + ".error.message", exc.getMessage());
+ return QueryStatus.FAILURE;
+ }
+
+ getLogger().debug("newModelSave - returning SUCCESS");
+ return QueryStatus.SUCCESS;
+ }
+
+ private Method findSetterFor(Class<? extends AAIDatum> resourceClass, String value) {
+ try {
+ String setterName = "set"+StringUtils.capitalize(value);
+ for (Method method : resourceClass.getDeclaredMethods()) {
+ int modifiers = method.getModifiers();
+ if (Modifier.isPublic(modifiers) && setterName.contentEquals(method.getName())) {
+ return method;
+ }
+ }
+ } catch(Exception exc) {
+ getLogger().warn("findSetterFor()", exc);
+ }
+ return null;
+ }
+
+ private QueryStatus newModelProcessRelationshipList(Object instance, Map<String, String> params, String prefix, SvcLogicContext ctx) throws Exception {
+
+ Class resourceClass = instance.getClass();
+
+ Set<String> relationshipKeys = new TreeSet<>();
+
+ Set<String> set = params.keySet();
+
+ for(String attribute : set) {
+ String value = params.get(attribute);
+
+ if(attribute.startsWith("relationship-list")) {
+ relationshipKeys.add(attribute);
+ }
+ }
+
+ // 3. Process Relationships
+ // add relationship list
+ if(!relationshipKeys.isEmpty()) {
+ RelationshipList relationshipList;
+ Object obj = null;
+ Method getRelationshipListMethod = null;
+ try {
+ getRelationshipListMethod = resourceClass.getMethod("getRelationshipList");
+ } catch(Exception exc) {
+ getLogger().debug(RELATIONSHIP_DATA + exc.getMessage());
+ }
+ if(getRelationshipListMethod != null){
+ try {
+ obj = getRelationshipListMethod.invoke(instance);
+ } catch (InvocationTargetException x) {
+ Throwable cause = x.getCause();
+ }
+ }
+ if(obj != null && obj instanceof RelationshipList){
+ relationshipList = (RelationshipList)obj;
+ } else {
+ relationshipList = new RelationshipList();
+ Method setRelationshipListMethod = resourceClass.getMethod("setRelationshipList", RelationshipList.class);
+ if(setRelationshipListMethod != null){
+ try {
+ Object arglist[] = new Object[1];
+ arglist[0] = relationshipList;
+
+ obj = setRelationshipListMethod.invoke(instance, arglist);
+ } catch (InvocationTargetException x) {
+ Throwable cause = x.getCause();
+ }
+ }
+ }
+
+ boolean createdNewRelationships = false;
+ List<Relationship> relationships = relationshipList.getRelationship();
+ if(relationships == null) {
+ relationships = new ArrayList<>();
+ createdNewRelationships = true;
+ }
+
+ int i = 0;
+ while(true){
+ String searchKey = "relationship-list.relationship[" + i + "].related-to";
+ if(!params.containsKey(searchKey))
+ break;
+
+ String relatedTo = params.get(searchKey);
+ String relatedLinkKey = "relationship-list.relationship[" + i + "].related-link";
+ String relatedLink = null;
+ if(params.containsKey(relatedLinkKey)) {
+ relatedLink = params.get(relatedLinkKey);
+ }
+
+ Relationship relationship = new Relationship();
+ relationships.add(relationship);
+ relationship.setRelatedTo(relatedTo);
+
+ String relationshipLabel = "relationship-list.relationship[" + i + "].relationship-label";
+ if(params.containsKey(searchKey)) {
+ relationship.setRelationshipLabel(params.get(relationshipLabel));
+ }
+
+ if (relatedLink != null) {
+ if(relatedLink.contains("v$"))
+ relatedLink = relatedLink.replace(VERSION_PATTERN, AAIRequest.getSupportedAAIVersion());
+ relationship.setRelatedLink(relatedLink);
+ } else {
+ Map<String, String> relParams = new HashMap<>();
+ int j = 0;
+
+ while (true) {
+ String searchRelationshipKey = "relationship-list.relationship[" + i + "].relationship-data["
+ + j + "].relationship-key";
+ String searchRelationshipValue = "relationship-list.relationship[" + i + "].relationship-data["
+ + j + "].relationship-value";
+ if (!params.containsKey(searchRelationshipKey))
+ break;
+
+ RelationshipData relDatum = new RelationshipData();
+ relDatum.setRelationshipKey(params.get(searchRelationshipKey));
+ relDatum.setRelationshipValue(params.get(searchRelationshipValue));
+ relationship.getRelationshipData().add(relDatum);
+
+ relParams.put(params.get(searchRelationshipKey), params.get(searchRelationshipValue));
+ j++;
+ }
+ AAIRequest rlRequest = AAIRequest.createRequest(relatedTo, relParams);
+ for (Map.Entry<String, String> entry : relParams.entrySet()) {
+ rlRequest.addRequestProperty(entry.getKey(), entry.getValue());
+ }
+ String path = rlRequest.updatePathDataValues(null);
+ relationship.setRelatedLink(path);
+ }
+ {
+ int k = 0;
+ // process related to properties
+ Map<String, String> relParams = new HashMap<String, String>();
+
+ while(true) {
+ String searchRelatedToKey = "relationship-list.relationship[" + i + "].related-to-property[" + k + "].property-key";
+ String searchRelatedToValue = "relationship-list.relationship[" + i + "].related-to-property[" + k + "].property-value";
+ if(!params.containsKey(searchRelatedToKey))
+ break;
+
+ RelatedToProperty relDatum = new RelatedToProperty();
+ relDatum.setPropertyKey(params.get(searchRelatedToKey));
+ relDatum.setPropertyValue(params.get(searchRelatedToValue));
+ relationship.getRelatedToProperty().add(relDatum);
+
+ relParams.put(params.get(searchRelatedToKey), params.get(searchRelatedToValue));
+ k++;
+ }
+ }
+
+ i++;
+ }
+ }
+
+ return QueryStatus.SUCCESS;
+ }
+
+ private QueryStatus newModelProcessMetadata(Object instance, Map<String, String> params, String prefix, SvcLogicContext ctx) throws Exception {
+
+ if (!(instance instanceof ServiceInstance) && !(instance instanceof Image)) {
+ throw new IllegalArgumentException("request is not applicable for selected request");
+ }
+
+ Class resourceClass = instance.getClass();
+ Set<String> metadataKeys = new TreeSet<>();
+ Set<String> set = params.keySet();
+ for(String attribute : set) {
+ if(attribute.startsWith("metadata")) {
+ metadataKeys.add(attribute);
+ }
+ }
+
+ // 3. Process Metadata
+ // add metadata
+ if(!metadataKeys.isEmpty()) {
+ Metadata metadata = null;
+ Object obj = null;
+ Method getMetadataMethod = resourceClass.getMethod("getMetadata");
+ if(getMetadataMethod != null){
+ try {
+ obj = getMetadataMethod.invoke(instance);
+ } catch (InvocationTargetException x) {
+ Throwable cause = x.getCause();
+ }
+ }
+ if(obj != null && obj instanceof Metadata){
+ metadata = (Metadata)obj;
+ } else {
+ metadata = new Metadata();
+ Method setMetadataMethod = resourceClass.getMethod("setMetadata", Metadata.class);
+ if(setMetadataMethod != null){
+ try {
+ setMetadataMethod.invoke(instance, metadata);
+ } catch (InvocationTargetException x) {
+ }
+ }
+ }
+
+ List<Metadatum> metadatumList = metadata.getMetadatum();
+ int i = 0;
+ while(true){
+ String metaNameKey = "metadata.metadatum[" + i + "].metaname";
+ String metaValueKey = "metadata.metadatum[" + i + "].metaval";
+ if(!params.containsKey(metaNameKey) || !params.containsKey(metaValueKey))
+ break;
+
+ Metadatum metadatum = new Metadatum();
+ metadatum.setMetaname(params.get(metaNameKey));
+ metadatum.setMetaval(params.get(metaValueKey));
+ metadatumList.add(metadatum);
+
+ i++;
+ }
+ }
+
+ return QueryStatus.SUCCESS;
+ }
+
+ private Relationship findRelationship(List<Relationship> relationships, String relatedTo) {
+ if(relatedTo == null)
+ return null;
+
+ for(Relationship relationship : relationships) {
+ if(relationship.getRelatedTo().equals(relatedTo)){
+ return relationship;
+ }
+ }
+ return null;
+ }
+
+
+ public QueryStatus backup(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException {
+ String resource = params.get("resource").toLowerCase();
+ String prefix = params.get("data-key");
+
+ HashMap<String, String> nameValues = new HashMap<>();
+ if(AAIRequest.createRequest(resource, nameValues) != null) {
+
+ try {
+ return newModelBackupRequest(resource, params, prefix, ctx);
+ } catch (Exception exc) {
+ getLogger().warn("Failed backup - returning FAILURE", exc);
+ return QueryStatus.FAILURE;
+ }
+ }
+
+ return QueryStatus.NOT_FOUND;
+ }
+
+ @Override
+ public QueryStatus restore(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException {
+
+ QueryStatus retval = QueryStatus.SUCCESS;
+ String resource = params.get("resource").toLowerCase();
+ String prefix = params.get("data-key");
+
+ HashMap<String, String> nameValues = new HashMap<>();
+ if(AAIRequest.createRequest(resource, nameValues) != null) {
+
+ try {
+ retval = newModelBackupRequest(resource, params, "tmpRestore", ctx);
+ if(retval == QueryStatus.SUCCESS) {
+ ctx.setAttribute("tmpRestore", null);
+ }
+ } catch (Exception exc) {
+ getLogger().warn("Failed restore - returning FAILURE", exc);
+ return QueryStatus.FAILURE;
+ }
+ }
+
+ return QueryStatus.NOT_FOUND;
+ }
+
+ protected Map<String, Object> objectToProperties(Object object) {
+ ObjectMapper mapper = AAIService.getObjectMapper();
+ return mapper.convertValue(object, Map.class);
+ }
+
+ static <T> T valueOf(Class<T> klazz, String arg) {
+ Exception cause = null;
+ T ret = null;
+ try {
+ ret = klazz.cast(klazz.getDeclaredMethod("valueOf", String.class).invoke(null, arg));
+ } catch (NoSuchMethodException exc) {
+ LoggerFactory.getLogger(AAIService.class).warn("Wrong data type", exc);
+ ret = klazz.cast(arg);
+ } catch (IllegalAccessException e) {
+ cause = e;
+ } catch (InvocationTargetException e) {
+ cause = e;
+ }
+ if (cause == null) {
+ return ret;
+ } else {
+ throw new IllegalArgumentException(cause);
+ }
+ }
+
+ private QueryStatus processDeleteRelationshipList(String resource, String key, SvcLogicContext ctx, HashMap<String, String> nameValues) {
+ try {
+ AAIRequest request = AAIRequest.createRequest(resource.split(":")[0], nameValues);
+ if(request == null) {
+ return QueryStatus.FAILURE;
+ }
+
+ request.processRequestPathValues(nameValues);
+ URL url = request.getRequestUrl("GET", null);
+
+ Class resourceClass = request.getModelClass();
+ Object instance = getResource(url.toString(), resourceClass);
+ if(instance == null)
+ return QueryStatus.NOT_FOUND;
+
+ // get resource version
+ String resourceVersion = null;
+ Method getResourceVersionMethod = resourceClass.getMethod("getResourceVersion");
+ if(getResourceVersionMethod != null){
+ try {
+ Object object = getResourceVersionMethod.invoke(instance);
+ if(object != null)
+ resourceVersion = object.toString();
+ } catch (InvocationTargetException exc) {
+ getLogger().warn("Retrieving resource version", exc);
+ }
+ }
+
+ RelationshipList relationshipList = null;
+ Object obj = null;
+ Method getRelationshipListMethod = null;
+ try {
+ getRelationshipListMethod = resourceClass.getMethod("getRelationshipList");
+ } catch(Exception exc) {
+ getLogger().debug(RELATIONSHIP_DATA + exc.getMessage());
+ }
+ if(getRelationshipListMethod != null){
+ try {
+ obj = getRelationshipListMethod.invoke(instance);
+ } catch (InvocationTargetException x) {
+ Throwable cause = x.getCause();
+ }
+ }
+ if(obj != null && obj instanceof RelationshipList){
+ relationshipList = (RelationshipList)obj;
+ } else {
+ getLogger().debug("No relationships found to process.");
+ return QueryStatus.NOT_FOUND;
+ }
+
+ if(relationshipList.getRelationship() == null || relationshipList.getRelationship().isEmpty()) {
+ return QueryStatus.NOT_FOUND;
+ }
+ String relatedTo = nameValues.get("related_to");
+ if(relatedTo == null) {
+ return QueryStatus.FAILURE;
+ }
+
+ relatedTo = relatedTo.replaceAll("_", "-");
+
+ String relatedLink = nameValues.get("relationship.related_link");
+ if(relatedLink != null) {
+ relatedLink = URLDecoder.decode(relatedLink, "UTF-8");
+ }
+
+ List<Relationship> relationships = relationshipList.getRelationship();
+ List<Relationship> relationshipsToDelete = new LinkedList<>();
+
+ for(Relationship relationship : relationships) {
+ if(relatedTo.equals(relationship.getRelatedTo())) {
+ if(relatedLink != null) {
+ if(relationship.getRelatedLink() != null ) {
+ String localRelatedLink = relationship.getRelatedLink();
+ localRelatedLink = URLDecoder.decode(localRelatedLink, "UTF-8");
+ if(localRelatedLink.endsWith(relatedLink)) {
+ getLogger().debug(String.format("Found relationship of '%s' to keyword '%s'", relationship.getRelatedTo(), relatedTo));
+ relationshipsToDelete.add(relationship);
+ }
+ }
+ } else {
+ getLogger().debug(String.format("Found relationship of '%s' to keyword '%s'", relationship.getRelatedTo(), relatedTo));
+ relationshipsToDelete.add(relationship);
+ }
+ }
+ }
+ if(relationshipsToDelete == null || relationshipsToDelete.isEmpty()) {
+ getLogger().info(String.format("Relationship has not been found for %s", key));
+ return QueryStatus.NOT_FOUND;
+ }
+
+ String path = url.toString();
+ path = path + "/relationship-list/relationship";
+ URL deleteUrl = new URL(path);
+
+ ObjectMapper mapper = AAIService.getObjectMapper();
+
+ boolean cumulativeResponse = true;
+
+ for(Relationship targetRelationship : relationshipsToDelete) {
+ String json_text = mapper.writeValueAsString(targetRelationship);
+ boolean response = deleteList(deleteUrl, json_text);
+ if(!response)
+ cumulativeResponse = response;
+
+ }
+
+ if(!cumulativeResponse)
+ return QueryStatus.FAILURE;
+
+ return QueryStatus.SUCCESS;
+
+ } catch(Exception exc) {
+ getLogger().warn("processDelete", exc);
+ return QueryStatus.FAILURE;
+ }
+ }
+
+ private QueryStatus processDeleteMetadata(String resource, String key, SvcLogicContext ctx, HashMap<String, String> nameValues) {
+ try {
+ AAIRequest request = AAIRequest.createRequest(resource, nameValues);
+ if(request == null) {
+ return QueryStatus.FAILURE;
+ }
+
+ request.processRequestPathValues(nameValues);
+ URL url = request.getRequestUrl("GET", null);
+
+ Class<?> resourceClass = request.getModelClass();
+ Object instance = getResource(url.toString(), resourceClass);
+
+ // get resource version
+ String resourceVersion = null;
+ Method getResourceVersionMethod = resourceClass.getMethod("getResourceVersion");
+ if(getResourceVersionMethod != null){
+ try {
+ resourceVersion = (String) getResourceVersionMethod.invoke(instance);
+ } catch (InvocationTargetException x) {
+ }
+ }
+
+ Metadata metadata = null;
+ Object obj = null;
+ Method getMetadataMethod = resourceClass.getMethod("getMetadata");
+ if(getMetadataMethod != null){
+ try {
+ obj = getMetadataMethod.invoke(instance);
+ } catch (InvocationTargetException x) {
+ Throwable cause = x.getCause();
+ }
+ }
+ if(obj != null && obj instanceof Metadata){
+ metadata = (Metadata)obj;
+ } else {
+ getLogger().debug("No metadata found to process.");
+ return QueryStatus.NOT_FOUND;
+ }
+
+ if(metadata.getMetadatum() == null || metadata.getMetadatum().isEmpty()) {
+ return QueryStatus.NOT_FOUND;
+ }
+
+ List<Metadatum> metadatumList = metadata.getMetadatum();
+ Metadatum metadatumToDelete = null;
+
+ final String metaname = nameValues.get("metaname");
+
+ for(Metadatum metadatum : metadatumList) {
+ getLogger().debug(String.format("Comparing existing metadatum of '%s' to keyword '%s'", metadatum.getMetaname(), metaname));
+ if(metaname.equals(metadatum.getMetaname())) {
+ metadatumToDelete = metadatum;
+ break;
+ }
+ }
+ if(metadatumToDelete == null) {
+ getLogger().info(String.format("Metadatum has not been found for %s", key));
+ return QueryStatus.NOT_FOUND;
+ }
+
+ String path = url.toString();
+ path = path + "/metadata/metadatum/" + encodeQuery( metadatumToDelete.getMetaname() ) +
+ "?resource-version=" + metadatumToDelete.getResourceVersion();
+ URL deleteUrl = new URL(path);
+ boolean response = deleteList(deleteUrl, null);
+
+ if(!response)
+ return QueryStatus.FAILURE;
+
+ return QueryStatus.SUCCESS;
+
+ } catch(Exception exc) {
+ getLogger().warn("processDelete", exc);
+ return QueryStatus.FAILURE;
+ }
+ }
+
+ protected String encodeQuery(String param) throws UnsupportedEncodingException {
+ return URLEncoder.encode(param, "UTF-8").replace("+", "%20");
+ }
+
+ static final Map<String, String> ctxGetBeginsWith( SvcLogicContext ctx, String prefix ) {
+ Map<String, String> tmpPrefixMap = new HashMap<>();
+
+ if(prefix == null || prefix.isEmpty()){
+ return tmpPrefixMap;
+ }
+
+ for( String key : ctx.getAttributeKeySet() ) {
+ if( key.startsWith(prefix) ) {
+ String tmpKey = key.substring(prefix.length() + 1);
+ tmpPrefixMap.put( tmpKey, ctx.getAttribute(key));
+ }
+ }
+
+ Map<String, String> prefixMap = new HashMap<>();
+ Pattern p = Pattern.compile(".*\\[\\d\\]");
+
+ SortedSet<String> keys = new TreeSet<String>(tmpPrefixMap.keySet () );
+ for(String key : keys) {
+ Matcher m = p.matcher(key);
+ if(m.matches()) {
+ continue;
+ } else if(key.endsWith("_length")) {
+ String listKey = key.substring(0, key.indexOf("_length"));
+ int max = Integer.parseInt(tmpPrefixMap.get(key));
+
+ ArrayList<String> data = new ArrayList<>();
+ for(int x = 0; x < max; x++){
+ String tmpKey = String.format("%s[%d]", listKey, x);
+ String tmpValue = tmpPrefixMap.get(tmpKey);
+ if(tmpValue != null && !tmpValue.isEmpty()) {
+ data.add(tmpValue);
+ }
+ }
+ if(!data.isEmpty()) {
+ prefixMap.put(listKey, data.toString());
+ } else {
+ prefixMap.put(key, tmpPrefixMap.get(key));
+ }
+ } else {
+ prefixMap.put(key, tmpPrefixMap.get(key));
+ }
+ }
+
+ return prefixMap;
+ }
+
+ public abstract <T> T getResource(String key, Class<T> type) throws AAIServiceException ;
+ protected abstract boolean deleteList(URL url, String caller) throws AAIServiceException;
+}
diff --git a/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/AAIExecutorInterface.java b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/AAIExecutorInterface.java
new file mode 100755
index 000000000..d02f14a95
--- /dev/null
+++ b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/AAIExecutorInterface.java
@@ -0,0 +1,33 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+/**
+ * @author Rich Tabedzki
+ *
+ */
+package org.onap.ccsdk.sli.adaptors.aai;
+
+public interface AAIExecutorInterface {
+ public String get(AAIRequest request) throws AAIServiceException;
+ public String post(AAIRequest request) throws AAIServiceException;
+ public Boolean delete(AAIRequest request, String resourceVersion) throws AAIServiceException;
+ public Object query(AAIRequest request, Class clas) throws AAIServiceException;
+ public Boolean patch(AAIRequest request, String resourceVersion) throws AAIServiceException;
+}
diff --git a/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/AAIRequest.java b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/AAIRequest.java
new file mode 100755
index 000000000..9facab82c
--- /dev/null
+++ b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/AAIRequest.java
@@ -0,0 +1,493 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Modifications Copyright (C) 2018 IBM.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+/**
+ * @author Rich Tabedzki
+ *
+ */
+package org.onap.ccsdk.sli.adaptors.aai;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.io.UnsupportedEncodingException;
+import java.lang.reflect.Method;
+import java.net.MalformedURLException;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.net.URLDecoder;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.BitSet;
+import java.util.HashSet;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.apache.commons.lang.StringUtils;
+import org.onap.aai.inventory.v21.GenericVnf;
+import org.onap.ccsdk.sli.adaptors.aai.data.AAIDatum;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.FrameworkUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.JsonMappingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+public abstract class AAIRequest {
+ protected static final Logger LOG = LoggerFactory.getLogger(AAIRequest.class);
+
+ protected static final String TARGET_URI = "org.onap.ccsdk.sli.adaptors.aai.uri";
+
+ protected static final String MASTER_REQUEST = "master-request";
+
+ public static final String RESOURCE_VERSION = "resource-version";
+
+ public static final String DEPTH = "depth";
+
+ protected static Properties configProperties;
+ protected final String targetUri;
+ protected static AAIService aaiService;
+
+ protected AAIDatum requestDatum;
+
+ protected final Properties requestProperties = new Properties();
+
+
+ public static AAIRequest createRequest(String resoourceName, Map<String, String> nameValues){
+
+ String resoource = resoourceName;
+ String masterResource = null;
+
+ if(resoource == null)
+ return null;
+
+ if(resoource.contains(":")) {
+ String[] tokens = resoource.split(":");
+ if(tokens != null && tokens.length == 2) {
+ resoource = tokens[1];
+ masterResource = tokens[0];
+ Class<? extends AAIDatum> clazz = getClassFromResource(resoource) ;
+
+ if(clazz == null) {
+ return null;
+ }
+ }
+ }
+
+ if(nameValues.containsKey("selflink")){
+ Class<? extends AAIDatum> clazz = getClassFromResource(resoource) ;
+
+ if(clazz != null)
+ return new SelfLinkRequest(clazz);
+ else
+ return null;
+ }
+
+ switch(resoource){
+ case "generic-query":
+ return new GenericQueryRequest();
+ case "nodes-query":
+ return new NodesQueryRequest();
+ case "custom-query":
+ case "formatted-query":
+ return new CustomQueryRequest();
+ case "echo":
+ case "test":
+ return new EchoRequest();
+
+ case "linterface":
+ case "l2-bridge-sbg":
+ case "l2-bridge-bgf":
+ {
+ resoource = "l-interface";
+ return getRequestFromResource("l-interface");
+ }
+ case "relationship-list":
+ return new RelationshipListRequest(AAIRequest.createRequest(masterResource, nameValues));
+ case "relationship":
+ return new RelationshipRequest(AAIRequest.createRequest(masterResource, nameValues));
+ default:
+ return getRequestFromResource(resoource);
+ }
+ }
+
+
+ /**
+ * Map containing resource tag to its bit position in bitset mapping
+ */
+ private static Map<String, String> tagValues = new LinkedHashMap<>();
+ /**
+ * Map containing bitset value of the path to its path mapping
+ */
+ private static Map<BitSet, String> bitsetPaths = new LinkedHashMap<>();
+
+
+ public static Set<String> getResourceNames() {
+ return tagValues.keySet();
+ }
+
+
+ public static void setProperties(Properties props, AAIService aaiService) {
+ AAIRequest.configProperties = props;
+ AAIRequest.aaiService = aaiService;
+
+ InputStream in = null;
+
+ try
+ {
+ LOG.info("Loading aai-path.properties via OSGi");
+ URL url = null;
+ Bundle bundle = FrameworkUtil.getBundle(AAIService.class);
+ if(bundle != null) {
+ BundleContext ctx = bundle.getBundleContext();
+ if(ctx == null)
+ return;
+
+ url = ctx.getBundle().getResource(AAIService.PATH_PROPERTIES);
+ } else {
+ url = aaiService.getClass().getResource("/aai-path.properties");
+ }
+
+ in = url.openStream();
+ }
+ catch (NoClassDefFoundError|Exception e) {
+ LOG.info("Loading aai-path.properties from jar");
+ in = AAIRequest.class.getResourceAsStream("/aai-path.properties");
+
+ }
+
+ if (in == null) {
+ return;
+ }
+
+ try {
+ Reader reader = new InputStreamReader(in, StandardCharsets.UTF_8);
+
+ Properties properties = new Properties();
+ properties.load(reader);
+ LOG.info("loaded " + properties.size());
+
+ Set<String> keys = properties.stringPropertyNames();
+
+ int index = 0;
+ Set<String> resourceNames = new TreeSet<>();
+
+ for(String key : keys) {
+ String[] tags = key.split("\\|");
+ for(String tag : tags) {
+ if(!resourceNames.contains(tag)) {
+ resourceNames.add(tag);
+ tagValues.put(tag, Integer.toString(++index));
+ }
+ }
+ BitSet bs = new BitSet(256);
+ for(String tag : tags) {
+ String value = tagValues.get(tag);
+ Integer bitIndex = Integer.parseInt(value) ;
+ bs.set(bitIndex);
+ }
+ String path = properties.getProperty(key);
+ LOG.trace(String.format("bitset %s\t\t%s", bs.toString(), path));
+ bitsetPaths.put(bs, path);
+ }
+ LOG.info("loaded " + resourceNames.toString());
+ }
+ catch (Exception e)
+ {
+ LOG.error("Caught exception", e);
+ }
+ }
+
+ public AAIRequest() {
+ targetUri = configProperties.getProperty(TARGET_URI);
+ }
+
+ public void addRequestProperty(String key, String value) {
+ requestProperties.put(key, value);
+ }
+
+ public final void setRequestObject(AAIDatum value) {
+ requestDatum = value;
+ }
+
+ public final AAIDatum getRequestObject() {
+ return requestDatum;
+ }
+
+ public final void addMasterRequest(AAIRequest masterRequest) {
+ requestProperties.put(MASTER_REQUEST, masterRequest);
+ }
+
+ protected static String encodeQuery(String param) throws UnsupportedEncodingException {
+ return URLEncoder.encode(param, "UTF-8").replace("+", "%20");
+ }
+
+ protected void handleException(AAIRequest lInterfaceRequest, JsonProcessingException exc) {
+ aaiService.getLogger().warn("Could not deserialize object of type " + lInterfaceRequest.getClass().getSimpleName(), exc) ;
+ }
+
+ public URL getRequestUrl(String method, String resourceVersion) throws UnsupportedEncodingException, MalformedURLException, URISyntaxException {
+
+ String request_url = null;
+
+ request_url = targetUri + updatePathDataValues(resourceVersion);
+
+ URL http_req_url = new URL(request_url);
+
+ aaiService.LOGwriteFirstTrace(method, http_req_url.toString());
+
+ return http_req_url;
+ }
+
+ public String updatePathDataValues(Object resourceVersion) throws UnsupportedEncodingException, MalformedURLException {
+ String request_url = getRequestPath();
+
+ Set<String> uniqueResources = extractUniqueResourceSetFromKeys(requestProperties.stringPropertyNames());
+
+ for(String resoourceName:uniqueResources) {
+ AAIRequest locRequest = AAIRequest.createRequest(resoourceName, new HashMap<String, String>());
+ if(locRequest != null) {
+ Class<?> clazz = locRequest.getClass();
+ Method function = null;
+ try {
+ function = clazz.getMethod("processPathData", request_url.getClass(), requestProperties.getClass());
+ request_url = (String) function.invoke(null, request_url, requestProperties);
+ } catch (Exception e) {
+ LOG.error("Caught exception", e);
+ }
+ }
+ }
+
+ if(resourceVersion != null) {
+ request_url = request_url +"?resource-version="+resourceVersion;
+ }
+
+ return request_url;
+ }
+
+ protected String getRequestPath() throws MalformedURLException {
+ return getRequestPath(null);
+ }
+
+ protected String getRequestPath(String resource) throws MalformedURLException {
+ if(requestProperties.containsKey("resource-path")) {
+ return requestProperties.getProperty("resource-path");
+ }
+
+ Set<String> uniqueResources = extractUniqueResourceSetFromKeys(requestProperties.stringPropertyNames());
+ if(resource != null) {
+ // for group search add itself, but remove singular version of itself
+ if(!uniqueResources.contains(resource)) {
+ boolean replaced = false;
+ Set<String> tmpUniqueResources = new HashSet<>();
+ tmpUniqueResources.addAll(uniqueResources);
+ for(String item : tmpUniqueResources){
+ String plural = item +"s";
+ if(item.endsWith("y")){
+ plural = item.substring(0, item.length()-1)+ "ies";
+ }
+ if(plural.equals(resource)) {
+ uniqueResources.remove(item);
+ uniqueResources.add(resource);
+ replaced = true;
+ break;
+ }
+ }
+ if(!replaced){
+ if(!uniqueResources.contains(resource)) {
+ uniqueResources.add(resource);
+ }
+ }
+ }
+ }
+ BitSet bitset = new BitSet();
+ for(String key : uniqueResources) {
+ if(tagValues.containsKey(key)) {
+ Object tmpValue = tagValues.get(key);
+ if(tmpValue != null) {
+ String value = tmpValue.toString();
+ int bitIndex = Integer.parseInt(value);
+ bitset.set(bitIndex);
+ }
+ }
+ }
+
+ String path = bitsetPaths.get(bitset);
+ if(path == null) {
+ throw new MalformedURLException("PATH not found for key string containing valies :" +requestProperties.toString());
+ }
+ return path;
+ }
+
+ public abstract URL getRequestQueryUrl(String method) throws UnsupportedEncodingException, MalformedURLException, URISyntaxException;
+
+ public abstract String toJSONString();
+
+ public abstract String[] getArgsList();
+
+ public abstract Class<? extends AAIDatum> getModelClass() ;
+
+ public String getPrimaryResourceName(String resource) {
+ return resource;
+ }
+
+ public String formatKey(String argument) {
+ return argument;
+ }
+
+ public AAIDatum jsonStringToObject(String jsonData) throws JsonParseException, JsonMappingException, IOException {
+ if(jsonData == null) {
+ return null;
+ }
+
+ AAIDatum response = null;
+ ObjectMapper mapper = getObjectMapper();
+ response = mapper.readValue(jsonData, getModelClass());
+ return response;
+ }
+
+ protected static Set<String> extractUniqueResourceSetFromKeys(Set<String> keySet) {
+ Set<String> uniqueResources = new TreeSet<>();
+ List<String> keys = new ArrayList<>(keySet);
+ for(String resource : keys) {
+ if(resource.contains(".")) {
+ String [] split = resource.split("\\.");
+ uniqueResources.add(split[0].replaceAll("_", "-"));
+ }
+ }
+ return uniqueResources;
+ }
+
+ public void processRequestPathValues(Map<String, String> nameValues) {
+ Set<String> uniqueResources = extractUniqueResourceSetFromKeys(nameValues.keySet());
+
+ Set<String> tokens = new TreeSet<>();
+ tokens.add(DEPTH);
+ tokens.addAll(Arrays.asList(this.getArgsList()));
+
+ for(String resoourceName:uniqueResources) {
+ AAIRequest locRequest = AAIRequest.createRequest(resoourceName, nameValues);
+ if(locRequest != null)
+ tokens.addAll(Arrays.asList(locRequest.getArgsList()));
+ }
+
+ String[] arguments = tokens.toArray(new String[0]);
+ for(String name : arguments) {
+ String tmpName = name.replaceAll("-", "_");
+ String value = nameValues.get(tmpName);
+ if(value != null && !value.isEmpty()) {
+ value = value.trim().replace("'", "").replace("$", "").replace("'", "");
+ this.addRequestProperty(name, value);
+ }
+ }
+ }
+
+ public static String processPathData(String request_url, Properties requestProperties) throws UnsupportedEncodingException {
+ return request_url;
+ }
+
+ public boolean isDeleteDataRequired() {
+ return false;
+ }
+
+ ObjectMapper getObjectMapper() {
+ return AAIService.getObjectMapper();
+ }
+
+ public static Class<? extends AAIDatum> getClassFromResource(String resoourceName) {
+ String className = GenericVnf.class.getName();
+ String[] split = resoourceName.split("-");
+ for(int i = 0; i < split.length; i++) {
+ split[i] = StringUtils.capitalize(split[i]);
+ }
+
+ String caps = StringUtils.join(split);
+ className = className.replace("GenericVnf", caps);
+ try {
+ return (Class<? extends AAIDatum>)Class.forName(className);
+ } catch (ClassNotFoundException e) {
+ LOG.warn("AAIRequest does not support class: " + e.getMessage());
+ return null;
+ }
+ }
+
+ protected static AAIRequest getRequestFromResource(String resoourceName) {
+
+ Class<? extends AAIDatum> clazz = getClassFromResource(resoourceName);
+
+ if(clazz == null) {
+ return null;
+ }
+ return new GenericRequest(clazz);
+ }
+
+ public static Map<String, String> splitQuery(String query) throws UnsupportedEncodingException {
+ Map<String, String> query_pairs = new LinkedHashMap<>();
+
+ if(query != null && !query.isEmpty()) {
+ String[] pairs = query.split("&");
+ for (String pair : pairs) {
+ int idx = pair.indexOf('=');
+ query_pairs.put(URLDecoder.decode(pair.substring(0, idx), "UTF-8"), URLDecoder.decode(pair.substring(idx + 1), "UTF-8"));
+ }
+ }
+ return query_pairs;
+ }
+
+ public static Map<String, String> splitPath(String path) throws UnsupportedEncodingException {
+ Map<String, String> query_pairs = new LinkedHashMap<>();
+
+ if(path != null && !path.isEmpty()) {
+ String[] pairs = path.split("/");
+ for (String pair : pairs) {
+ int idx = pair.indexOf('=');
+ query_pairs.put(URLDecoder.decode(pair.substring(0, idx), "UTF-8"), URLDecoder.decode(pair.substring(idx + 1), "UTF-8"));
+ }
+ }
+ return query_pairs;
+ }
+
+ protected boolean expectsDataFromPUTRequest() {
+ return false;
+ }
+
+
+ public String getTargetUri() {
+ return targetUri;
+ }
+
+ public static final String getSupportedAAIVersion() {
+ return configProperties.getProperty(AAIDeclarations.AAI_VERSION, "/v21/");
+ }
+}
diff --git a/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/AAIService.java b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/AAIService.java
new file mode 100755
index 000000000..4d51550a3
--- /dev/null
+++ b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/AAIService.java
@@ -0,0 +1,1547 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Modifications Copyright (C) 2019 IBM.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+/**
+ * @author Rich Tabedzki
+ *
+ */
+package org.onap.ccsdk.sli.adaptors.aai;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.io.UnsupportedEncodingException;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+import java.security.KeyManagementException;
+import java.security.KeyStore;
+import java.security.NoSuchAlgorithmException;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Properties;
+import java.util.Set;
+import java.util.TimeZone;
+import java.util.UUID;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSession;
+import javax.net.ssl.SSLSocketFactory;
+import javax.ws.rs.HttpMethod;
+import javax.xml.bind.annotation.XmlElement;
+
+import org.apache.commons.codec.binary.Base64;
+import org.apache.commons.lang3.StringUtils;
+import org.onap.ccsdk.sli.adaptors.aai.data.AAIDatum;
+import org.onap.ccsdk.sli.adaptors.aai.data.ErrorResponse;
+import org.onap.ccsdk.sli.adaptors.aai.data.notify.NotifyEvent;
+import org.onap.ccsdk.sli.core.sli.ConfigurationException;
+import org.onap.ccsdk.sli.core.sli.MetricLogger;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.core.sli.SvcLogicResource;
+import org.onap.aai.inventory.v21.GenericVnf;
+import org.onap.aai.inventory.v21.PhysicalLink;
+import org.onap.aai.inventory.v21.ResultData;
+import org.onap.aai.inventory.v21.SearchResults;
+import org.onap.aai.inventory.v21.Vserver;
+import org.onap.logging.ref.slf4j.ONAPLogConstants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.slf4j.MDC;
+
+import com.fasterxml.jackson.annotation.JsonInclude.Include;
+import com.fasterxml.jackson.databind.AnnotationIntrospector;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector;
+import com.fasterxml.jackson.databind.type.TypeFactory;
+import com.fasterxml.jackson.module.jaxb.JaxbAnnotationIntrospector;
+
+
+public class AAIService extends AAIDeclarations implements AAIClient, SvcLogicResource {
+
+ public static final String AAICLIENT_PROPERTIES = "/aaiclient.properties";
+ public static final String PATH_PROPERTIES = "/aai-path.properties";
+
+ private static final Logger LOG = LoggerFactory.getLogger(AAIService.class);
+
+ private final String truststorePath;
+ private final String truststorePassword;
+ private final String keystorePath;
+ private final String keystorePassword;
+ private final Boolean ignoreCertificateHostError;
+
+ private final String targetUri;
+ private final String networkVserverPath;
+
+ private final String svc_inst_query_path;
+
+ private final String ubb_notify_path;
+ private final String selflinkAvpn;
+ private final String selflinkFqdn;
+
+ private final int connectionTimeout;
+ private final int readTimeout;
+
+ // 1602
+ private final String queryNodesPath;
+ private final String applicationId;
+
+ // authentication credentials
+ private String userName;
+ private String userPassword;
+
+ // runtime
+ private final boolean runtimeOSGI;
+
+ private SSLContext CTX;
+
+ private final MetricLogger ml = new MetricLogger();
+
+ private AAIExecutorInterface executor;
+
+ public AAIService(final UtilsProvider configuration) {
+ this(configuration.getProperties());
+ }
+
+ public AAIService(final URL url) {
+ this(getProperties(url));
+ }
+
+ public AAIService(Properties props) {
+ LOG.info("Entered AAIService.ctor");
+
+ String runtime = System.getProperty("aaiclient.runtime");
+ if("OSGI".equals(runtime)) {
+ runtimeOSGI = true;
+ } else {
+ runtimeOSGI = false;
+ }
+
+ try {
+ AAIRequest.setProperties(props, this);
+
+ } catch(Exception exc){
+ LOG.error("AicAAIResource.static", exc);
+ }
+
+ executor = new AAIClientRESTExecutor(props);
+
+ userName = props.getProperty(CLIENT_NAME);
+ userPassword = props.getProperty(CLIENT_PWWD);
+
+ if(userName == null || userName.isEmpty()){
+ LOG.debug("Basic user name is not set");
+ }
+ if(userPassword == null || userPassword.isEmpty()) {
+ LOG.debug("Basic password is not set");
+ }
+
+ truststorePath = props.getProperty(TRUSTSTORE_PATH);
+ truststorePassword = props.getProperty(TRUSTSTORE_PSSWD);
+ keystorePath = props.getProperty(KEYSTORE_PATH);
+ keystorePassword = props.getProperty(KEYSTORE_PSSWD);
+
+ targetUri = props.getProperty(TARGET_URI);
+ props.getProperty(QUERY_PATH);
+ props.getProperty(UPDATE_PATH);
+
+ String tmpApplicationId = props.getProperty(APPLICATION_ID);
+ if(tmpApplicationId == null || tmpApplicationId.isEmpty()) {
+ tmpApplicationId = "SDNC";
+ }
+ this.applicationId = tmpApplicationId;
+
+ // connection timeout
+ int tmpConnectionTimeout = 30000;
+ int tmpReadTimeout = 30000;
+
+ try {
+ String tmpValue = null;
+ tmpValue = props.getProperty(CONNECTION_TIMEOUT, "30000");
+ tmpConnectionTimeout = Integer.parseInt(tmpValue);
+ tmpValue = props.getProperty(READ_TIMEOUT, "30000");
+ tmpReadTimeout = Integer.parseInt(tmpValue);
+ } catch(Exception exc) {
+ LOG.error("Failed setting connection timeout", exc);
+ tmpConnectionTimeout = 30000;
+ tmpReadTimeout = 30000;
+ }
+ connectionTimeout = tmpConnectionTimeout;
+ readTimeout = tmpReadTimeout;
+
+ networkVserverPath =props.getProperty(NETWORK_VSERVER_PATH);
+
+ props.getProperty(SVC_INSTANCE_PATH);
+ svc_inst_query_path = props.getProperty(SVC_INST_QRY_PATH);
+ props.getProperty(PARAM_SERVICE_TYPE, "service-type");
+
+ props.getProperty(VNF_IMAGE_QUERY_PATH);
+
+ ubb_notify_path = props.getProperty(UBB_NOTIFY_PATH);
+ selflinkAvpn = props.getProperty(SELFLINK_AVPN);
+ selflinkFqdn = props.getProperty(SELFLINK_FQDN);
+
+ props.getProperty(SERVICE_PATH);
+
+ props.getProperty(SITE_PAIR_SET_PATH);
+
+ queryNodesPath = props.getProperty(QUERY_NODES_PATH);
+
+ String iche = props.getProperty(CERTIFICATE_HOST_ERROR);
+ boolean host_error = false;
+ if(iche != null && !iche.isEmpty()) {
+ host_error = Boolean.valueOf(iche);
+ }
+
+ ignoreCertificateHostError = host_error;
+
+ HttpsURLConnection.setDefaultHostnameVerifier( new HostnameVerifier(){
+ public boolean verify(String string,SSLSession ssls) {
+ return ignoreCertificateHostError;
+ }
+ });
+
+ if(truststorePath != null && truststorePassword != null && (new File(truststorePath)).exists()) {
+ System.setProperty("javax.net.ssl.trustStore", truststorePath);
+ System.setProperty("javax.net.ssl.trustStorePassword", truststorePassword);
+ }
+
+ if(keystorePath != null && keystorePassword != null && (new File(keystorePath)).exists()) {
+ //DefaultClientConfig config = new DefaultClientConfig();
+ //both jersey and HttpURLConnection can use this
+ SSLContext ctx = null;
+ try {
+ ctx = SSLContext.getInstance("TLS");
+
+ KeyManagerFactory kmf = null;
+ try (FileInputStream fin = new FileInputStream(keystorePath)){
+ String def = "SunX509";
+ String storeType = "PKCS12";
+ def = KeyStore.getDefaultType();
+ kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
+
+ String extension = keystorePath.substring(keystorePath.lastIndexOf(".") + 1);
+ if("JKS".equalsIgnoreCase(extension)) {
+ storeType = "JKS";
+ }
+ KeyStore ks = KeyStore.getInstance(storeType);
+
+ char[] pwd = keystorePassword.toCharArray();
+ ks.load(fin, pwd);
+ kmf.init(ks, pwd);
+ } catch (Exception ex) {
+ LOG.error("AAIResource", ex);
+ }
+
+ if(null!=kmf) {
+ ctx.init(kmf.getKeyManagers(), null, null);
+ }
+ /*
+ * config.getProperties().put(HTTPSProperties.PROPERTY_HTTPS_PROPERTIES, new
+ * HTTPSProperties( new HostnameVerifier() {
+ *
+ * @Override public boolean verify( String s, SSLSession sslSession ) { return
+ * ignoreCertificateHostError; } }, ctx));
+ */
+
+ CTX = ctx;
+ LOG.debug("SSLContext created");
+
+ } catch (KeyManagementException | NoSuchAlgorithmException exc) {
+ LOG.error("AAIResource", exc);
+ }
+ }
+
+ LOG.info("AAIResource.ctor initialized.");
+
+ try {
+ Field methodsField = HttpURLConnection.class.getDeclaredField("methods");
+ methodsField.setAccessible(true);
+ // get the methods field modifiers
+ Field modifiersField = Field.class.getDeclaredField("modifiers");
+ // bypass the "private" modifier
+ modifiersField.setAccessible(true);
+
+ // remove the "final" modifier
+ modifiersField.setInt(methodsField, methodsField.getModifiers() & ~Modifier.FINAL);
+
+ /* valid HTTP methods */
+ String[] methods = {
+ "GET", "POST", "HEAD", "OPTIONS", "PUT", "DELETE", "TRACE", "PATCH"
+ };
+ // set the new methods - including patch
+ methodsField.set(null, methods);
+
+ } catch (SecurityException | IllegalArgumentException | IllegalAccessException | NoSuchFieldException e) {
+ LOG.error("Exception occured", e);
+ }
+
+ }
+
+ private static Properties getProperties(URL url) {
+ Properties properties = new Properties();
+ try {
+ properties.load(url.openStream());
+ } catch (IOException exc) {
+ LOG.error("getProperties", exc);
+ }
+ return properties;
+ }
+
+ public void setExecutor(AAIExecutorInterface executor) {
+ this.executor = executor;
+ }
+
+ public void cleanUp() {
+
+ }
+
+ /**
+ *
+ * @param http_req_url
+ * @param method
+ * @return
+ * @throws Exception
+ */
+ protected HttpURLConnection getConfiguredConnection(URL http_req_url, String method) throws Exception {
+ HttpURLConnection con = (HttpURLConnection) http_req_url.openConnection();
+
+ // Set up the connection properties
+ con.setRequestProperty( "Connection", "close" );
+ con.setDoInput(true);
+ con.setDoOutput(true);
+ con.setUseCaches(false);
+ con.setConnectTimeout( connectionTimeout );
+ con.setReadTimeout( readTimeout );
+ con.setRequestMethod( method );
+ con.setRequestProperty( "Accept", "application/json" );
+ con.setRequestProperty( "Content-Type", "PATCH".equalsIgnoreCase(method) ? "application/merge-patch+json" : "application/json" );
+ con.setRequestProperty("X-FromAppId", applicationId);
+ con.setRequestProperty("X-TransactionId",TransactionIdTracker.getNextTransactionId());
+ String mlId = ml.getRequestID();
+ if(mlId != null && !mlId.isEmpty()) {
+ LOG.debug(String.format("MetricLogger requestId = %s", mlId));
+ con.setRequestProperty(ONAPLogConstants.MDCs.REQUEST_ID, mlId);
+ } else {
+ LOG.debug("MetricLogger requestId is null");
+ }
+ con.setRequestProperty("Transfer-Encoding","chunked");
+
+ if(userName != null && !userName.isEmpty() && userPassword != null && !userPassword.isEmpty()) {
+ String basicAuth = "Basic " + new String(Base64.encodeBase64((userName + ":" + userPassword).getBytes()));
+ con.setRequestProperty ("Authorization", basicAuth);
+ }
+
+ if(con instanceof HttpsURLConnection && CTX != null) {
+ SSLSocketFactory sockFact = CTX.getSocketFactory();
+ HttpsURLConnection.class.cast(con).setSSLSocketFactory( sockFact );
+ }
+ return con;
+ }
+
+
+ @Override
+ public GenericVnf requestGenericVnfData(String vnf_id) throws AAIServiceException {
+ GenericVnf response = null;
+
+ try {
+ AAIRequest request = AAIRequest.getRequestFromResource("generic-vnf");
+ request.addRequestProperty("generic-vnf.vnf-id", vnf_id);
+ String rv = executor.get(request);
+ if(rv != null) {
+ ObjectMapper mapper = getObjectMapper();
+ response = mapper.readValue(rv, GenericVnf.class);
+ }
+ } catch(AAIServiceException aaiexc) {
+ throw aaiexc;
+ } catch (Exception exc) {
+ LOG.warn(Object.class.getClass().getEnclosingMethod().getName(), exc);
+ throw new AAIServiceException(exc);
+ }
+
+ return response;
+
+ }
+
+ @Override
+ public boolean postGenericVnfData(String vnf_id, GenericVnf data) throws AAIServiceException {
+ try {
+ AAIRequest request = AAIRequest.getRequestFromResource("generic-vnf");
+ request.addRequestProperty("generic-vnf.vnf-id", vnf_id);
+ request.setRequestObject(data);
+ Object response = executor.post(request);
+ return true;
+ } catch(AAIServiceException aaiexc) {
+ throw aaiexc;
+ } catch (Exception exc) {
+ LOG.warn("requestGenericVnfData", exc);
+ throw new AAIServiceException(exc);
+ }
+ }
+
+ @Override
+ public SearchResults requestServiceInstanceURL(String svc_instance_id) throws AAIServiceException {
+ SearchResults response = null;
+ InputStream inputStream = null;
+
+ try {
+ String path = svc_inst_query_path;
+ path = path.replace("{svc-instance-id}", encodeQuery(svc_instance_id));
+
+ String request_url = targetUri+path;
+ URL http_req_url = new URL(request_url);
+
+ HttpURLConnection con = getConfiguredConnection(http_req_url, HttpMethod.GET);
+
+ LOGwriteFirstTrace(HttpMethod.GET, http_req_url.toString());
+ LOGwriteDateTrace("svc_instance_id", svc_instance_id);
+
+ // Check for errors
+ int responseCode = con.getResponseCode();
+ if (responseCode == HttpURLConnection.HTTP_OK) {
+ inputStream = con.getInputStream();
+ } else {
+ inputStream = con.getErrorStream();
+ }
+
+ // Process the response
+ LOG.debug("HttpURLConnection result:" + responseCode);
+ if(inputStream == null) inputStream = new ByteArrayInputStream("".getBytes(StandardCharsets.UTF_8));
+ BufferedReader reader = new BufferedReader( new InputStreamReader( inputStream ) );
+
+ ObjectMapper mapper = getObjectMapper();
+
+ if (responseCode == HttpURLConnection.HTTP_OK) {
+ response = mapper.readValue(reader, SearchResults.class);
+ LOGwriteEndingTrace(HttpURLConnection.HTTP_OK, "SUCCESS", mapper.writeValueAsString(response));
+ } else if(responseCode == HttpURLConnection.HTTP_NOT_FOUND ) {
+ LOGwriteEndingTrace(responseCode, "HTTP_NOT_FOUND", "Entry does not exist.");
+ return response;
+ } else {
+ ErrorResponse errorresponse = mapper.readValue(reader, ErrorResponse.class);
+ LOGwriteEndingTrace(responseCode, "FAILURE", mapper.writeValueAsString(errorresponse));
+ throw new AAIServiceException(responseCode, errorresponse);
+ }
+
+ } catch(AAIServiceException aaiexc) {
+ throw aaiexc;
+ } catch (Exception exc) {
+ LOG.warn("requestServiceInstanceURL", exc);
+ throw new AAIServiceException(exc);
+ } finally {
+ if(inputStream != null){
+ try {
+ inputStream.close();
+ } catch(Exception exc) {
+ LOG.warn("Error closing Inputstream", exc);
+ }
+ }
+ }
+ return response;
+ }
+
+
+ private static Properties initialize(URL url ) throws ConfigurationException {
+
+ if(url == null) {
+ throw new NullPointerException();
+ }
+
+ InputStream is = null;
+ Properties props = new Properties();
+
+ try {
+ if(LOG.isDebugEnabled())
+ LOG.info("Property file is: " + url.toString());
+
+ is = url.openStream();
+
+ props.load(is);
+ if(LOG.isDebugEnabled()) {
+ LOG.info("Properties loaded: " + props.size());
+ Enumeration<Object> en = props.keys();
+
+ while(en.hasMoreElements()) {
+ String key = (String)en.nextElement();
+ String property = props.getProperty(key);
+ LOG.debug(key + " : " + property);
+ }
+ }
+ } catch (Exception e) {
+ throw new ConfigurationException("Could not load properties file.", e);
+ }
+ return props;
+ }
+
+ static class TransactionIdTracker {
+// protected static AtomicLong tracker = new AtomicLong();
+
+ public static String getNextTransactionId() {
+ // Check if RequestId exists as MDC. If not, create new.
+ String transactionId = MDC.get("RequestId");
+ if ("".equals(transactionId) || transactionId == null) {
+ transactionId = UUID.randomUUID().toString();
+ LOG.info("Missing requestID. Assigned " + transactionId);
+ MDC.put("RequestId", transactionId);
+ }
+ return transactionId;
+ }
+
+ }
+
+ protected void LOGwriteFirstTrace(String method, String url) {
+ String time = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'").format(System.currentTimeMillis());
+ LOG.info("A&AI transaction :");
+ LOG.info("Request Time : " + time + ", Method : " + method);
+ LOG.info("Request URL : "+ url);
+ }
+
+ protected void LOGwriteDateTrace(String name, String data) {
+ LOG.info("Input - " + name + " : " + data);
+ }
+
+ protected void LOGwriteEndingTrace(int response_code, String comment, String data) {
+ LOG.info("Response code : " + response_code +", " + comment);
+ LOG.info(String.format("Response data : %s", data));
+ }
+
+ protected String encodeQuery(String param) throws UnsupportedEncodingException {
+ return URLEncoder.encode(param, "UTF-8").replace("+", "%20");
+ }
+
+ private String encodeCustomerURL(final String selection)
+ {
+ String encrypted_url = selection;
+ String apnpattern =
+ "/aai/v11/business/customers/customer/(.+)/service-subscriptions/service-subscription/(.+)/service-instances/service-instance/(.+)/";
+ Pattern pattern = Pattern.compile(apnpattern);
+
+ try {
+ URL url = new URL(selection);
+ String path = url.getPath();
+
+ LOG.info("Trying to match apn to <" + path + ">");
+
+ Matcher matcher = pattern.matcher(path);
+
+ while(matcher.find()) {
+ String customer = matcher.group(1);
+ String subscription = matcher.group(2);
+ String service = matcher.group(3);
+
+ encrypted_url = selection.replace(customer, encodeQuery(customer));
+ encrypted_url = encrypted_url.replace(subscription, encodeQuery(subscription));
+ encrypted_url = encrypted_url.replace(service, encodeQuery(service));
+ }
+ } catch (Exception e) {
+ LOG.warn("", e);
+ }
+
+ return encrypted_url;
+ }
+
+
+
+ /*
+ * (non-Javadoc)
+ * @see org.onap.sdnct.sli.aai.AAIClient#requestVServersData(java.lang.String, java.lang.String)
+ */
+ @Override
+ public Vserver requestVServerData(String tenantId, String vserverId, String cloudOwner, String cloudRegionId) throws AAIServiceException {
+ Vserver response = null;
+
+ try {
+ AAIRequest request = AAIRequest.getRequestFromResource("vserver");
+ request.addRequestProperty("cloud-region.cloud-owner", cloudOwner);
+ request.addRequestProperty("cloud-region.cloud-region-id", cloudRegionId);
+ request.addRequestProperty("tenant.tenant-id", tenantId);
+ request.addRequestProperty("vserver.vserver-id", vserverId);
+
+ String rv = executor.get(request);
+ if(rv != null) {
+ ObjectMapper mapper = getObjectMapper();
+ response = mapper.readValue(rv, Vserver.class);
+ }
+ } catch(AAIServiceException aaiexc) {
+ throw aaiexc;
+ } catch (Exception exc) {
+ LOG.warn(Object.class.getClass().getEnclosingMethod().getName(), exc);
+ throw new AAIServiceException(exc);
+ }
+ return response;
+ }
+
+
+ //================== End of DvsSwitch =================
+ //==================== PhysicalLink ======================
+ @Override
+ public PhysicalLink requestPhysicalLinkData(String linkName) throws AAIServiceException {
+ PhysicalLink response = null;
+
+ try {
+ AAIRequest request = AAIRequest.getRequestFromResource("physical-link");
+ request.addRequestProperty("physical-link.link-name", linkName);
+
+ String rv = executor.get(request);
+ if(rv != null) {
+ ObjectMapper mapper = getObjectMapper();
+ response = mapper.readValue(rv, PhysicalLink.class);
+ }
+ } catch(AAIServiceException aaiexc) {
+ throw aaiexc;
+ } catch (Exception exc) {
+ LOG.warn("requestPhysicalLinkData", exc);
+ throw new AAIServiceException(exc);
+ }
+ return response;
+ }
+
+ @Override
+ public boolean postPhysicalLinkData(String linkName, PhysicalLink data) throws AAIServiceException {
+ try {
+ AAIRequest request = AAIRequest.getRequestFromResource("physical-link");
+ request.addRequestProperty("physical-link.link-name", linkName);
+ request.setRequestObject(data);
+ Object response = executor.post(request);
+ return true;
+ } catch(AAIServiceException aaiexc) {
+ throw aaiexc;
+ } catch (Exception exc) {
+ LOG.warn(Object.class.getClass().getEnclosingMethod().getName(), exc);
+ throw new AAIServiceException(exc);
+ }
+ }
+
+ @Override
+ public boolean deletePhysicalLinkData(String linkName, String resourceVersion) throws AAIServiceException {
+ boolean response = false;
+
+ try {
+ AAIRequest request = AAIRequest.getRequestFromResource("physical-link");
+ request.addRequestProperty("physical-link.link-name", linkName);
+ response = executor.delete(request, resourceVersion);
+ } catch(AAIServiceException aaiexc) {
+ throw aaiexc;
+ } catch (Exception exc) {
+ LOG.warn("deletePhysicalLinkData", exc);
+ throw new AAIServiceException(exc);
+ }
+ return response;
+ }
+
+ public boolean deleteAAIEntity(URL url, String caller) throws AAIServiceException {
+
+ if(url == null) {
+ throw new NullPointerException();
+ }
+
+ boolean response = false;
+ InputStream inputStream = null;
+
+ try {
+ URL http_req_url = url;
+
+ HttpURLConnection con = getConfiguredConnection(http_req_url, HttpMethod.DELETE);
+
+ LOGwriteFirstTrace("DELETE", http_req_url.toString());
+
+
+ // Check for errors
+ int responseCode = con.getResponseCode();
+ if (responseCode == HttpURLConnection.HTTP_OK || responseCode == HttpURLConnection.HTTP_NO_CONTENT) {
+ inputStream = con.getInputStream();
+ } else {
+ inputStream = con.getErrorStream();
+ }
+
+ // Process the response
+ LOG.debug("HttpURLConnection result:" + responseCode);
+ if(inputStream == null) inputStream = new ByteArrayInputStream("".getBytes(StandardCharsets.UTF_8));
+ BufferedReader reader = new BufferedReader( new InputStreamReader( inputStream ) );
+ String line = null;
+
+ ObjectMapper mapper = getObjectMapper();
+
+ if (responseCode == HttpURLConnection.HTTP_OK || responseCode == HttpURLConnection.HTTP_NO_CONTENT) {
+ StringBuilder stringBuilder = new StringBuilder();
+
+ while( ( line = reader.readLine() ) != null ) {
+ stringBuilder.append( line );
+ }
+ LOGwriteEndingTrace(responseCode, "SUCCESS", stringBuilder.toString());
+ response = true;
+ } else if(responseCode == HttpURLConnection.HTTP_NOT_FOUND ) {
+ LOGwriteEndingTrace(responseCode, "HTTP_NOT_FOUND", "Entry does not exist.");
+ response = false;
+ } else {
+ ErrorResponse errorresponse = mapper.readValue(reader, ErrorResponse.class);
+ LOGwriteEndingTrace(responseCode, "FAILURE", mapper.writeValueAsString(errorresponse));
+ throw new AAIServiceException(responseCode, errorresponse);
+ }
+
+ } catch(AAIServiceException aaiexc) {
+ throw aaiexc;
+ } catch (Exception exc) {
+ LOG.warn(caller, exc);
+ throw new AAIServiceException(exc);
+ } finally {
+ if(inputStream != null){
+ try {
+ inputStream.close();
+ } catch(Exception exc) {
+ LOG.warn("Error closing InputStream", exc);
+ }
+ }
+ }
+ return response;
+ }
+
+ /**
+ * Generic method to GET json data from an A&AI callback URL.
+ * Then convert that json to an Object.
+ * If successful the Object is attempted to be cast to the type parameter.
+ *
+ * @param key
+ * callback url for A&AI
+ * @param type
+ * the class of object that A&AI will return
+ * @return the object created from json or null if the response code is not 200
+ *
+ * @throws AAIServiceException
+ * if empty or null key and or type or there's an error with processing
+ */
+ public <T> T dataChangeRequestAaiData(String key, Class<T> type) throws AAIServiceException {
+ if (StringUtils.isEmpty(key) || type == null) {
+ throw new AAIServiceException("Key is empty or null and or type is null");
+ }
+
+ T response = null;
+
+ SvcLogicContext ctx = new SvcLogicContext();
+ if(!key.contains(" = ") && isValidURL(key)) {
+ key = String.format("selflink = '%s'", key);
+ } else
+ if(!key.contains(" = ") && isValidURI(key)) {
+ key = String.format("resource-path = '%s'", key);
+ }
+
+ HashMap<String, String> nameValues = AAIServiceUtils.keyToHashMap(key, ctx);
+
+ SelfLinkRequest request = new SelfLinkRequest(type);
+ request.processRequestPathValues(nameValues);
+ Object obj = this.getExecutor().query(request, type);
+ response = type.cast(obj);
+
+ return response != null ? type.cast(response) : response;
+ }
+
+
+ public boolean sendNotify(NotifyEvent event, String serviceInstanceId, String pathCode) throws AAIServiceException {
+ InputStream inputStream = null;
+
+ try {
+
+ String selfLink = selflinkFqdn;
+ if(SELFLINK_AVPN != null && SELFLINK_AVPN.equals(pathCode)) {
+ selfLink = selflinkAvpn;
+ }
+ selfLink = selfLink.replace("{service-instance-id}", encodeQuery(serviceInstanceId));
+ event.setSelflink(selfLink);
+
+ ObjectMapper mapper = getObjectMapper();
+ String json_text = mapper.writeValueAsString(event);
+
+ SSLSocketFactory sockFact = CTX.getSocketFactory();
+
+ String request_url = targetUri+ubb_notify_path;
+ URL http_req_url = new URL(request_url);
+
+ HttpURLConnection con = getConfiguredConnection(http_req_url, HttpMethod.PUT);
+
+ if (json_text != null) {
+ OutputStreamWriter osw = new OutputStreamWriter(con.getOutputStream());
+ osw.write(json_text);
+ osw.flush();
+ osw.close();
+ }
+
+ LOGwriteFirstTrace("PUT", request_url);
+ LOGwriteDateTrace("NotifyEvent", json_text);
+
+ // Check for errors
+ int responseCode = con.getResponseCode();
+ if (responseCode == HttpURLConnection.HTTP_OK || responseCode == HttpURLConnection.HTTP_CREATED || responseCode == HttpURLConnection.HTTP_ACCEPTED || responseCode == HttpURLConnection.HTTP_NO_CONTENT) {
+ inputStream = con.getInputStream();
+ } else {
+ inputStream = con.getErrorStream();
+ }
+
+ // Process the response
+ BufferedReader reader;
+ String line = null;
+ reader = new BufferedReader( new InputStreamReader( inputStream ) );
+
+ if (responseCode == HttpURLConnection.HTTP_OK || responseCode == HttpURLConnection.HTTP_CREATED || responseCode == HttpURLConnection.HTTP_ACCEPTED || responseCode == HttpURLConnection.HTTP_NO_CONTENT) {
+ StringBuilder stringBuilder = new StringBuilder();
+
+ while( ( line = reader.readLine() ) != null ) {
+ stringBuilder.append( line );
+ }
+ LOGwriteEndingTrace(responseCode, "SUCCESS", (stringBuilder.length() > 0) ? stringBuilder.toString() :
+ "{no-data}");
+ return true;
+ } else {
+ ErrorResponse errorresponse = mapper.readValue(reader, ErrorResponse.class);
+ LOGwriteEndingTrace(responseCode, "FAILURE", mapper.writeValueAsString(errorresponse));
+
+ throw new AAIServiceException(responseCode, errorresponse);
+ }
+ } catch(AAIServiceException aaiexc) {
+ throw aaiexc;
+ } catch (Exception exc) {
+ LOG.warn("sendNotify", exc);
+ throw new AAIServiceException(exc);
+ } finally {
+ try {
+ if(inputStream != null)
+ inputStream.close();
+ } catch (Exception exc) {
+ LOG.warn("Error closing Input stream", exc);
+ }
+ }
+ }
+
+ @Override
+ public SearchResults requestNodeQuery(String node_type, String entityIdentifier, String entityName) throws AAIServiceException {
+ SearchResults response = null;
+ InputStream inputStream = null;
+
+ try {
+ String request_url = targetUri+queryNodesPath;
+ request_url = request_url.replace("{node-type}", encodeQuery(node_type)) ;
+ request_url = request_url.replace("{entity-identifier}", entityIdentifier) ;
+ request_url = request_url.replace("{entity-name}", encodeQuery(entityName)) ;
+ URL http_req_url = new URL(request_url);
+
+ HttpURLConnection con = getConfiguredConnection(http_req_url, HttpMethod.GET);
+
+ LOGwriteFirstTrace(HttpMethod.GET, http_req_url.toString());
+ LOGwriteDateTrace("node_type", node_type);
+ LOGwriteDateTrace("vnf_name", entityName);
+
+ // Check for errors
+ int responseCode = con.getResponseCode();
+ if (responseCode == HttpURLConnection.HTTP_OK) {
+ inputStream = con.getInputStream();
+ } else {
+ inputStream = con.getErrorStream();
+ }
+
+ // Process the response
+ LOG.debug("HttpURLConnection result:" + responseCode);
+ if(inputStream == null) inputStream = new ByteArrayInputStream("".getBytes(StandardCharsets.UTF_8));
+ BufferedReader reader = new BufferedReader( new InputStreamReader( inputStream ) );
+
+ ObjectMapper mapper = getObjectMapper();
+
+ if (responseCode == HttpURLConnection.HTTP_OK) {
+ response = mapper.readValue(reader, SearchResults.class);
+ LOGwriteEndingTrace(HttpURLConnection.HTTP_OK, "SUCCESS", mapper.writeValueAsString(response));
+ } else if (responseCode == HttpURLConnection.HTTP_NOT_FOUND) {
+ LOGwriteEndingTrace(responseCode, "HTTP_NOT_FOUND", "Entry does not exist.");
+ return response;
+ } else {
+ ErrorResponse errorresponse = mapper.readValue(reader, ErrorResponse.class);
+ LOGwriteEndingTrace(responseCode, "FAILURE", mapper.writeValueAsString(errorresponse));
+ throw new AAIServiceException(responseCode, errorresponse);
+ }
+
+ } catch(AAIServiceException aaiexc) {
+ throw aaiexc;
+ } catch (Exception exc) {
+ LOG.warn("requestNodeQuery", exc);
+ throw new AAIServiceException(exc);
+ } finally {
+ if(inputStream != null){
+ try {
+ inputStream.close();
+ } catch(Exception exc) {
+ LOG.warn("Error closing Input stream", exc);
+ }
+ }
+ }
+ return response;
+
+ }
+
+
+ @Override
+ public String requestDataByURL(URL url) throws AAIServiceException {
+
+ if(url == null) {
+ throw new NullPointerException();
+ }
+
+ String response = null;
+ InputStream inputStream = null;
+
+ try {
+ URL http_req_url = url;
+
+ HttpURLConnection con = getConfiguredConnection(http_req_url, HttpMethod.GET);
+
+ LOGwriteFirstTrace(HttpMethod.GET, http_req_url.toString());
+
+ // Check for errors
+ int responseCode = con.getResponseCode();
+ if (responseCode == HttpURLConnection.HTTP_OK) {
+ inputStream = con.getInputStream();
+ } else {
+ inputStream = con.getErrorStream();
+ }
+
+ // Process the response
+ LOG.debug("HttpURLConnection result:" + responseCode);
+ if(inputStream == null) inputStream = new ByteArrayInputStream("".getBytes(StandardCharsets.UTF_8));
+ BufferedReader reader = new BufferedReader( new InputStreamReader( inputStream ) );
+
+ ObjectMapper mapper = getObjectMapper();
+
+ if (responseCode == HttpURLConnection.HTTP_OK) {
+ StringBuilder stringBuilder = new StringBuilder("\n");
+ String line = null;
+ while( ( line = reader.readLine() ) != null ) {
+ stringBuilder.append( line );
+ }
+ LOG.info(stringBuilder.toString());
+// response = mapper.readValue(reader, String.class);
+ response = stringBuilder.toString();
+ LOGwriteEndingTrace(HttpURLConnection.HTTP_OK, "SUCCESS", mapper.writeValueAsString(response));
+ } else if(responseCode == HttpURLConnection.HTTP_NOT_FOUND ) {
+ LOGwriteEndingTrace(responseCode, "HTTP_NOT_FOUND", "Entry does not exist.");
+ response = null;
+ } else {
+ ErrorResponse errorresponse = mapper.readValue(reader, ErrorResponse.class);
+ LOGwriteEndingTrace(responseCode, "FAILURE", mapper.writeValueAsString(errorresponse));
+ throw new AAIServiceException(responseCode, errorresponse);
+ }
+
+ } catch(AAIServiceException aaiexc) {
+ throw aaiexc;
+ } catch (Exception exc) {
+ LOG.warn("requestNetworkVceData", exc);
+ throw new AAIServiceException(exc);
+ } finally {
+ if(inputStream != null){
+ try {
+ inputStream.close();
+ } catch(Exception exc) {
+ LOG.warn("Error closing Input stream", exc);
+ }
+ }
+ }
+ return response;
+ }
+
+
+ @Override
+ public GenericVnf requestGenericVnfeNodeQuery(String vnf_name) throws AAIServiceException {
+
+ if(vnf_name == null) {
+ throw new NullPointerException();
+ }
+
+ GenericVnf entity = null;
+ SearchResults resp = this.requestNodeQuery("generic-vnf", "vnf-name", vnf_name);
+
+ List<ResultData> resultDataList = resp.getResultData();
+
+ try {
+ for (ResultData datum : resultDataList) {
+ URI url = new URI(datum.getResourceLink());
+ entity = this.getResource(url.toString(), GenericVnf.class);
+ }
+ }
+ catch (Exception e)
+ {
+ LOG.error("Caught exception", e);
+ }
+ return entity;
+ }
+
+ @Override
+ public Vserver requestVServerDataByURL(URL url) throws AAIServiceException {
+
+ if(url == null) {
+ throw new NullPointerException();
+ }
+
+ Vserver entity = null;
+
+ try {
+ entity = this.getResource(url.toString(), Vserver.class);
+ } catch (AAIServiceException exc) {
+ throw exc;
+ } catch (Exception e) {
+ throw new AAIServiceException(e);
+ }
+ return entity;
+ }
+
+ @Override
+ public URL requestVserverURLNodeQuery(String vserver_name) throws AAIServiceException {
+
+ if(vserver_name == null) {
+ throw new NullPointerException();
+ }
+
+ URL entity = null;
+ SearchResults resp = this.requestNodeQuery("vserver", "vserver-name", vserver_name);
+
+ List<ResultData> resultDataList = resp.getResultData();
+
+ try {
+ for (ResultData datum : resultDataList) {
+ String data_type = datum.getResourceType();
+ String resourceLink = datum.getResourceLink();
+ if(!resourceLink.isEmpty() && !resourceLink.toLowerCase().startsWith("http")) {
+ resourceLink = (new EchoRequest()).targetUri + resourceLink;
+ }
+ entity = new URL(resourceLink);
+ }
+ } catch (Exception e) {
+ throw new AAIServiceException(e);
+ }
+ return entity;
+ }
+
+ @Override
+ public String getTenantIdFromVserverUrl(URL url) {
+
+ String path = url.getPath();
+
+ String[] split = path.split("/tenants/tenant/");
+ if(split.length > 1) {
+ split = split[1].split("/");
+ return split[0];
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ public String getCloudOwnerFromVserverUrl(URL url) {
+
+ String path = url.getPath();
+
+ String[] split = path.split("/cloud-regions/cloud-region/");
+ if(split.length > 1) {
+ split = split[1].split("/");
+ return split[0];
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ public String getCloudRegionFromVserverUrl(URL url) {
+
+ String path = url.getPath();
+
+ String[] split = path.split("/cloud-regions/cloud-region/");
+ if(split.length > 1) {
+ split = split[1].split("/");
+ return split[1];
+ } else {
+ return null;
+ }
+ }
+
+ @Override
+ public String getVServerIdFromVserverUrl(URL url, String tenantId) {
+ String pattern = networkVserverPath;
+ pattern = pattern.replace("{tenant-id}", tenantId);
+
+ int end = pattern.indexOf("{vserver-id}");
+ String prefix = pattern.substring(0, end);
+
+ String path = url.getPath();
+
+ if(path.startsWith(prefix)) {
+ path = path.substring(prefix.length());
+ }
+
+ return path;
+ }
+
+ protected Logger getLogger(){
+ return LOG;
+ }
+
+
+ @Override
+ public AAIExecutorInterface getExecutor() {
+ return executor;
+ }
+
+ /**
+ * Creates a current time stamp in UTC i.e. 2016-03-08T22:15:13.343Z.
+ * If there are any parameters the values are appended to the time stamp.
+ *
+ * @param parameters
+ * values to be appended to current time stamp
+ * @param ctx
+ * used to set an attribute for a DG
+ * @throws SvcLogicException
+ */
+ public void setStatusMethod(Map<String, String> parameters, SvcLogicContext ctx) throws SvcLogicException {
+ if (ctx == null) {
+ throw new SvcLogicException("SvcLogicContext is null.");
+ }
+
+ StringBuilder sb = new StringBuilder();
+ sb.append(String.format("%tFT%<tTZ", Calendar.getInstance(TimeZone.getTimeZone("Z")))).append(" - ");
+
+ for (Entry<String, String> entry : parameters.entrySet()) {
+ sb.append(entry.getValue()).append(" ");
+ }
+
+ if (sb.length() > 0) {
+ sb.setLength(sb.length() - 2);
+ }
+
+ ctx.setAttribute("aai-summary-status-message", sb.toString());
+ LOG.info("aai-summary-status-message: " + sb.toString());
+ }
+
+ /**
+ * Generic method to GET json data from an A&AI using key structure.
+ * Then convert that json to an Object.
+ * If successful the Object is attempted to be cast to the type parameter.
+ *
+ * @param key
+ * key identifying the resource to be retrieved from AAI
+ * @param type
+ * the class of object that A&AI will return
+ * @return the object created from json or null if the response code is not 200
+ *
+ * @throws AAIServiceException
+ * if empty or null key and or type or there's an error with processing
+ */
+
+ public <T> T getResource(String key, Class<T> type) throws AAIServiceException {
+ if (StringUtils.isEmpty(key) || type == null) {
+ throw new AAIServiceException("Key is empty or null and or type is null");
+ }
+
+ T response = null;
+
+ SvcLogicContext ctx = new SvcLogicContext();
+ if(!key.contains(" = ")) {
+ if(isValidURL(key)) {
+ key = String.format("selflink = '%s'", key);
+ } else if(isValidURI(key)) {
+ key = String.format("resource-path = '%s'", key);
+ } else {
+ return response;
+ }
+ }
+
+ HashMap<String, String> nameValues = AAIServiceUtils.keyToHashMap(key, ctx);
+
+ AAIRequest request = new SelfLinkRequest(type);
+ if(nameValues.containsKey(PathRequest.RESOURCE_PATH.replaceAll("-", "_"))) {
+ request = new PathRequest(type);
+ }
+
+ request.processRequestPathValues(nameValues);
+ Object obj = this.getExecutor().query(request, type);
+ response = type.cast(obj);
+
+ return response != null ? type.cast(response) : response;
+ }
+
+ public boolean isValidURL(String url) {
+
+ URL u = null;
+
+ try {
+ u = new URL(url);
+ } catch (MalformedURLException e) {
+ LOG.warn("MalformedURLException", e);
+ return false;
+ }
+
+ try {
+ u.toURI();
+ } catch (URISyntaxException e) {
+ LOG.warn("URISyntaxException", e);
+ return false;
+ }
+
+ return true;
+ }
+
+
+ public boolean isValidURI(String url) {
+
+ URI u = null;
+
+ try {
+ u = new URI(url);
+ } catch (URISyntaxException e) {
+ LOG.warn("URISyntaxException", e);
+ return false;
+ }
+
+ return true;
+ }
+
+
+ protected boolean deleteList(URL httpReqUrl, String jsonText) throws AAIServiceException {
+ if(httpReqUrl == null) {
+ throw new NullPointerException();
+ }
+
+ boolean response = false;
+ InputStream inputStream = null;
+
+ try {
+ HttpURLConnection con = getConfiguredConnection(httpReqUrl, HttpMethod.DELETE);
+
+// SSLSocketFactory sockFact = CTX.getSocketFactory();
+// con.setSSLSocketFactory( sockFact );
+ if (jsonText != null) {
+ OutputStreamWriter osw = new OutputStreamWriter(con.getOutputStream());
+ osw.write(jsonText);
+ osw.flush();
+ osw.close();
+ }
+
+ LOGwriteFirstTrace("DELETE", httpReqUrl.toString());
+ LOGwriteDateTrace("data", jsonText);
+
+ // Check for errors
+ int responseCode = con.getResponseCode();
+ if (responseCode == HttpURLConnection.HTTP_OK || responseCode == HttpURLConnection.HTTP_NO_CONTENT) {
+ inputStream = con.getInputStream();
+ } else {
+ inputStream = con.getErrorStream();
+ }
+
+ // Process the response
+ LOG.debug("HttpURLConnection result:" + responseCode);
+ if(inputStream == null) inputStream = new ByteArrayInputStream("".getBytes(StandardCharsets.UTF_8));
+ BufferedReader reader = new BufferedReader( new InputStreamReader( inputStream ) );
+ String line = null;
+
+ ObjectMapper mapper = getObjectMapper();
+
+ if (responseCode == HttpURLConnection.HTTP_OK || responseCode == HttpURLConnection.HTTP_NO_CONTENT) {
+ StringBuilder stringBuilder = new StringBuilder();
+
+ while( ( line = reader.readLine() ) != null ) {
+ stringBuilder.append( line );
+ }
+ LOGwriteEndingTrace(responseCode, "SUCCESS", stringBuilder.toString());
+ response = true;
+ } else if(responseCode == HttpURLConnection.HTTP_NOT_FOUND ) {
+ LOGwriteEndingTrace(responseCode, "HTTP_NOT_FOUND", "Entry does not exist.");
+ response = false;
+ } else {
+ ErrorResponse errorresponse = mapper.readValue(reader, ErrorResponse.class);
+ LOGwriteEndingTrace(responseCode, "FAILURE", mapper.writeValueAsString(errorresponse));
+ throw new AAIServiceException(responseCode, errorresponse);
+ }
+
+ } catch(AAIServiceException aaiexc) {
+ throw aaiexc;
+ } catch (Exception exc) {
+ LOG.warn("deleteList", exc);
+ throw new AAIServiceException(exc);
+ } finally {
+ if(inputStream != null){
+ try {
+ inputStream.close();
+ } catch(Exception exc) {
+
+ }
+ }
+ }
+ return response;
+ }
+
+ public static ObjectMapper getObjectMapper() {
+ ObjectMapper mapper = new ObjectMapper();
+ AnnotationIntrospector introspector = new JaxbAnnotationIntrospector(TypeFactory.defaultInstance());
+ AnnotationIntrospector secondary = new JacksonAnnotationIntrospector();
+ mapper.setAnnotationIntrospector(AnnotationIntrospector.pair(introspector, secondary));
+ mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
+ mapper.setSerializationInclusion(Include.NON_NULL);
+ mapper.setSerializationInclusion(Include.NON_EMPTY);
+ return mapper;
+ }
+
+ public void logMetricRequest(String requestId, String targetServiceName, String msg, String path){
+ String svcInstanceId = "";
+ String svcName = null;
+ String partnerName = null;
+ String targetEntity = "A&AI";
+ String targetVirtualEntity = null;
+
+ ml.logRequest(svcInstanceId, svcName, partnerName, targetEntity, targetServiceName, targetVirtualEntity, msg);
+ }
+
+ public void logMetricResponse(String requestId, int responseCode, String responseDescription){
+ ml.logResponse(responseCode < 400 ? "COMPLETE" : "ERROR", Integer.toString(responseCode), responseDescription);
+ }
+
+ public void logKeyError(String keys){
+ LOG.error("Atleast one of the keys [" + keys + "] should have been populated. This will cause a NPE.");
+ }
+
+
+ /**
+ * Retrofit code
+ */
+ @Override
+ public QueryStatus save(String resource, boolean force, boolean localOnly, String key, Map<String, String> params, String prefix, SvcLogicContext ctx)
+ throws SvcLogicException {
+ String normResource = resource.split(":")[0];
+
+ switch(normResource){
+ case "custom-query":
+ case "formatted-query":
+ case "generic-query":
+ case "nodes-query":
+ case "linterface":
+ case "l2-bridge-sbg":
+ case "l2-bridge-bgf":
+ case "echo":
+ case "test":
+ break;
+
+ default:
+ if(key.contains("selflink =")) {
+ break;
+ }
+ if(!key.contains(String.format("%s.", normResource))) {
+ key = rewriteKey(resource, key, ctx);
+ }
+ }
+ return super.save(resource, force, localOnly, key, params, prefix, ctx);
+ }
+
+ @Override
+ public QueryStatus query(String resource, boolean localOnly, String select, String key, String prefix, String orderBy, SvcLogicContext ctx)
+ throws SvcLogicException {
+ String normResource = resource.split(":")[0];
+
+ switch(normResource){
+ case "custom-query":
+ case "formatted-query":
+ case "generic-query":
+ case "nodes-query":
+ case "linterface":
+ case "l2-bridge-sbg":
+ case "l2-bridge-bgf":
+ case "echo":
+ case "test":
+ break;
+
+ default:
+ if(key.contains("selflink =")) {
+ break;
+ }
+ if(!key.contains(String.format("%s.", normResource))) {
+ key = rewriteKey(resource, key, ctx);
+ }
+ }
+
+ return super.query(resource, localOnly, select, key, prefix, orderBy, ctx);
+ }
+
+ @Override
+ public QueryStatus delete(String resource, String key, SvcLogicContext ctx) throws SvcLogicException {
+ String normResource = resource.split(":")[0];
+
+ switch(normResource){
+ case "custom-query":
+ case "formatted-query":
+ case "generic-query":
+ case "nodes-query":
+ case "linterface":
+ case "l2-bridge-sbg":
+ case "l2-bridge-bgf":
+ case "echo":
+ case "test":
+ break;
+
+ default:
+ if(key.contains("selflink =")) {
+ break;
+ }
+ if(!key.contains(String.format("%s.", normResource))) {
+ key = rewriteKey(resource, key, ctx);
+ }
+ }
+
+ return super.delete(resource, key, ctx);
+ }
+
+ @Override
+ public QueryStatus update(String resource, String key, Map<String, String> params, String prefix, SvcLogicContext ctx) throws SvcLogicException {
+ String normResource = resource.split(":")[0];
+
+ switch(normResource){
+ case "custom-query":
+ case "formatted-query":
+ case "generic-query":
+ case "nodes-query":
+ case "linterface":
+ case "l2-bridge-sbg":
+ case "l2-bridge-bgf":
+ case "echo":
+ case "test":
+ break;
+
+ default:
+ if(key.contains("selflink =")) {
+ break;
+ }
+ if(!key.contains(String.format("%s.", normResource))) {
+ key = rewriteKey(resource, key, ctx);
+ }
+ }
+
+ return super.update(resource, key, params, prefix, ctx);
+ }
+
+ private String rewriteKey(String resource, String key, SvcLogicContext ctx) {
+ LOG.info("AAI Deprecation - the format of request key is no longer supported. Please rewrite this key : " + key);
+
+ String normResource = resource.split(":")[0];
+ Class<? extends AAIDatum> clazz = AAIRequest.getClassFromResource(normResource) ;
+
+ if(clazz == null)
+ return key;
+
+ List<String> fieldAnnotatedNames = new LinkedList<>();
+
+ Field[] fields = clazz.getDeclaredFields();
+ for(Field field : fields) {
+ String fieldName = field.getName();
+ XmlElement annotation = field.getAnnotation(XmlElement.class);
+ if(annotation == null)
+ continue;
+ String primaryId = annotation.name();
+ if("##default".equals(primaryId)) {
+ primaryId = fieldName;
+ }
+ fieldAnnotatedNames.add(primaryId);
+ }
+
+ HashMap<String, String> nameValues = AAIServiceUtils.keyToHashMap(key, ctx);
+ Set<String> keyset = nameValues.keySet();
+ for(String keyName : keyset) {
+ if(keyName.contains("."))
+ continue;
+ else {
+ String tmpKeyName = keyName.replaceAll("_", "-");
+ String valueToSubstitute = String.format("%s =", tmpKeyName);
+ if(fieldAnnotatedNames.contains(tmpKeyName) && key.contains(valueToSubstitute)) {
+ key = key.replace(valueToSubstitute, String.format("%s.%s =", normResource, tmpKeyName));
+ }
+ }
+ }
+
+
+ return key;
+ }
+
+ @Override
+ public String getPathTemplateForResource(String resoourceName, String keys, SvcLogicContext ctx) throws MalformedURLException {
+ return AAIServiceUtils.getPathForResource(resoourceName, StringUtils.join(keys, " AND "), ctx);
+ }
+
+ @Override
+ public boolean isDeprecatedFormat(String resource, Map<String, String> nameValues) {
+ return !AAIServiceUtils.isValidFormat(resource, nameValues);
+ }
+
+ public AAIRequest getRequestFromResource(String resoourceName) {
+ return AAIRequest.getRequestFromResource(resoourceName);
+ }
+
+ /* (non-Javadoc)
+ * @see org.onap.ccsdk.sli.core.sli.aai.haha#query(org.onap.ccsdk.sli.core.sli.aai.AAIRequest)
+ */
+ @Override
+ public String query(AAIRequest request) throws AAIServiceException {
+ return executor.get(request);
+ }
+
+ /* (non-Javadoc)
+ * @see org.onap.ccsdk.sli.core.sli.aai.haha#save(org.onap.ccsdk.sli.core.sli.aai.AAIRequest)
+ */
+ @Override
+ public String save(AAIRequest request) throws AAIServiceException {
+ return executor.post(request);
+ }
+
+ public boolean update(AAIRequest request, String resourceVersion) throws AAIServiceException {
+ return executor.patch(request, resourceVersion);
+ }
+
+ /* (non-Javadoc)
+ * @see org.onap.ccsdk.sli.core.sli.aai.haha#delete(org.onap.ccsdk.sli.core.sli.aai.AAIRequest, java.lang.String)
+ */
+ @Override
+ public boolean delete(AAIRequest request, String resourceVersion) throws AAIServiceException {
+ return executor.delete(request, resourceVersion);
+ }
+
+}
diff --git a/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/AAIServiceException.java b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/AAIServiceException.java
new file mode 100755
index 000000000..2f774e407
--- /dev/null
+++ b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/AAIServiceException.java
@@ -0,0 +1,89 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+/**
+ * @author Rich Tabedzki
+ *
+ */
+package org.onap.ccsdk.sli.adaptors.aai;
+
+import org.onap.ccsdk.sli.adaptors.aai.data.ErrorResponse;
+
+public class AAIServiceException extends Exception {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -9039257722542999522L;
+
+ protected final ErrorResponse errorResponse;
+ protected final int returnCode;
+
+ public AAIServiceException() {
+ returnCode = -1;
+ errorResponse = null;
+ }
+
+ public AAIServiceException(String message) {
+ super(message);
+ returnCode = -1;
+ errorResponse = null;
+ }
+
+ public AAIServiceException(Throwable cause) {
+ super(cause);
+ returnCode = -1;
+ errorResponse = null;
+ }
+
+ public AAIServiceException(String message, Throwable cause) {
+ super(message, cause);
+ returnCode = -1;
+ errorResponse = null;
+ }
+
+ public AAIServiceException(String message, Throwable cause,
+ boolean enableSuppression, boolean writableStackTrace) {
+ super(message, cause, enableSuppression, writableStackTrace);
+ returnCode = -1;
+ errorResponse = null;
+ }
+
+ public AAIServiceException(int returnCode, ErrorResponse errorresponse) {
+ this.errorResponse = errorresponse;
+ this.returnCode = returnCode;
+ }
+
+ public ErrorResponse getErrorResponse() {
+ return errorResponse;
+ }
+
+ public int getReturnCode() {
+ return returnCode;
+ }
+
+ public String getMessage() {
+ if(errorResponse != null) {
+ return errorResponse.getRequestError().getServiceException().getText();
+ } else {
+ return super.getMessage();
+ }
+ }
+}
diff --git a/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/AAIServiceProvider.java b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/AAIServiceProvider.java
new file mode 100755
index 000000000..743f975b6
--- /dev/null
+++ b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/AAIServiceProvider.java
@@ -0,0 +1,226 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 - 2018 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+/**
+ * @author Rich Tabedzki
+ *
+ */
+package org.onap.ccsdk.sli.adaptors.aai;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.util.Optional;
+import java.util.Properties;
+import java.util.Vector;
+
+import org.onap.ccsdk.sli.core.utils.JREFileResolver;
+import org.onap.ccsdk.sli.core.utils.KarafRootFileResolver;
+import org.onap.ccsdk.sli.core.utils.PropertiesFileResolver;
+import org.onap.ccsdk.sli.core.utils.common.BundleContextFileResolver;
+import org.onap.ccsdk.sli.core.utils.common.CoreDefaultFileResolver;
+import org.onap.ccsdk.sli.core.utils.common.SdncConfigEnvVarFileResolver;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.ServiceReference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Responsible for determining the properties file to use and instantiating the <code>DBResourceManager</code>
+ * Service. The priority for properties file resolution is as follows:
+ *
+ * <ol>
+ * <li>A directory identified by the system environment variable <code>SDNC_CONFIG_DIR</code></li>
+ * <li>The default directory <code>DEFAULT_DBLIB_PROP_DIR</code></li>
+ * <li>A directory identified by the JRE argument <code>dblib.properties</code></li>
+ * <li>A <code>dblib.properties</code> file located in the karaf root directory</li>
+ * </ol>
+ *
+ * Encryption Support
+ * <ol>
+ * <li>Uses ecryption provided by <code>AAAEncryptionService</code></li>
+ * <li>AAA Configuration file is <code>aaa-cert-config.xml</code></li>
+ * </ol>
+ *
+ */
+public class AAIServiceProvider implements UtilsProvider {
+
+ private static final Logger LOG = LoggerFactory.getLogger(AAIServiceProvider.class);
+
+ /**
+ * The name of the properties file for database configuration
+ */
+ private static final String AAISEERVICE_PROP_FILE_NAME = "aaiclient.properties";
+
+ /**
+ * The name of the pwd key
+ */
+ private static final String AAICLIENT_PROPERTY_NAME = "org.onap.ccsdk.sli.adaptors.aai.client.psswd";
+
+ /**
+ * A prioritized list of strategies for resolving dblib properties files.
+ */
+ private Vector<PropertiesFileResolver> dblibPropertiesFileResolvers = new Vector<>();
+
+ /**
+ * The configuration properties for the db connection.
+ */
+ private Properties properties;
+
+ /**
+ * Set up the prioritized list of strategies for resolving dblib properties files.
+ */
+ public AAIServiceProvider() {
+ dblibPropertiesFileResolvers.add(new SdncConfigEnvVarFileResolver(
+ "Using property file (1) from environment variable"
+ ));
+ dblibPropertiesFileResolvers.add(new JREFileResolver(
+ "Using property file (2) from JRE argument", AAIServiceProvider.class
+ ));
+ dblibPropertiesFileResolvers.add(new BundleContextFileResolver(
+ "Using property file (3) from JRE argument", AAIServiceProvider.class
+ ));
+ dblibPropertiesFileResolvers.add(new KarafRootFileResolver(
+ "Using property file (4) from karaf root", this
+ ));
+ dblibPropertiesFileResolvers.add(new CoreDefaultFileResolver(
+ "Using property file (5) from default directory"
+ ));
+
+ // determines properties file as according to the priority described in the class header comment
+ final File propertiesFile = determinePropertiesFile();
+ if (propertiesFile != null) {
+ try(FileInputStream fileInputStream = new FileInputStream(propertiesFile)) {
+ properties = new Properties();
+ properties.load(fileInputStream);
+
+ if(properties.containsKey(AAICLIENT_PROPERTY_NAME)) {
+ String sensitive = properties.getProperty(AAICLIENT_PROPERTY_NAME);
+ if(sensitive != null && sensitive.startsWith("ENC:")) {
+ try {
+ sensitive = sensitive.substring(4);
+ String postsense = decrypt(sensitive);
+ properties.setProperty(AAICLIENT_PROPERTY_NAME, postsense);
+ } catch(Exception exc) {
+ LOG.error("Failed to translate property", exc);
+ }
+ }
+ }
+ } catch (final IOException e) {
+ LOG.error("Failed to load properties for file: {}", propertiesFile.toString(),
+ new AAIServiceException("Failed to load properties for file: "
+ + propertiesFile.toString(), e));
+ }
+ }
+ }
+
+ /**
+ *
+ * @param value
+ * @return decrypted string if successful or the original value if unsuccessful
+ */
+ private String decrypt(String value) {
+ try {
+ BundleContext bctx = FrameworkUtil.getBundle(this.getClass()).getBundleContext();
+
+ ServiceReference sref = bctx.getServiceReference("org.opendaylight.aaa.encrypt.AAAEncryptionService");
+ if(sref == null) {
+ LOG.warn("Could not acquire service reference for 'org.opendaylight.aaa.encrypt.AAAEncryptionService'");
+ return value;
+ }
+ Object encrSvc = bctx.getService(sref);
+ if(encrSvc == null) {
+ LOG.warn("Could not access service for 'org.opendaylight.aaa.encrypt.AAAEncryptionService'");
+ return value;
+ }
+
+ Method gs2Method = encrSvc.getClass().getMethod("decrypt", new Class[] { "".getClass() });
+ Object unmasked = gs2Method.invoke(encrSvc, new Object[] { value });
+ return unmasked.toString();
+
+ } catch (Exception|NoClassDefFoundError exc) {
+ LOG.error("Failure", exc);
+ return value;
+ }
+ }
+
+ /**
+ * Extract db config properties.
+ *
+ * @return the db config properties
+ */
+ public Properties getProperties() {
+ return properties;
+ }
+
+ /**
+ * Reports the method chosen for properties resolution to the <code>Logger</code>.
+ *
+ * @param message Some user friendly message
+ * @param fileOptional The file location of the chosen properties file
+ * @return the file location of the chosen properties file
+ */
+ private static File reportSuccess(final String message, final Optional<File> fileOptional) {
+ if(fileOptional.isPresent()) {
+ final File file = fileOptional.get();
+ LOG.info("{} {}", message, file.getPath());
+ return file;
+ }
+ return null;
+ }
+
+ /**
+ * Reports fatal errors. This is the case in which no properties file could be found.
+ *
+ * @param message An appropriate fatal error message
+ * @param dblibConfigurationException An exception describing what went wrong during resolution
+ */
+ private static void reportFailure(final String message,
+ final AAIServiceException dblibConfigurationException) {
+
+ LOG.error("{}", message, dblibConfigurationException);
+ }
+
+ /**
+ * Determines the dblib properties file to use based on the following priority:
+ * <ol>
+ * <li>A directory identified by the system environment variable <code>SDNC_CONFIG_DIR</code></li>
+ * <li>The default directory <code>DEFAULT_DBLIB_PROP_DIR</code></li>
+ * <li>A directory identified by the JRE argument <code>dblib.properties</code></li>
+ * <li>A <code>dblib.properties</code> file located in the karaf root directory</li>
+ * </ol>
+ */
+ File determinePropertiesFile() {
+
+ for (final PropertiesFileResolver dblibPropertiesFileResolver : dblibPropertiesFileResolvers) {
+ final Optional<File> fileOptional = dblibPropertiesFileResolver.resolveFile(AAISEERVICE_PROP_FILE_NAME);
+ if (fileOptional.isPresent()) {
+ return reportSuccess(dblibPropertiesFileResolver.getSuccessfulResolutionMessage(), fileOptional);
+ }
+ }
+
+ reportFailure("Missing configuration properties resource(3)",
+ new AAIServiceException("Missing configuration properties resource(3): "
+ + AAISEERVICE_PROP_FILE_NAME));
+ return null;
+ }
+}
diff --git a/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/AAIServiceUtils.java b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/AAIServiceUtils.java
new file mode 100755
index 000000000..b3ee7474d
--- /dev/null
+++ b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/AAIServiceUtils.java
@@ -0,0 +1,394 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Modifications Copyright (C) 2018 IBM.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+/**
+ * @author Rich Tabedzki
+ *
+ */
+package org.onap.ccsdk.sli.adaptors.aai;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+import javax.xml.bind.annotation.XmlType;
+
+import org.apache.commons.lang.StringUtils;
+import org.onap.aai.inventory.v21.Relationship;
+import org.onap.aai.inventory.v21.RelationshipData;
+import org.onap.aai.inventory.v21.RelationshipList;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.adaptors.aai.data.AAIDatum;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class AAIServiceUtils {
+
+ private static final String VERSION_PATTERN = "/v$/";
+
+ private static final Logger LOG = LoggerFactory.getLogger(AAIService.class);
+
+ private AAIServiceUtils() {
+ }
+
+ public static String getPrimaryIdFromClass(Class<? extends AAIDatum> resourceClass){
+ // 1. find class
+ getLogger().debug(resourceClass.getName());
+
+ try {
+ Annotation[] annotations = resourceClass.getAnnotations();
+ for(Annotation annotation : annotations) {
+ Class<? extends Annotation> anotationType = annotation.annotationType();
+ String annotationName = anotationType.getName();
+
+ // 2. find string property setters and getters for the lists
+ if("javax.xml.bind.annotation.XmlType".equals(annotationName)){
+ XmlType order = (XmlType)annotation;
+ String[] values = order.propOrder();
+ for(String value : values) {
+ String id = camelCaseToDashedString(value);
+ return id;
+ }
+ }
+ }
+ } catch(Exception exc) {
+ getLogger().warn("getPrimaryIdFromClass failed", exc);
+ }
+ return null;
+ }
+
+ public static String getSecondaryIdFromClass(Class<? extends AAIDatum> resourceClass){
+ getLogger().debug(resourceClass.getName());
+
+ try {
+ Annotation[] annotations = resourceClass.getAnnotations();
+ for(Annotation annotation : annotations) {
+ Class<? extends Annotation> anotationType = annotation.annotationType();
+ String annotationName = anotationType.getName();
+
+ // 2. find string property setters and getters for the lists
+ if("javax.xml.bind.annotation.XmlType".equals(annotationName)){
+ boolean primaryIdFound = false;
+ XmlType order = (XmlType)annotation;
+ String[] values = order.propOrder();
+ for(String value : values) {
+ String id = camelCaseToDashedString(value);
+ if(primaryIdFound) {
+ return id;
+ } else {
+ primaryIdFound = true;
+ }
+ }
+ }
+ }
+ } catch(Exception exc) {
+
+ }
+ return null;
+ }
+
+ public static Method getRelationshipListGetterMethodFromClassDefinition(Class resourceClass) {
+ Method getRelationshipListMethod = null;
+
+ try {
+ getRelationshipListMethod = resourceClass.getMethod("getRelationshipList");
+ } catch(Exception exc) {
+ getLogger().debug("Retrofiting relationship data: " + exc.getMessage());
+ }
+ return getRelationshipListMethod;
+ }
+
+ private static Logger getLogger() {
+ return LOG;
+ }
+
+
+ private static final String regex = "([A-Z][a-z,0-9]+)";
+ private static final String replacement = "-$1";
+
+ public static String camelCaseToDashedString(String propOrder) {
+ return propOrder.replaceAll(regex, replacement).toLowerCase();
+ }
+
+ public static HashMap<String,String> keyToHashMap(String key, SvcLogicContext ctx) {
+ if (key == null) {
+ return (null);
+ }
+
+ getLogger().debug("Converting key [" + key + "] to where clause");
+
+ if (key.startsWith("'") && key.endsWith("'")) {
+ key = key.substring(1, key.length() - 1);
+
+ getLogger().debug("Stripped outer single quotes - key is now [" + key + "]");
+ }
+
+ String[] keyTerms = key.split("\\s+");
+
+ StringBuffer whereBuff = new StringBuffer();
+ String term1 = null;
+ String op = null;
+ String term2 = null;
+ HashMap<String, String> results = new HashMap<>();
+
+ for (int i = 0; i < keyTerms.length; i++) {
+ if (term1 == null) {
+ if ("and".equalsIgnoreCase(keyTerms[i])
+ || "or".equalsIgnoreCase(keyTerms[i])) {
+ // Skip over ADD/OR
+ } else {
+ term1 = resolveTerm(keyTerms[i], ctx);
+ }
+ } else if (op == null) {
+ if ("==".equals(keyTerms[i])) {
+ op = "=";
+ } else {
+ op = keyTerms[i];
+ }
+ } else {
+ term2 = resolveTerm(keyTerms[i], ctx);
+ term2 = term2.trim().replace("'", "").replace("$", "").replace("'", "");
+ results.put(term1, term2);
+
+ term1 = null;
+ op = null;
+ term2 = null;
+ }
+ }
+
+ return (results);
+ }
+
+ private static String resolveTerm(String term, SvcLogicContext ctx) {
+ if (term == null) {
+ return (null);
+ }
+
+ getLogger().debug("resolveTerm: term is " + term);
+
+ if (term.startsWith("$") && (ctx != null)) {
+ // Resolve any index variables.
+
+ term = ("'" + resolveCtxVariable(term.substring(1), ctx) + "'");
+ if (term.contains(VERSION_PATTERN) && (ctx != null)) {
+ return term.replace(VERSION_PATTERN, AAIRequest.getSupportedAAIVersion());
+ }
+ return term;
+ } else if (term.contains(VERSION_PATTERN) && (ctx != null)) {
+ return term.replace(VERSION_PATTERN, AAIRequest.getSupportedAAIVersion());
+ } else if (term.startsWith("'") || term.startsWith("\"")) {
+ return (term);
+ } else {
+ return (term.replaceAll("-", "_"));
+
+ }
+ }
+
+ private static String resolveCtxVariable(String ctxVarName, SvcLogicContext ctx) {
+
+ if (ctxVarName.indexOf('[') == -1) {
+ // Ctx variable contains no arrays
+ return (ctx.getAttribute(ctxVarName));
+ }
+
+ // Resolve any array references
+ StringBuffer sbuff = new StringBuffer();
+ String[] ctxVarParts = ctxVarName.split("\\[");
+ sbuff.append(ctxVarParts[0]);
+ for (int i = 1; i < ctxVarParts.length; i++) {
+ if (ctxVarParts[i].startsWith("$")) {
+ int endBracketLoc = ctxVarParts[i].indexOf("]");
+ if (endBracketLoc == -1) {
+ // Missing end bracket ... give up parsing
+ getLogger().warn("Variable reference " + ctxVarName
+ + " seems to be missing a ']'");
+ return (ctx.getAttribute(ctxVarName));
+ }
+
+ String idxVarName = ctxVarParts[i].substring(1, endBracketLoc);
+ String remainder = ctxVarParts[i].substring(endBracketLoc);
+
+ sbuff.append("[");
+ sbuff.append(ctx.getAttribute(idxVarName));
+ sbuff.append(remainder);
+
+ } else {
+ // Index is not a variable reference
+ sbuff.append("[");
+ sbuff.append(ctxVarParts[i]);
+ }
+ }
+
+ return (ctx.getAttribute(sbuff.toString()));
+ }
+
+ public static void populateRelationshipDataFromPath(RelationshipList rl) throws URISyntaxException {
+ List<Relationship> list = rl.getRelationship();
+ if(list != null && !list.isEmpty()) {
+ for(Relationship relationship : list) {
+ if(relationship.getRelationshipData().isEmpty()){
+ String link = relationship.getRelatedLink();
+ URI uri = new URI(link);
+ link = uri.getPath();
+ HashMap<String,String> contributors = pathToHashMap(link);
+ for(String key : contributors.keySet()) {
+ RelationshipData rd = new RelationshipData();
+ rd.setRelationshipKey(key);
+ rd.setRelationshipValue(contributors.get(key));
+ relationship.getRelationshipData().add(rd);
+ }
+ }
+ }
+ }
+ }
+
+ protected static HashMap<String,String> pathToHashMap(String path) {
+ HashMap<String, String> nameValues = new HashMap<>();
+
+ String[] split = path.split("/");
+
+ LinkedList<String> list = new LinkedList<String>( Arrays.asList(split));
+ Iterator<String> it = list.iterator();
+
+ while(it.hasNext()) {
+ String tag = it.next();
+ if(!tag.isEmpty()) {
+ if(AAIRequest.getResourceNames().contains(tag)){
+ LOG.info(tag);
+ // get the class from tag
+ Class<? extends AAIDatum> clazz = AAIRequest.getClassFromResource(tag);
+ String fieldName = AAIServiceUtils.getPrimaryIdFromClass(clazz);
+
+ String value = it.next();
+ if(!StringUtils.isEmpty(value)){
+ nameValues.put(String.format("%s.%s", tag, fieldName), value);
+ switch(tag) {
+ case "cloud-region":
+ case "entitlement":
+ case "license":
+ case "route-target":
+ case "service-capability":
+ case "ctag-pool":
+ String secondaryFieldName = AAIServiceUtils.getSecondaryIdFromClass(clazz);
+ if(secondaryFieldName != null) {
+ value = it.next();
+ nameValues.put(String.format("%s.%s", tag, secondaryFieldName), value);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ }
+ }
+ return nameValues;
+ }
+
+ public static String getPathForResource(String resource, String key, SvcLogicContext ctx ) throws MalformedURLException{
+ HashMap<String, String> nameValues = AAIServiceUtils.keyToHashMap(key, ctx);
+ AAIRequest request = AAIRequest.createRequest(resource, nameValues);
+
+ for(String name : nameValues.keySet()) {
+ request.addRequestProperty(name, nameValues.get(name));
+ }
+ return request.getRequestPath();
+ }
+
+ public static boolean isValidFormat(String resource, Map<String, String> nameValues) {
+
+ switch(resource){
+ case "custom-query":
+ case "formatted-query":
+ case "generic-query":
+ case "nodes-query":
+ case "linterface":
+ case "l2-bridge-sbg":
+ case "l2-bridge-bgf":
+ case "echo":
+ case "test":
+ return true;
+ }
+ if(resource.contains(":")) {
+ resource = resource.substring(0, resource.indexOf(":"));
+ }
+
+ Set<String> keys = nameValues.keySet();
+ for(String key : keys) {
+ if(!key.contains(".")) {
+ if("depth".equals(key) || "related-to".equals(key) || "related_to".equals(key) || "related-link".equals(key) || "related_link".equals(key) || "selflink".equals(key) || "resource_path".equals(key))
+ continue;
+ else {
+ getLogger().warn(String.format("key '%s' is incompatible with resource type '%s'", key, resource));
+ }
+ }
+ }
+ return true;
+ }
+
+ public static boolean containsResource(String resource, HashMap<String, String> nameValues) {
+ if(resource.contains(":")) {
+ return true;
+ }
+
+ switch(resource){
+ case "custom-query":
+ case "formatted-query":
+ case "generic-query":
+ case "nodes-query":
+ case "linterface":
+ case "l2-bridge-sbg":
+ case "l2-bridge-bgf":
+ case "echo":
+ case "test":
+ return true;
+
+ default:
+ if(nameValues.containsKey("selflink")) {
+ return true;
+ }
+ }
+
+ Set<String> tags = new HashSet<>();
+
+ for(String key : nameValues.keySet()) {
+ key = key.replace("_", "-");
+ if(key.contains(".")) {
+ String[] split = key.split("\\.");
+ tags.add(split[0]);
+ } else {
+ tags.add(key);
+ }
+ }
+ return tags.contains(resource);
+ }
+}
diff --git a/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/AAITrinityService.java b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/AAITrinityService.java
new file mode 100755
index 000000000..d1abda13d
--- /dev/null
+++ b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/AAITrinityService.java
@@ -0,0 +1,39 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+/**
+ * @author Rich Tabedzki
+ *
+ */
+package org.onap.ccsdk.sli.adaptors.aai;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class AAITrinityService extends AAIService {
+
+ private static final Logger LOG = LoggerFactory.getLogger(AAITrinityService.class);
+
+ public AAITrinityService(UtilsProvider configuration) {
+ super(configuration);
+ LOG.info("Entered AAITrinityService.ctor");
+ }
+
+}
diff --git a/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/CustomQueryRequest.java b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/CustomQueryRequest.java
new file mode 100755
index 000000000..a99e6d5ef
--- /dev/null
+++ b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/CustomQueryRequest.java
@@ -0,0 +1,138 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * Modifications Copyright (C) 2018 IBM.
+ * Modifications Copyright (C) 2019 IBM.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+/**
+ * @author Rich Tabedzki
+ *
+ */
+package org.onap.ccsdk.sli.adaptors.aai;
+
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Properties;
+
+import org.onap.ccsdk.sli.adaptors.aai.data.AAIDatum;
+import org.onap.ccsdk.sli.adaptors.aai.query.FormattedQueryRequestData;
+import org.onap.ccsdk.sli.adaptors.aai.query.FormattedQueryResultList;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+
+public class CustomQueryRequest extends AAIRequest {
+
+ public static final String GENERIC_SEARCH_PATH_CONST = "org.onap.ccsdk.sli.adaptors.aai.query.generic";
+
+ private final String generic_search_path;
+
+ public static final String FORMAT = "format";
+
+
+ public CustomQueryRequest() {
+ String tmpGenericSearchPath = configProperties.getProperty(GENERIC_SEARCH_PATH_CONST);
+ tmpGenericSearchPath = tmpGenericSearchPath.split("search")[0];
+ generic_search_path = tmpGenericSearchPath +"query";
+ }
+
+
+ @Override
+ public URL getRequestUrl(String method, String resourceVersion) throws UnsupportedEncodingException, MalformedURLException {
+
+ String requestUrl = targetUri+generic_search_path;
+
+ requestUrl = processPathData(requestUrl, requestProperties);
+
+ String formatQuery = requestProperties.getProperty(FORMAT);
+
+ if(formatQuery != null) {
+ requestUrl = requestUrl +"?format="+formatQuery;
+ }
+ URL httpReqUrl = new URL(requestUrl);
+
+ aaiService.LOGwriteFirstTrace(method, httpReqUrl.toString());
+
+ return httpReqUrl;
+ }
+
+ @Override
+ public URL getRequestQueryUrl(String method) throws UnsupportedEncodingException, MalformedURLException {
+ return getRequestUrl(method, null);
+ }
+
+
+ @Override
+ public String toJSONString() {
+ ObjectMapper mapper = getObjectMapper();
+ FormattedQueryRequestData tenant = (FormattedQueryRequestData)requestDatum;
+ String jsonText = null;
+ try {
+ jsonText = mapper.writeValueAsString(tenant);
+ } catch (JsonProcessingException exc) {
+ handleException(this, exc);
+ return null;
+ }
+ return jsonText;
+ }
+
+
+ @Override
+ public String[] getArgsList() {
+ String[] args = {FORMAT};
+ return args;
+ }
+
+
+ @Override
+ public Class<? extends AAIDatum> getModelClass() {
+ return FormattedQueryRequestData.class;
+ }
+
+
+ public static String processPathData(String requestUrl, Properties requestProperties) throws UnsupportedEncodingException {
+
+ String key = FORMAT;
+
+ String encodedVnf = encodeQuery(requestProperties.getProperty(key));
+ requestUrl = requestUrl.replace("{identifier}", encodedVnf) ;
+ aaiService.LOGwriteDateTrace("identifier", requestProperties.getProperty(key));
+
+ return requestUrl;
+ }
+
+ @Override
+ public AAIDatum jsonStringToObject(String jsonData) throws IOException {
+ if(jsonData == null) {
+ return null;
+ }
+
+ AAIDatum response = null;
+ ObjectMapper mapper = getObjectMapper();
+ response = mapper.readValue(jsonData, FormattedQueryResultList.class);
+ return response;
+ }
+
+ protected boolean expectsDataFromPUTRequest() {
+ return true;
+ }
+}
diff --git a/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/EchoRequest.java b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/EchoRequest.java
new file mode 100755
index 000000000..8e6af0100
--- /dev/null
+++ b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/EchoRequest.java
@@ -0,0 +1,97 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * Modifications Copyright (C) 2018 IBM.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+/**
+ * @author Rich Tabedzki
+ *
+ */
+package org.onap.ccsdk.sli.adaptors.aai;
+
+import java.io.UnsupportedEncodingException;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import org.onap.ccsdk.sli.adaptors.aai.data.AAIDatum;
+import org.onap.ccsdk.sli.adaptors.aai.data.EchoResponse;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+public class EchoRequest extends AAIRequest {
+
+
+
+ private final String echoPath;
+
+ public EchoRequest() {
+ echoPath = "/aai/util/echo";
+ }
+
+
+ @Override
+ public URL getRequestUrl(String method, String resourceVersion) throws UnsupportedEncodingException, MalformedURLException {
+
+ String requestUrl = targetUri+echoPath;
+
+ if(resourceVersion != null) {
+ requestUrl = requestUrl +"?resource-version="+resourceVersion;
+ }
+ URL httpReqUrl = new URL(requestUrl);
+
+ aaiService.LOGwriteFirstTrace(method, httpReqUrl.toString());
+
+ return httpReqUrl;
+ }
+
+ @Override
+ public URL getRequestQueryUrl(String method) throws UnsupportedEncodingException, MalformedURLException {
+ return getRequestUrl(method, null);
+ }
+
+
+ @Override
+ public String toJSONString() {
+ ObjectMapper mapper = getObjectMapper();
+ EchoResponse tenant = (EchoResponse)requestDatum;
+ String jsonText = null;
+ try {
+ jsonText = mapper.writeValueAsString(tenant);
+ } catch (JsonProcessingException exc) {
+ handleException(this, exc);
+ return null;
+ }
+ return jsonText;
+ }
+
+
+ @Override
+ public String[] getArgsList() {
+ String[] args = {};
+ return args;
+ }
+
+
+ @Override
+ public Class<? extends AAIDatum> getModelClass() {
+ return EchoResponse.class;
+ }
+
+}
diff --git a/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/GenericQueryRequest.java b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/GenericQueryRequest.java
new file mode 100755
index 000000000..29fe24ef2
--- /dev/null
+++ b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/GenericQueryRequest.java
@@ -0,0 +1,128 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Modifications Copyright (C) 2018 IBM.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+/**
+ * @author Rich Tabedzki
+ *
+ */
+package org.onap.ccsdk.sli.adaptors.aai;
+
+import java.io.UnsupportedEncodingException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Properties;
+
+import org.onap.ccsdk.sli.adaptors.aai.data.AAIDatum;
+import org.onap.aai.inventory.v21.ResultData;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+public class GenericQueryRequest extends AAIRequest {
+
+ public static final String GENERIC_SEARCH_PATH = "org.onap.ccsdk.sli.adaptors.aai.query.generic";
+
+ private final String generic_search_path;
+
+ public static final String START_NODE_TYPE = "start-node-type";
+ public static final String IDENTIFIER = "identifier";
+ public static final String VALUE = "value";
+
+
+ public GenericQueryRequest() {
+ generic_search_path = configProperties.getProperty(GENERIC_SEARCH_PATH);
+ }
+
+ @Override
+ public URL getRequestUrl(String method, String resourceVersion) throws UnsupportedEncodingException, MalformedURLException {
+
+ String request_url = targetUri+generic_search_path;
+
+ request_url = processPathData(request_url, requestProperties);
+
+ if(resourceVersion != null) {
+ request_url = request_url +"?resource-version="+resourceVersion;
+ }
+ URL http_req_url = new URL(request_url);
+
+ aaiService.LOGwriteFirstTrace(method, http_req_url.toString());
+
+ return http_req_url;
+ }
+
+ @Override
+ public URL getRequestQueryUrl(String method) throws UnsupportedEncodingException, MalformedURLException {
+ return getRequestUrl(method, null);
+ }
+
+
+ @Override
+ public String toJSONString() {
+ ObjectMapper mapper = getObjectMapper();
+ ResultData tenant = (ResultData)requestDatum;
+ String json_text = null;
+ try {
+ json_text = mapper.writeValueAsString(tenant);
+ } catch (JsonProcessingException exc) {
+ handleException(this, exc);
+ return null;
+ }
+ return json_text;
+ }
+
+
+ @Override
+ public String[] getArgsList() {
+ String[] args = {START_NODE_TYPE, IDENTIFIER, VALUE};
+ return args;
+ }
+
+
+ @Override
+ public Class<? extends AAIDatum> getModelClass() {
+ return ResultData.class;
+ }
+
+
+ public static String processPathData(String request_url, Properties requestProperties) throws UnsupportedEncodingException {
+
+ String key = IDENTIFIER;
+
+ String encoded_vnf = encodeQuery(requestProperties.getProperty(key));
+ request_url = request_url.replace("{identifier}", encoded_vnf) ;
+ aaiService.LOGwriteDateTrace(IDENTIFIER, requestProperties.getProperty(key));
+
+ key = VALUE;
+
+ encoded_vnf = encodeQuery(requestProperties.getProperty(key));
+ request_url = request_url.replace("{value}", encoded_vnf) ;
+ aaiService.LOGwriteDateTrace(VALUE, requestProperties.getProperty(key));
+
+ key = START_NODE_TYPE;
+
+ encoded_vnf = encodeQuery(requestProperties.getProperty(key));
+ request_url = request_url.replace("{start-node-type}", encoded_vnf) ;
+ aaiService.LOGwriteDateTrace(START_NODE_TYPE, requestProperties.getProperty(key));
+
+ return request_url;
+ }
+}
diff --git a/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/GenericRequest.java b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/GenericRequest.java
new file mode 100755
index 000000000..604dd0e5c
--- /dev/null
+++ b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/GenericRequest.java
@@ -0,0 +1,265 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Modifications Copyright (C) 2018 IBM.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+ /**
+ * @author Rich Tabedzki
+ *
+ */
+package org.onap.ccsdk.sli.adaptors.aai;
+
+import java.io.UnsupportedEncodingException;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.net.MalformedURLException;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+
+import org.onap.ccsdk.sli.adaptors.aai.data.AAIDatum;
+import org.onap.aai.inventory.v21.L3Network;
+import org.onap.aai.inventory.v21.L3Networks;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.common.base.Joiner;
+
+public class GenericRequest extends AAIRequest {
+
+
+ protected Class<? extends AAIDatum> model;
+
+ public GenericRequest(Class<? extends AAIDatum> clazz) {
+ model = clazz;
+ }
+
+ @Override
+ public String updatePathDataValues(Object resourceVersion) throws UnsupportedEncodingException, MalformedURLException {
+
+ String originalPath = null;
+ String pathSubstitute = null;
+ String resourceName = null;
+
+ Annotation[] annotations = model.getAnnotations();
+ for(Annotation annotation : annotations) {
+ Class<? extends Annotation> anotationType = annotation.annotationType();
+ String annotationName = anotationType.getName();
+ if("javax.xml.bind.annotation.XmlRootElement".equals(annotationName)){
+ XmlRootElement order = (XmlRootElement)annotation;
+ resourceName = order.name();
+ }
+ }
+
+ String request_url = getRequestPath(resourceName);
+
+ Map<String, String> queryParams = new HashMap<> ();
+ if(resourceVersion != null) {
+ queryParams.put("resource-version", resourceVersion.toString());
+ }
+
+ Set<String> uniqueResources = extractUniqueResourceSetFromKeys(requestProperties.stringPropertyNames());
+
+ String[] keys = requestProperties.keySet().toArray(new String[0]);
+ for(String key : keys) {
+ switch(key) {
+ case "cloud-region.cloud-region-id":
+ case "entitlement.resource-uuid":
+ case "license.resource-uuid":
+ case "route-target.route-target-role":
+ case "service-capability.vnf-type":
+ case "ctag-pool.availability-zone-name":
+ continue;
+ }
+
+ String value = requestProperties.getProperty(key);
+ if(key.contains(".")) {
+ String[] splitKey = key.split("\\.");
+ if("cloud-region".equals(splitKey[0])){
+ String cloudRegionId = requestProperties.getProperty("cloud-region.cloud-region-id");
+ aaiService.LOGwriteDateTrace("cloud-region-id", cloudRegionId);
+ String token = String.format("%s/{%s}/{cloud-region-id}", splitKey[0], splitKey[1] );
+ String encoded_owner = encodeQuery(value);
+ String encoded_region = encodeQuery(cloudRegionId);
+ request_url = request_url.replace(token, String.format("%s/%s/%s", splitKey[0], encoded_owner, encoded_region));
+ } else if("entitlement".equals(splitKey[0])){
+ String cloudRegionId = requestProperties.getProperty("entitlement.resource-uuid");
+ aaiService.LOGwriteDateTrace("resource-uuid", cloudRegionId);
+ String token = String.format("%s/{%s}/{resource-uuid}", splitKey[0], splitKey[1] );
+ String encoded_owner = encodeQuery(value);
+ String encoded_region = encodeQuery(cloudRegionId);
+ request_url = request_url.replace(token, String.format("%s/%s/%s", splitKey[0], encoded_owner, encoded_region));
+ } else if("license".equals(splitKey[0])){
+ String cloudRegionId = requestProperties.getProperty("license.resource-uuid");
+ aaiService.LOGwriteDateTrace("resource-uuid", cloudRegionId);
+ String token = String.format("%s/{%s}/{resource-uuid}", splitKey[0], splitKey[1] );
+ String encoded_owner = encodeQuery(value);
+ String encoded_region = encodeQuery(cloudRegionId);
+ request_url = request_url.replace(token, String.format("%s/%s/%s", splitKey[0], encoded_owner, encoded_region));
+ } else if("route-target".equals(splitKey[0])){
+ String cloudRegionId = requestProperties.getProperty("route-target.route-target-role");
+ aaiService.LOGwriteDateTrace("route-target-role", cloudRegionId);
+ String token = String.format("%s/{%s}/{route-target-role}", splitKey[0], splitKey[1] );
+ String encoded_owner = encodeQuery(value);
+ String encoded_region = encodeQuery(cloudRegionId);
+ request_url = request_url.replace(token, String.format("%s/%s/%s", splitKey[0], encoded_owner, encoded_region));
+ } else if("service-capability".equals(splitKey[0])){
+ String vnfType = requestProperties.getProperty("service-capability.vnf-type");
+ aaiService.LOGwriteDateTrace("vnf-type", vnfType);
+ String token = String.format("%s/{%s}/{vnf-type}", splitKey[0], splitKey[1] );
+ String encoded_service_type = encodeQuery(value);
+ String encoded_vnf_type = encodeQuery(vnfType);
+ if("service-capability".equals(resourceName)) {
+ request_url = request_url.replace(token, String.format("%s/%s/%s", splitKey[0], encoded_service_type, encoded_vnf_type));
+ } else if("service-capabilities".equals(resourceName)) {
+ queryParams.put("service-type", encoded_service_type);
+ queryParams.put("vnf-type", encoded_vnf_type);
+ }
+ } else if("ctag-pool".equals(splitKey[0])){
+ String cloudRegionId = requestProperties.getProperty("ctag-pool.availability-zone-name");
+ aaiService.LOGwriteDateTrace("availability-zone-name", cloudRegionId);
+ String token = String.format("%s/{%s}/{availability-zone-name}", splitKey[0], splitKey[1] );
+ String encoded_owner = encodeQuery(value);
+ String encoded_region = encodeQuery(cloudRegionId);
+ request_url = request_url.replace(token, String.format("%s/%s/%s", splitKey[0], encoded_owner, encoded_region));
+ } else {
+ Class<? extends AAIDatum> clazz = getClassFromResource(splitKey[0]);
+
+ if(clazz != null) {
+ if(clazz == this.model) {
+ Field[] fields = this.model.getDeclaredFields();
+ Field field = fields[0];
+ String fieldName = field.getName();
+ XmlElement annotation = field.getAnnotation(XmlElement.class);
+ String primaryId = null;
+ if(annotation != null) {
+ primaryId = annotation.name();
+ if("##default".equals(primaryId)) {
+ primaryId = fieldName;
+ }
+ } else {
+ primaryId = fieldName;
+ }
+
+ String token = String.format("%s/{%s}", splitKey[0], primaryId);
+
+ if(splitKey[1].equals(primaryId)) {
+ String encoded_vnf = encodeQuery(value);
+ request_url = request_url.replace(token, String.format("%s/%s", splitKey[0], encoded_vnf));
+ } else {
+ queryParams.put(splitKey[1], encodeQuery(value));
+ originalPath = token;
+ pathSubstitute = String.format("%s", splitKey[0]);
+ }
+ } else if(L3Networks.class == this.model) {
+ Field[] fields = L3Network.class.getDeclaredFields();
+ Field field = fields[0];
+ String fieldName = field.getName();
+ XmlElement annotation = field.getAnnotation(XmlElement.class);
+ String primaryId = annotation.name();
+ if("##default".equals(primaryId)) {
+ primaryId = fieldName;
+ }
+
+ String token = String.format("%s/{%s}", splitKey[0], primaryId);
+ originalPath = token;
+ pathSubstitute = String.format("");
+
+ queryParams.put(splitKey[1], encodeQuery(value));
+ } else {
+ String encoded_vnf = encodeQuery(value);
+ if(!resourceName.equals(splitKey[0]) && resourceName.contains(splitKey[0])) {
+ queryParams.put(splitKey[1], encoded_vnf);
+ } else {
+ String token = String.format("%s/{%s}", splitKey[0], splitKey[1]);
+ request_url = request_url.replace(token, String.format("%s/%s", splitKey[0], encoded_vnf));
+ }
+ }
+ }
+
+ }
+ aaiService.LOGwriteDateTrace(splitKey[1], value);
+ }
+ }
+
+ if(originalPath != null && pathSubstitute != null)
+ request_url = request_url.replace(originalPath, pathSubstitute);
+
+ if(!queryParams.isEmpty()) {
+ Joiner.MapJoiner mapJoiner = Joiner.on("&").withKeyValueSeparator("=");
+ String queryString = mapJoiner.join(queryParams);
+ request_url = String.format("%s?%s", request_url, queryString);
+ }
+
+ return request_url;
+ }
+
+ @Override
+ public URL getRequestQueryUrl(String method) throws UnsupportedEncodingException, MalformedURLException, URISyntaxException {
+ return this.getRequestUrl(method, null);
+ }
+
+
+ @Override
+ public String toJSONString() {
+ ObjectMapper mapper = getObjectMapper();
+
+ String json_text = null;
+ try {
+ json_text = mapper.writeValueAsString(requestDatum);
+ } catch (JsonProcessingException exc) {
+ handleException(this, exc);
+ return null;
+ }
+ return json_text;
+ }
+
+ @Override
+ public String[] getArgsList() {
+ String[] args = {};
+ return args;
+ }
+
+ @Override
+ public Class<? extends AAIDatum> getModelClass() {
+ return model;
+ }
+
+ public void processRequestPathValues(Map<String, String> nameValues) {
+ // identify unique resources
+ Set<String> uniqueResources = AAIRequest.extractUniqueResourceSetFromKeys(nameValues.keySet());
+
+ String[] arguments = nameValues.keySet().toArray(new String[0]);
+ for(String name : arguments) {
+ String tmpName = name.replaceAll("-", "_");
+ String value = nameValues.get(tmpName);
+ if(value != null && !value.isEmpty()) {
+ value = value.trim().replace("'", "").replace("$", "").replace("'", "");
+ tmpName = name.replaceAll("_", "-");
+ this.addRequestProperty(tmpName, value);
+ }
+ }
+ }
+}
diff --git a/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/HttpMethod.java b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/HttpMethod.java
new file mode 100755
index 000000000..8f7abe601
--- /dev/null
+++ b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/HttpMethod.java
@@ -0,0 +1,13 @@
+package org.onap.ccsdk.sli.adaptors.aai;
+/**
+ * @author Rich Tabedzki
+ *
+ */
+public interface HttpMethod {
+ public static final String GET = "GET";
+ public static final String HEAD = "HEAD";
+ public static final String PATCH = "PATCH";
+ public static final String POST = "POST";
+ public static final String PUT = "PUT";
+ public static final String DELETE = "DELETE";
+}
diff --git a/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/NodesQueryRequest.java b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/NodesQueryRequest.java
new file mode 100755
index 000000000..c40d96cad
--- /dev/null
+++ b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/NodesQueryRequest.java
@@ -0,0 +1,129 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Modifications Copyright (C) 2018 IBM.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+/**
+ * @author Rich Tabedzki
+ *
+ */
+package org.onap.ccsdk.sli.adaptors.aai;
+
+import java.io.UnsupportedEncodingException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Properties;
+
+import org.onap.ccsdk.sli.adaptors.aai.data.AAIDatum;
+import org.onap.aai.inventory.v21.SearchResults;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+public class NodesQueryRequest extends AAIRequest {
+
+ public static final String NODES_SEARCH_PATH = "org.onap.ccsdk.sli.adaptors.aai.query.nodes";
+
+ private final String nodes_search_path;
+
+ public static final String NODE_TYPE = "node-type";
+ public static final String ENTITY_IDENTIFIER = "entity-identifier";
+ public static final String ENTITY_VALUE = "entity-value";
+
+
+ public NodesQueryRequest() {
+ nodes_search_path = configProperties.getProperty(NODES_SEARCH_PATH);
+ }
+
+
+ @Override
+ public URL getRequestUrl(String method, String resourceVersion) throws UnsupportedEncodingException, MalformedURLException {
+
+ String request_url = targetUri+nodes_search_path;
+
+ request_url = processPathData(request_url, requestProperties);
+
+ if(resourceVersion != null) {
+ request_url = request_url +"?resource-version="+resourceVersion;
+ }
+ URL http_req_url = new URL(request_url);
+
+ aaiService.LOGwriteFirstTrace(method, http_req_url.toString());
+
+ return http_req_url;
+ }
+
+ @Override
+ public URL getRequestQueryUrl(String method) throws UnsupportedEncodingException, MalformedURLException {
+ return getRequestUrl(method, null);
+ }
+
+
+ @Override
+ public String toJSONString() {
+ ObjectMapper mapper = getObjectMapper();
+ SearchResults tenant = (SearchResults)requestDatum;
+ String json_text = null;
+ try {
+ json_text = mapper.writeValueAsString(tenant);
+ } catch (JsonProcessingException exc) {
+ handleException(this, exc);
+ return null;
+ }
+ return json_text;
+ }
+
+
+ @Override
+ public String[] getArgsList() {
+ String[] args = {NODE_TYPE, ENTITY_IDENTIFIER, ENTITY_VALUE};
+ return args;
+ }
+
+
+ @Override
+ public Class<? extends AAIDatum> getModelClass() {
+ return SearchResults.class;
+ }
+
+
+ public static String processPathData(String request_url, Properties requestProperties) throws UnsupportedEncodingException {
+
+ String key = ENTITY_IDENTIFIER;
+
+ String encoded_vnf = encodeQuery(requestProperties.getProperty(key));
+ request_url = request_url.replace("{entity-identifier}", encoded_vnf) ;
+ aaiService.LOGwriteDateTrace(ENTITY_IDENTIFIER, requestProperties.getProperty(key));
+
+ key = ENTITY_VALUE;
+
+ encoded_vnf = encodeQuery(requestProperties.getProperty(key));
+ request_url = request_url.replace("{entity-name}", encoded_vnf) ;
+ aaiService.LOGwriteDateTrace("entity-name", requestProperties.getProperty(key));
+
+ key = NODE_TYPE;
+
+ encoded_vnf = encodeQuery(requestProperties.getProperty(key));
+ request_url = request_url.replace("{node-type}", encoded_vnf) ;
+ aaiService.LOGwriteDateTrace(NODE_TYPE, requestProperties.getProperty(key));
+
+ return request_url;
+ }
+}
diff --git a/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/PathRequest.java b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/PathRequest.java
new file mode 100755
index 000000000..68aff1f95
--- /dev/null
+++ b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/PathRequest.java
@@ -0,0 +1,91 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+/**
+ * @author Rich Tabedzki
+ *
+ */
+package org.onap.ccsdk.sli.adaptors.aai;
+
+import java.io.UnsupportedEncodingException;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import org.onap.ccsdk.sli.adaptors.aai.data.AAIDatum;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+public class PathRequest extends AAIRequest {
+
+ private final Class<? extends AAIDatum> classType;
+
+ public static final String RESOURCE_PATH = "resource-path";
+
+ public PathRequest(Class<?> type) {
+ classType = (Class<? extends AAIDatum>)type;
+ }
+
+
+ @Override
+ public URL getRequestUrl(String method, String resourceVersion) throws UnsupportedEncodingException, MalformedURLException {
+
+ String request_url = targetUri + "{resource-path}";
+
+ String encoded_vnf = requestProperties.getProperty(RESOURCE_PATH);
+ request_url = request_url.replace("{resource-path}", encoded_vnf) ;
+
+ URL http_req_url = new URL(request_url);
+
+ aaiService.LOGwriteFirstTrace(method, http_req_url.toString());
+
+ return http_req_url;
+ }
+
+ @Override
+ public URL getRequestQueryUrl(String method) throws UnsupportedEncodingException, MalformedURLException {
+ return this.getRequestUrl(method, null);
+ }
+
+
+ @Override
+ public String toJSONString() {
+ ObjectMapper mapper = getObjectMapper();
+ String json_text = null;
+ try {
+ json_text = mapper.writeValueAsString(classType);
+ } catch (JsonProcessingException exc) {
+ handleException(this, exc);
+ return null;
+ }
+ return json_text;
+ }
+
+ @Override
+ public String[] getArgsList() {
+ String[] args = {RESOURCE_PATH};
+ return args;
+ }
+
+ @Override
+ public Class<? extends AAIDatum> getModelClass() {
+ return classType;
+ }
+}
diff --git a/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/RelationshipListRequest.java b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/RelationshipListRequest.java
new file mode 100755
index 000000000..751fe5d59
--- /dev/null
+++ b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/RelationshipListRequest.java
@@ -0,0 +1,65 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+/**
+ * @author Rich Tabedzki
+ *
+ */
+package org.onap.ccsdk.sli.adaptors.aai;
+
+import java.io.UnsupportedEncodingException;
+import java.net.MalformedURLException;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.List;
+
+import org.apache.http.NameValuePair;
+import org.apache.http.client.utils.URIBuilder;
+import org.apache.http.message.BasicNameValuePair;
+import org.onap.aai.inventory.v21.RelationshipList;
+
+public class RelationshipListRequest extends GenericRequest {
+
+ public static final String SELFLINK = "selflink";
+
+ public RelationshipListRequest(AAIRequest masterRequest) {
+ super(RelationshipList.class);
+ this.addMasterRequest(masterRequest);
+ }
+
+
+ @Override
+ public URL getRequestUrl(String method, String resourceVersion) throws UnsupportedEncodingException, MalformedURLException, URISyntaxException {
+
+ URL url = super.getRequestUrl(method, null);
+ URIBuilder builder = new URIBuilder(url.toURI());
+ String newPath = builder.getPath() + "/relationship-list";
+ builder.setPath(newPath);
+ if(resourceVersion != null) {
+ List<NameValuePair> queryList = builder.getQueryParams();
+ NameValuePair nvp = new BasicNameValuePair("resourceVersion", resourceVersion);
+ queryList.add(nvp);
+ }
+
+ aaiService.LOGwriteFirstTrace(method, builder.toString());
+
+ return builder.build().toURL();
+ }
+}
diff --git a/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/RelationshipRequest.java b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/RelationshipRequest.java
new file mode 100755
index 000000000..fa71d6f22
--- /dev/null
+++ b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/RelationshipRequest.java
@@ -0,0 +1,67 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * Modifications Copyright (C) 2018 IBM.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+/**
+ * @author Rich Tabedzki
+ *
+ */
+package org.onap.ccsdk.sli.adaptors.aai;
+
+import java.io.UnsupportedEncodingException;
+import java.net.MalformedURLException;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.List;
+
+import org.apache.http.NameValuePair;
+import org.apache.http.client.utils.URIBuilder;
+import org.apache.http.message.BasicNameValuePair;
+
+import org.onap.aai.inventory.v21.Relationship;
+
+
+public class RelationshipRequest extends GenericRequest {
+
+ public RelationshipRequest(AAIRequest masterRequest) {
+ super(Relationship.class);
+ this.addMasterRequest(masterRequest);
+ }
+
+
+ @Override
+ public URL getRequestUrl(String method, String resourceVersion) throws UnsupportedEncodingException, MalformedURLException, URISyntaxException {
+
+
+ URL url = super.getRequestUrl(method, null);
+ URIBuilder builder = new URIBuilder(url.toURI());
+ String newPath = builder.getPath() + "/relationship-list/relationship";
+ builder.setPath(newPath);
+ if(resourceVersion != null) {
+ List<NameValuePair> queryList = builder.getQueryParams();
+ NameValuePair nvp = new BasicNameValuePair("resourceVersion", resourceVersion);
+ queryList.add(nvp);
+ }
+
+ aaiService.LOGwriteFirstTrace(method, builder.toString());
+
+ return builder.build().toURL();
+ }
+}
diff --git a/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/SelfLinkRequest.java b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/SelfLinkRequest.java
new file mode 100755
index 000000000..0094b45fd
--- /dev/null
+++ b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/SelfLinkRequest.java
@@ -0,0 +1,109 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+/**
+ * @author Rich Tabedzki
+ *
+ */
+package org.onap.ccsdk.sli.adaptors.aai;
+
+import java.io.UnsupportedEncodingException;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URL;
+
+import org.onap.ccsdk.sli.adaptors.aai.data.AAIDatum;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.google.common.base.Joiner;
+
+public class SelfLinkRequest extends AAIRequest {
+
+ private final Class<? extends AAIDatum> classType;
+
+ public static final String SELFLINK = "selflink";
+
+ public SelfLinkRequest(Class<?> type) {
+ classType = (Class<? extends AAIDatum>)type;
+ }
+
+
+ @Override
+ public URL getRequestUrl(String method, String resourceVersion) throws UnsupportedEncodingException, MalformedURLException {
+
+ String request_url = null;
+
+ request_url = requestProperties.getProperty(SELFLINK);
+ try {
+ URI uri = new URI(request_url);
+ if(uri.getHost() == null) {
+ request_url = targetUri + request_url;
+ }
+ } catch(Exception exc) {
+ LOG.error("SelfLinkRequest.getRequestUrl", exc);
+ }
+ String query = null;
+
+ if(request_url.contains("?")) {
+ query = request_url.substring(request_url.indexOf("?"));
+ Joiner.MapJoiner mapJoiner = Joiner.on(",").withKeyValueSeparator("=");
+// String queryString = mapJoiner.join(query);
+ } else {
+ request_url = request_url + "?depth=1";
+ }
+
+ URL http_req_url = new URL(request_url);
+
+ aaiService.LOGwriteFirstTrace(method, http_req_url.toString());
+
+ return http_req_url;
+ }
+
+ @Override
+ public URL getRequestQueryUrl(String method) throws UnsupportedEncodingException, MalformedURLException {
+ return this.getRequestUrl(method, null);
+ }
+
+
+ @Override
+ public String toJSONString() {
+ ObjectMapper mapper = getObjectMapper();
+ String json_text = null;
+ try {
+ json_text = mapper.writeValueAsString(classType);
+ } catch (JsonProcessingException exc) {
+ handleException(this, exc);
+ return null;
+ }
+ return json_text;
+ }
+
+ @Override
+ public String[] getArgsList() {
+ String[] args = {SELFLINK};
+ return args;
+ }
+
+ @Override
+ public Class<? extends AAIDatum> getModelClass() {
+ return classType;
+ }
+}
diff --git a/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/UpdateRequest.java b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/UpdateRequest.java
new file mode 100755
index 000000000..8046ca5e3
--- /dev/null
+++ b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/UpdateRequest.java
@@ -0,0 +1,152 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * Modifications Copyright (C) 2018 IBM.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+/**
+ * The UpdateRequest class provides processing related to update transaction.
+ * @author richtabedzki
+ */
+
+package org.onap.ccsdk.sli.adaptors.aai;
+
+import java.io.UnsupportedEncodingException;
+import java.net.MalformedURLException;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import org.onap.ccsdk.sli.adaptors.aai.data.AAIDatum;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+public class UpdateRequest extends AAIRequest {
+
+ private AAIRequest request;
+ private Map<String, String> params;
+
+ public UpdateRequest(AAIRequest request, Map<String, String> parms) {
+ this.request = request;
+ this.params = parms;
+ }
+
+ @Override
+ public URL getRequestUrl(String method, String resourceVersion)
+ throws UnsupportedEncodingException, MalformedURLException, URISyntaxException {
+ return request.getRequestUrl(method, resourceVersion);
+ }
+
+ @Override
+ public URL getRequestQueryUrl(String method) throws UnsupportedEncodingException, MalformedURLException, URISyntaxException {
+ return request.getRequestQueryUrl(method);
+ }
+
+ @Override
+ public String toJSONString() {
+ updateArrayEntries(params);
+ ObjectMapper mapper = AAIService.getObjectMapper();
+ String json = null;
+
+ try {
+ json = mapper.writeValueAsString(params);
+ } catch (JsonProcessingException e) {
+ LOG.error("Could not convert parameters of " + request.getRequestObject().getClass().getName(), e);
+ }
+
+ return json;
+ }
+
+ /**
+ *
+ * Update array entries.
+ * The method converts indexed data entries to an array of values
+ *
+ * @param data Map containing String:String values representing input data
+ */
+ private void updateArrayEntries( Map<String, String> data) {
+ Set<String> set = data.keySet()
+ .stream()
+ .filter(s -> s.endsWith("_length"))
+ .collect(Collectors.toSet());
+
+ for(String lenghtKey : set) {
+ String key = lenghtKey.replace("_length", "");
+// String index = data.get(lenghtKey);
+ List<String> array = new ArrayList<>();
+
+ Set<String> subset = data.keySet()
+ .stream()
+ .filter(s -> s.startsWith(String.format("%s[",key)))
+ .collect(Collectors.toSet());
+ for(String subKey : subset) {
+ String subValue = data.get(subKey);
+ array.add(subValue);
+ LOG.trace("{} : {} ", subKey, subValue);
+ }
+ data.put(key, array.toString());
+ data.remove(lenghtKey);
+ for(String subKey : subset) {
+ data.remove(subKey);
+ }
+ }
+ }
+
+ @Override
+ public String[] getArgsList() {
+ return request.getArgsList();
+ }
+
+ @Override
+ public Class<? extends AAIDatum> getModelClass() {
+ return request.getModelClass();
+ }
+
+ @Override
+ public void addRequestProperty(String key, String value) {
+ request.requestProperties.put(key, value);
+ }
+
+ public static String processPathData(String requestUrl, Properties requestProperties) {
+
+// if(request != null) {
+// Class<?> clazz = request.getClass();
+// Method function = null;
+// try {
+// function = clazz.getMethod("processPathData", request_url.getClass(), requestProperties.getClass());
+// request_url = (String) function.invoke(null, request_url, requestProperties);
+// } catch (Exception e) {
+// e.printStackTrace();
+// }
+// }
+
+// request.processPathData(request_url, requestProperties);
+ return requestUrl;
+ }
+
+ public void processRequestPathValues(Map<String, String> nameValues) {
+ request.processRequestPathValues(nameValues);
+ }
+
+}
diff --git a/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/UtilsProvider.java b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/UtilsProvider.java
new file mode 100755
index 000000000..c89e35b2c
--- /dev/null
+++ b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/UtilsProvider.java
@@ -0,0 +1,36 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * onap
+ * ================================================================================
+ * Copyright (C) 2016 - 2017 ONAP
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.aai;
+
+import java.util.Properties;
+
+/**
+ * @author Rich Tabedzki
+ *
+ */
+public interface UtilsProvider {
+ /**
+ * Extract configuration properties.
+ *
+ * @return the configuration properties
+ */
+ Properties getProperties();
+}
diff --git a/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/data/AAIDatum.java b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/data/AAIDatum.java
new file mode 100644
index 000000000..2a44a38e4
--- /dev/null
+++ b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/data/AAIDatum.java
@@ -0,0 +1,26 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.aai.data;
+
+public interface AAIDatum {
+
+}
diff --git a/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/data/EchoResponse.java b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/data/EchoResponse.java
new file mode 100644
index 000000000..40f5f4e4c
--- /dev/null
+++ b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/data/EchoResponse.java
@@ -0,0 +1,76 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.aai.data;
+
+import java.util.HashMap;
+import java.util.Map;
+import javax.annotation.Generated;
+import com.fasterxml.jackson.annotation.JsonAnyGetter;
+import com.fasterxml.jackson.annotation.JsonAnySetter;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@Generated("org.jsonschema2pojo")
+@JsonPropertyOrder({
+ "responseMessages"
+})
+public class EchoResponse implements AAIDatum {
+
+ @JsonProperty("responseMessages")
+ private ResponseMessages responseMessages;
+ @JsonIgnore
+ private Map<String, Object> additionalProperties = new HashMap<String, Object>();
+
+ /**
+ *
+ * @return
+ * The responseMessages
+ */
+ @JsonProperty("responseMessages")
+ public ResponseMessages getResponseMessages() {
+ return responseMessages;
+ }
+
+ /**
+ *
+ * @param responseMessages
+ * The responseMessages
+ */
+ @JsonProperty("responseMessages")
+ public void setResponseMessages(ResponseMessages responseMessages) {
+ this.responseMessages = responseMessages;
+ }
+
+ @JsonAnyGetter
+ public Map<String, Object> getAdditionalProperties() {
+ return this.additionalProperties;
+ }
+
+ @JsonAnySetter
+ public void setAdditionalProperty(String name, Object value) {
+ this.additionalProperties.put(name, value);
+ }
+
+}
diff --git a/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/data/ErrorResponse.java b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/data/ErrorResponse.java
new file mode 100644
index 000000000..e650003cb
--- /dev/null
+++ b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/data/ErrorResponse.java
@@ -0,0 +1,78 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.aai.data;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.annotation.Generated;
+
+import com.fasterxml.jackson.annotation.JsonAnyGetter;
+import com.fasterxml.jackson.annotation.JsonAnySetter;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@Generated("org.jsonschema2pojo")
+@JsonPropertyOrder({
+ "requestError"
+})
+public class ErrorResponse {
+
+ @JsonProperty("requestError")
+ private RequestError requestError;
+ @JsonIgnore
+ private Map<String, Object> additionalProperties = new HashMap<String, Object>();
+
+ /**
+ *
+ * @return
+ * The requestError
+ */
+ @JsonProperty("requestError")
+ public RequestError getRequestError() {
+ return requestError;
+ }
+
+ /**
+ *
+ * @param requestError
+ * The requestError
+ */
+ @JsonProperty("requestError")
+ public void setRequestError(RequestError requestError) {
+ this.requestError = requestError;
+ }
+
+ @JsonAnyGetter
+ public Map<String, Object> getAdditionalProperties() {
+ return this.additionalProperties;
+ }
+
+ @JsonAnySetter
+ public void setAdditionalProperty(String name, Object value) {
+ this.additionalProperties.put(name, value);
+ }
+
+}
diff --git a/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/data/RequestError.java b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/data/RequestError.java
new file mode 100644
index 000000000..88325d828
--- /dev/null
+++ b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/data/RequestError.java
@@ -0,0 +1,78 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.aai.data;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.annotation.Generated;
+
+import com.fasterxml.jackson.annotation.JsonAnyGetter;
+import com.fasterxml.jackson.annotation.JsonAnySetter;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@Generated("org.jsonschema2pojo")
+@JsonPropertyOrder({
+ "serviceException"
+})
+public class RequestError {
+
+ @JsonProperty("serviceException")
+ private ServiceException serviceException;
+ @JsonIgnore
+ private Map<String, Object> additionalProperties = new HashMap<String, Object>();
+
+ /**
+ *
+ * @return
+ * The serviceException
+ */
+ @JsonProperty("serviceException")
+ public ServiceException getServiceException() {
+ return serviceException;
+ }
+
+ /**
+ *
+ * @param serviceException
+ * The serviceException
+ */
+ @JsonProperty("serviceException")
+ public void setServiceException(ServiceException serviceException) {
+ this.serviceException = serviceException;
+ }
+
+ @JsonAnyGetter
+ public Map<String, Object> getAdditionalProperties() {
+ return this.additionalProperties;
+ }
+
+ @JsonAnySetter
+ public void setAdditionalProperty(String name, Object value) {
+ this.additionalProperties.put(name, value);
+ }
+
+}
diff --git a/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/data/ResourceVersion.java b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/data/ResourceVersion.java
new file mode 100644
index 000000000..237d95a5a
--- /dev/null
+++ b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/data/ResourceVersion.java
@@ -0,0 +1,28 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.aai.data;
+
+public interface ResourceVersion {
+
+ public String getResourceVersion();
+ public void setResourceVersion(String resourceVersion);
+}
diff --git a/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/data/ResponseMessage.java b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/data/ResponseMessage.java
new file mode 100644
index 000000000..4742cef7a
--- /dev/null
+++ b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/data/ResponseMessage.java
@@ -0,0 +1,122 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.aai.data;
+
+import java.util.HashMap;
+import java.util.Map;
+import javax.annotation.Generated;
+import com.fasterxml.jackson.annotation.JsonAnyGetter;
+import com.fasterxml.jackson.annotation.JsonAnySetter;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@Generated("org.jsonschema2pojo")
+@JsonPropertyOrder({
+ "messageId",
+ "text",
+ "variables"
+})
+public class ResponseMessage {
+
+ @JsonProperty("messageId")
+ private String messageId;
+ @JsonProperty("text")
+ private String text;
+ @JsonProperty("variables")
+ private Variables variables;
+ @JsonIgnore
+ private Map<String, Object> additionalProperties = new HashMap<String, Object>();
+
+ /**
+ *
+ * @return
+ * The messageId
+ */
+ @JsonProperty("messageId")
+ public String getMessageId() {
+ return messageId;
+ }
+
+ /**
+ *
+ * @param messageId
+ * The messageId
+ */
+ @JsonProperty("messageId")
+ public void setMessageId(String messageId) {
+ this.messageId = messageId;
+ }
+
+ /**
+ *
+ * @return
+ * The text
+ */
+ @JsonProperty("text")
+ public String getText() {
+ return text;
+ }
+
+ /**
+ *
+ * @param text
+ * The text
+ */
+ @JsonProperty("text")
+ public void setText(String text) {
+ this.text = text;
+ }
+
+ /**
+ *
+ * @return
+ * The variables
+ */
+ @JsonProperty("variables")
+ public Variables getVariables() {
+ return variables;
+ }
+
+ /**
+ *
+ * @param variables
+ * The variables
+ */
+ @JsonProperty("variables")
+ public void setVariables(Variables variables) {
+ this.variables = variables;
+ }
+
+ @JsonAnyGetter
+ public Map<String, Object> getAdditionalProperties() {
+ return this.additionalProperties;
+ }
+
+ @JsonAnySetter
+ public void setAdditionalProperty(String name, Object value) {
+ this.additionalProperties.put(name, value);
+ }
+
+}
diff --git a/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/data/ResponseMessages.java b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/data/ResponseMessages.java
new file mode 100644
index 000000000..8ba5d145b
--- /dev/null
+++ b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/data/ResponseMessages.java
@@ -0,0 +1,78 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.aai.data;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.annotation.Generated;
+import com.fasterxml.jackson.annotation.JsonAnyGetter;
+import com.fasterxml.jackson.annotation.JsonAnySetter;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@Generated("org.jsonschema2pojo")
+@JsonPropertyOrder({
+ "responseMessage"
+})
+public class ResponseMessages {
+
+ @JsonProperty("responseMessage")
+ private List<ResponseMessage> responseMessage = new ArrayList<ResponseMessage>();
+ @JsonIgnore
+ private Map<String, Object> additionalProperties = new HashMap<String, Object>();
+
+ /**
+ *
+ * @return
+ * The responseMessage
+ */
+ @JsonProperty("responseMessage")
+ public List<ResponseMessage> getResponseMessage() {
+ return responseMessage;
+ }
+
+ /**
+ *
+ * @param responseMessage
+ * The responseMessage
+ */
+ @JsonProperty("responseMessage")
+ public void setResponseMessage(List<ResponseMessage> responseMessage) {
+ this.responseMessage = responseMessage;
+ }
+
+ @JsonAnyGetter
+ public Map<String, Object> getAdditionalProperties() {
+ return this.additionalProperties;
+ }
+
+ @JsonAnySetter
+ public void setAdditionalProperty(String name, Object value) {
+ this.additionalProperties.put(name, value);
+ }
+
+}
diff --git a/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/data/ServiceException.java b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/data/ServiceException.java
new file mode 100644
index 000000000..bdb09855a
--- /dev/null
+++ b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/data/ServiceException.java
@@ -0,0 +1,126 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.aai.data;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.annotation.Generated;
+
+import com.fasterxml.jackson.annotation.JsonAnyGetter;
+import com.fasterxml.jackson.annotation.JsonAnySetter;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@Generated("org.jsonschema2pojo")
+@JsonPropertyOrder({
+ "messageId",
+ "text",
+ "variables"
+})
+public class ServiceException {
+
+ @JsonProperty("messageId")
+ private String messageId;
+ @JsonProperty("text")
+ private String text;
+ @JsonProperty("variables")
+ private List<String> variables = new ArrayList<String>();
+ @JsonIgnore
+ private Map<String, Object> additionalProperties = new HashMap<String, Object>();
+
+ /**
+ *
+ * @return
+ * The messageId
+ */
+ @JsonProperty("messageId")
+ public String getMessageId() {
+ return messageId;
+ }
+
+ /**
+ *
+ * @param messageId
+ * The messageId
+ */
+ @JsonProperty("messageId")
+ public void setMessageId(String messageId) {
+ this.messageId = messageId;
+ }
+
+ /**
+ *
+ * @return
+ * The text
+ */
+ @JsonProperty("text")
+ public String getText() {
+ return text;
+ }
+
+ /**
+ *
+ * @param text
+ * The text
+ */
+ @JsonProperty("text")
+ public void setText(String text) {
+ this.text = text;
+ }
+
+ /**
+ *
+ * @return
+ * The variables
+ */
+ @JsonProperty("variables")
+ public List<String> getVariables() {
+ return variables;
+ }
+
+ /**
+ *
+ * @param variables
+ * The variables
+ */
+ @JsonProperty("variables")
+ public void setVariables(List<String> variables) {
+ this.variables = variables;
+ }
+
+ @JsonAnyGetter
+ public Map<String, Object> getAdditionalProperties() {
+ return this.additionalProperties;
+ }
+
+ @JsonAnySetter
+ public void setAdditionalProperty(String name, Object value) {
+ this.additionalProperties.put(name, value);
+ }
+
+}
diff --git a/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/data/SubInterface.java b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/data/SubInterface.java
new file mode 100644
index 000000000..7c66daa62
--- /dev/null
+++ b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/data/SubInterface.java
@@ -0,0 +1,171 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.aai.data;
+
+import java.util.HashMap;
+import java.util.Map;
+import javax.annotation.Generated;
+import com.fasterxml.jackson.annotation.JsonAnyGetter;
+import com.fasterxml.jackson.annotation.JsonAnySetter;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+
+import org.onap.aai.inventory.v21.RelationshipList;
+import org.onap.aai.inventory.v21.Vlans;
+
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@Generated("org.jsonschema2pojo")
+@JsonPropertyOrder({
+ "interface-name",
+ "interface-role",
+ "resource-version",
+ "vlans",
+ "relationshipList"
+})
+public class SubInterface implements AAIDatum {
+
+ @JsonProperty("interface-name")
+ private String interfaceName;
+ @JsonProperty("interface-role")
+ private String interfaceRole;
+ @JsonProperty("resource-version")
+ private String resourceVersion;
+ @JsonProperty("vlans")
+ private Vlans vlans;
+ @JsonProperty("relationshipList")
+ private RelationshipList relationshipList;
+ @JsonIgnore
+ private Map<String, Object> additionalProperties = new HashMap<String, Object>();
+
+ /**
+ *
+ * @return
+ * The interfaceName
+ */
+ @JsonProperty("interface-name")
+ public String getInterfaceName() {
+ return interfaceName;
+ }
+
+ /**
+ *
+ * @param interfaceName
+ * The interface-name
+ */
+ @JsonProperty("interface-name")
+ public void setInterfaceName(String interfaceName) {
+ this.interfaceName = interfaceName;
+ }
+
+ /**
+ *
+ * @return
+ * The interfaceRole
+ */
+ @JsonProperty("interface-role")
+ public String getInterfaceRole() {
+ return interfaceRole;
+ }
+
+ /**
+ *
+ * @param interfaceRole
+ * The interface-role
+ */
+ @JsonProperty("interface-role")
+ public void setInterfaceRole(String interfaceRole) {
+ this.interfaceRole = interfaceRole;
+ }
+
+ /**
+ *
+ * @return
+ * The resourceVersion
+ */
+ @JsonProperty("resource-version")
+ public String getResourceVersion() {
+ return resourceVersion;
+ }
+
+ /**
+ *
+ * @param resourceVersion
+ * The resource-version
+ */
+ @JsonProperty("resource-version")
+ public void setResourceVersion(String resourceVersion) {
+ this.resourceVersion = resourceVersion;
+ }
+
+ /**
+ *
+ * @return
+ * The vlans
+ */
+ @JsonProperty("vlans")
+ public Vlans getVlans() {
+ return vlans;
+ }
+
+ /**
+ *
+ * @param vlans
+ * The vlans
+ */
+ @JsonProperty("vlans")
+ public void setVlans(Vlans vlans) {
+ this.vlans = vlans;
+ }
+
+ /**
+ *
+ * @return
+ * The relationshipList
+ */
+ @JsonProperty("relationshipList")
+ public RelationshipList getRelationshipList() {
+ return relationshipList;
+ }
+
+ /**
+ *
+ * @param relationshipList
+ * The relationshipList
+ */
+ @JsonProperty("relationshipList")
+ public void setRelationshipList(RelationshipList relationshipList) {
+ this.relationshipList = relationshipList;
+ }
+
+ @JsonAnyGetter
+ public Map<String, Object> getAdditionalProperties() {
+ return this.additionalProperties;
+ }
+
+ @JsonAnySetter
+ public void setAdditionalProperty(String name, Object value) {
+ this.additionalProperties.put(name, value);
+ }
+
+}
diff --git a/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/data/Variables.java b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/data/Variables.java
new file mode 100644
index 000000000..3bdf70d7a
--- /dev/null
+++ b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/data/Variables.java
@@ -0,0 +1,78 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.aai.data;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.annotation.Generated;
+import com.fasterxml.jackson.annotation.JsonAnyGetter;
+import com.fasterxml.jackson.annotation.JsonAnySetter;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@Generated("org.jsonschema2pojo")
+@JsonPropertyOrder({
+ "variable"
+})
+public class Variables {
+
+ @JsonProperty("variable")
+ private List<String> variable = new ArrayList<String>();
+ @JsonIgnore
+ private Map<String, Object> additionalProperties = new HashMap<String, Object>();
+
+ /**
+ *
+ * @return
+ * The variable
+ */
+ @JsonProperty("variable")
+ public List<String> getVariable() {
+ return variable;
+ }
+
+ /**
+ *
+ * @param variable
+ * The variable
+ */
+ @JsonProperty("variable")
+ public void setVariable(List<String> variable) {
+ this.variable = variable;
+ }
+
+ @JsonAnyGetter
+ public Map<String, Object> getAdditionalProperties() {
+ return this.additionalProperties;
+ }
+
+ @JsonAnySetter
+ public void setAdditionalProperty(String name, Object value) {
+ this.additionalProperties.put(name, value);
+ }
+
+}
diff --git a/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/data/notify/KeyDatum.java b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/data/notify/KeyDatum.java
new file mode 100644
index 000000000..1cad9fdd6
--- /dev/null
+++ b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/data/notify/KeyDatum.java
@@ -0,0 +1,99 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.aai.data.notify;
+
+import java.util.HashMap;
+import java.util.Map;
+import javax.annotation.Generated;
+import com.fasterxml.jackson.annotation.JsonAnyGetter;
+import com.fasterxml.jackson.annotation.JsonAnySetter;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@Generated("org.jsonschema2pojo")
+@JsonPropertyOrder({
+ "key-name",
+ "key-value"
+})
+public class KeyDatum {
+
+ @JsonProperty("key-name")
+ private String keyName;
+ @JsonProperty("key-value")
+ private String keyValue;
+ @JsonIgnore
+ private Map<String, Object> additionalProperties = new HashMap<String, Object>();
+
+ /**
+ *
+ * @return
+ * The keyName
+ */
+ @JsonProperty("key-name")
+ public String getKeyName() {
+ return keyName;
+ }
+
+ /**
+ *
+ * @param keyName
+ * The key-name
+ */
+ @JsonProperty("key-name")
+ public void setKeyName(String keyName) {
+ this.keyName = keyName;
+ }
+
+ /**
+ *
+ * @return
+ * The keyValue
+ */
+ @JsonProperty("key-value")
+ public String getKeyValue() {
+ return keyValue;
+ }
+
+ /**
+ *
+ * @param keyValue
+ * The key-value
+ */
+ @JsonProperty("key-value")
+ public void setKeyValue(String keyValue) {
+ this.keyValue = keyValue;
+ }
+
+ @JsonAnyGetter
+ public Map<String, Object> getAdditionalProperties() {
+ return this.additionalProperties;
+ }
+
+ @JsonAnySetter
+ public void setAdditionalProperty(String name, Object value) {
+ this.additionalProperties.put(name, value);
+ }
+
+}
diff --git a/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/data/notify/NotifyEvent.java b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/data/notify/NotifyEvent.java
new file mode 100644
index 000000000..007096188
--- /dev/null
+++ b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/data/notify/NotifyEvent.java
@@ -0,0 +1,170 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.aai.data.notify;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.annotation.Generated;
+import com.fasterxml.jackson.annotation.JsonAnyGetter;
+import com.fasterxml.jackson.annotation.JsonAnySetter;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@Generated("org.jsonschema2pojo")
+@JsonPropertyOrder({
+ "event-id",
+ "event-trigger",
+ "key-data",
+ "node-type",
+ "selflink"
+})
+public class NotifyEvent {
+
+ @JsonProperty("event-id")
+ private String eventId;
+ @JsonProperty("event-trigger")
+ private String eventTrigger;
+ @JsonProperty("key-data")
+ private List<KeyDatum> keyData = new ArrayList<KeyDatum>();
+ @JsonProperty("node-type")
+ private String nodeType;
+ @JsonProperty("selflink")
+ private String selflink;
+ @JsonIgnore
+ private Map<String, Object> additionalProperties = new HashMap<String, Object>();
+
+ /**
+ *
+ * @return
+ * The eventId
+ */
+ @JsonProperty("event-id")
+ public String getEventId() {
+ return eventId;
+ }
+
+ /**
+ *
+ * @param eventId
+ * The event-id
+ */
+ @JsonProperty("event-id")
+ public void setEventId(String eventId) {
+ this.eventId = eventId;
+ }
+
+ /**
+ *
+ * @return
+ * The eventTrigger
+ */
+ @JsonProperty("event-trigger")
+ public String getEventTrigger() {
+ return eventTrigger;
+ }
+
+ /**
+ *
+ * @param eventTrigger
+ * The event-trigger
+ */
+ @JsonProperty("event-trigger")
+ public void setEventTrigger(String eventTrigger) {
+ this.eventTrigger = eventTrigger;
+ }
+
+ /**
+ *
+ * @return
+ * The keyData
+ */
+ @JsonProperty("key-data")
+ public List<KeyDatum> getKeyData() {
+ return keyData;
+ }
+
+ /**
+ *
+ * @param keyData
+ * The key-data
+ */
+ @JsonProperty("key-data")
+ public void setKeyData(List<KeyDatum> keyData) {
+ this.keyData = keyData;
+ }
+
+ /**
+ *
+ * @return
+ * The nodeType
+ */
+ @JsonProperty("node-type")
+ public String getNodeType() {
+ return nodeType;
+ }
+
+ /**
+ *
+ * @param nodeType
+ * The node-type
+ */
+ @JsonProperty("node-type")
+ public void setNodeType(String nodeType) {
+ this.nodeType = nodeType;
+ }
+
+ /**
+ *
+ * @return
+ * The selflink
+ */
+ @JsonProperty("selflink")
+ public String getSelflink() {
+ return selflink;
+ }
+
+ /**
+ *
+ * @param selflink
+ * The selflink
+ */
+ @JsonProperty("selflink")
+ public void setSelflink(String selflink) {
+ this.selflink = selflink;
+ }
+
+ @JsonAnyGetter
+ public Map<String, Object> getAdditionalProperties() {
+ return this.additionalProperties;
+ }
+
+ @JsonAnySetter
+ public void setAdditionalProperty(String name, Object value) {
+ this.additionalProperties.put(name, value);
+ }
+
+}
diff --git a/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/query/FormattedQueryRequestData.java b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/query/FormattedQueryRequestData.java
new file mode 100644
index 000000000..e2074e97b
--- /dev/null
+++ b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/query/FormattedQueryRequestData.java
@@ -0,0 +1,83 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.aai.query;
+
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+
+import org.onap.ccsdk.sli.adaptors.aai.data.AAIDatum;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "", propOrder = {
+ "start",
+ "query"
+})
+@XmlRootElement(name = "query-request")
+public class FormattedQueryRequestData implements AAIDatum {
+
+ @JsonProperty("start")
+ protected List<String> start;
+
+ @JsonProperty("query")
+ private String query;
+
+ @JsonProperty("start")
+ public List<String> getStart ()
+ {
+ return start;
+ }
+
+ @JsonProperty("start")
+ public void setStart (List<String> start)
+ {
+ this.start = start;
+ }
+
+ @JsonProperty("query")
+ public String getQuery ()
+ {
+ return query;
+ }
+
+ @JsonProperty("query")
+ public void setQuery (String query)
+ {
+ this.query = query;
+ }
+
+ @Override
+ public String toString()
+ {
+ return " [start = "+start+", query = "+query+"]";
+ }
+
+ public String getResourceVersion() {
+ return null;
+ }
+
+}
diff --git a/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/query/FormattedQueryResultList.java b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/query/FormattedQueryResultList.java
new file mode 100755
index 000000000..a50bf78b2
--- /dev/null
+++ b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/query/FormattedQueryResultList.java
@@ -0,0 +1,60 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.aai.query;
+
+import java.util.List;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+
+import org.onap.ccsdk.sli.adaptors.aai.data.AAIDatum;
+
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "", propOrder = {
+ "results"
+})
+@XmlRootElement(name = "result-list")
+public class FormattedQueryResultList implements AAIDatum {
+
+ @XmlElement(name = "results")
+ private List<Result> results;
+
+ @XmlElement(name = "results")
+ public List<Result> getResults ()
+ {
+ return results;
+ }
+ @XmlElement(name = "results")
+ public void setResults (List<Result> results)
+ {
+ this.results = results;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "ClassPojo [results = "+results+"]";
+ }
+}
diff --git a/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/query/InstanceFilter.java b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/query/InstanceFilter.java
new file mode 100755
index 000000000..48ada1fa9
--- /dev/null
+++ b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/query/InstanceFilter.java
@@ -0,0 +1,205 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.aai.query;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.annotation.Generated;
+
+import com.fasterxml.jackson.annotation.JsonAnyGetter;
+import com.fasterxml.jackson.annotation.JsonAnySetter;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+
+import org.onap.aai.inventory.v21.CloudRegion;
+import org.onap.aai.inventory.v21.GenericVnf;
+import org.onap.aai.inventory.v21.L3Network;
+import org.onap.aai.inventory.v21.Pnf;
+import org.onap.aai.inventory.v21.LogicalLink;
+import org.onap.aai.inventory.v21.PInterface;
+import org.onap.aai.inventory.v21.ServiceInstance;
+import org.onap.aai.inventory.v21.Tenant;
+import org.onap.aai.inventory.v21.Vnf;
+import org.onap.aai.inventory.v21.Vserver;
+
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@Generated("org.jsonschema2pojo")
+@JsonPropertyOrder({
+ "logical-link",
+ "pnf",
+ "l3-network",
+ "p-interface",
+ "generic-vnf",
+ "vserver",
+ "tenant",
+ "cloud-region",
+ "service-instance",
+ "vnfc"
+})
+public class InstanceFilter {
+
+ @JsonProperty("logical-link")
+ private LogicalLink logicalLink;
+ @JsonProperty("pnf")
+ private Pnf pnf;
+ @JsonProperty("l3-network")
+ private L3Network l3Network;
+ @JsonProperty("p-interface")
+ private PInterface pInterface;
+ @JsonProperty("generic-vnf")
+ private GenericVnf genericVnf;
+ @JsonProperty("vserver")
+ private Vserver vserver;
+ @JsonProperty("tenant")
+ private Tenant tenant;
+ @JsonProperty("cloud-region")
+ private CloudRegion cloudRegion;
+ @JsonProperty("service-instance")
+ private ServiceInstance serviceInstance;
+ @JsonProperty("vnfc")
+ private Vnf vnfc;
+
+ @JsonIgnore
+ private Map<String, Object> additionalProperties = new HashMap<String, Object>();
+
+ /**
+ *
+ * @return
+ * The logicalLink
+ */
+ @JsonProperty("logical-link")
+ public LogicalLink getLogicalLink() {
+ return logicalLink;
+ }
+
+ /**
+ *
+ * @param logicalLink
+ * The logical-link
+ */
+ @JsonProperty("logical-link")
+ public void setLogicalLink(LogicalLink logicalLink) {
+ this.logicalLink = logicalLink;
+ }
+
+ /**
+ *
+ * @return
+ * The pnf
+ */
+ @JsonProperty("pnf")
+ public Pnf getPnf() {
+ return pnf;
+ }
+
+ /**
+ *
+ * @param pnf
+ * The pnf
+ */
+ @JsonProperty("pnf")
+ public void setPnf(Pnf pnf) {
+ this.pnf = pnf;
+ }
+
+ @JsonProperty("l3-network")
+ public L3Network getL3Network() {
+ return l3Network;
+ }
+
+ @JsonProperty("l3-network")
+ public void setL3Network(L3Network l3Network) {
+ this.l3Network = l3Network;
+ }
+
+ @JsonAnyGetter
+ public Map<String, Object> getAdditionalProperties() {
+ return this.additionalProperties;
+ }
+
+ @JsonAnySetter
+ public void setAdditionalProperty(String name, Object value) {
+ this.additionalProperties.put(name, value);
+ }
+
+ @JsonProperty("service-instance")
+ public ServiceInstance getServiceInstance() {
+ return serviceInstance;
+ }
+
+ @JsonProperty("service-instance")
+ public void setServiceInstance(ServiceInstance serviceInstance) {
+ this.serviceInstance = serviceInstance;
+ }
+ @JsonProperty("p-interface")
+ public PInterface getpInterface() {
+ return pInterface;
+ }
+ @JsonProperty("p-interface")
+ public void setpInterface(PInterface pInterface) {
+ this.pInterface = pInterface;
+ }
+ @JsonProperty("generic-vnf")
+ public GenericVnf getGenericVnf() {
+ return genericVnf;
+ }
+ @JsonProperty("generic-vnf")
+ public void setGenericVnf(GenericVnf genericVnf) {
+ this.genericVnf = genericVnf;
+ }
+ @JsonProperty("vserver")
+ public Vserver getVserver() {
+ return vserver;
+ }
+ @JsonProperty("vserver")
+ public void setVserver(Vserver vserver) {
+ this.vserver = vserver;
+ }
+ @JsonProperty("tenant")
+ public Tenant getTenant() {
+ return tenant;
+ }
+ @JsonProperty("tenant")
+ public void setTenant(Tenant tenant) {
+ this.tenant = tenant;
+ }
+ @JsonProperty("cloud-region")
+ public CloudRegion getCloudRegion() {
+ return cloudRegion;
+ }
+ @JsonProperty("cloud-region")
+ public void setCloudRegion(CloudRegion cloudRegion) {
+ this.cloudRegion = cloudRegion;
+ }
+ @JsonProperty("vnfc")
+ public Vnf getVnfc() {
+ return vnfc;
+ }
+ @JsonProperty("vnfc")
+ public void setVnfc(Vnf vnfc) {
+ this.vnfc = vnfc;
+ }
+
+}
diff --git a/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/query/InstanceFilters.java b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/query/InstanceFilters.java
new file mode 100644
index 000000000..c0a3ba255
--- /dev/null
+++ b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/query/InstanceFilters.java
@@ -0,0 +1,78 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.aai.query;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.annotation.Generated;
+import com.fasterxml.jackson.annotation.JsonAnyGetter;
+import com.fasterxml.jackson.annotation.JsonAnySetter;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@Generated("org.jsonschema2pojo")
+@JsonPropertyOrder({
+ "instance-filter"
+})
+public class InstanceFilters {
+
+ @JsonProperty("instance-filter")
+ private List<InstanceFilter> instanceFilter = new ArrayList<InstanceFilter>();
+ @JsonIgnore
+ private Map<String, Object> additionalProperties = new HashMap<String, Object>();
+
+ /**
+ *
+ * @return
+ * The instanceFilter
+ */
+ @JsonProperty("instance-filter")
+ public List<InstanceFilter> getInstanceFilter() {
+ return instanceFilter;
+ }
+
+ /**
+ *
+ * @param instanceFilter
+ * The instance-filter
+ */
+ @JsonProperty("instance-filter")
+ public void setInstanceFilter(List<InstanceFilter> instanceFilter) {
+ this.instanceFilter = instanceFilter;
+ }
+
+ @JsonAnyGetter
+ public Map<String, Object> getAdditionalProperties() {
+ return this.additionalProperties;
+ }
+
+ @JsonAnySetter
+ public void setAdditionalProperty(String name, Object value) {
+ this.additionalProperties.put(name, value);
+ }
+
+}
diff --git a/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/query/Result.java b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/query/Result.java
new file mode 100755
index 000000000..1f8a17551
--- /dev/null
+++ b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/query/Result.java
@@ -0,0 +1,278 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.aai.query;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.XmlType;
+
+import org.onap.aai.inventory.v21.CloudRegion;
+import org.onap.aai.inventory.v21.Complex;
+import org.onap.aai.inventory.v21.Configuration;
+import org.onap.aai.inventory.v21.GenericVnf;
+import org.onap.aai.inventory.v21.L3InterfaceIpv4AddressList;
+import org.onap.aai.inventory.v21.L3InterfaceIpv6AddressList;
+import org.onap.aai.inventory.v21.L3Network;
+import org.onap.aai.inventory.v21.LInterface;
+//import org.onap.aai.inventory.v21.OwningEntity;
+import org.onap.aai.inventory.v21.Pserver;
+import org.onap.aai.inventory.v21.ServiceInstance;
+import org.onap.aai.inventory.v21.Vnfc;
+import org.onap.aai.inventory.v21.Vserver;
+
+import com.fasterxml.jackson.annotation.JsonAnyGetter;
+import com.fasterxml.jackson.annotation.JsonAnySetter;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "", propOrder = {
+ "resource-type",
+ "resource-link",
+ "url",
+ "cloud-region",
+ "complex",
+ "configuration",
+ "generic-vnf",
+ "l3-interface-ipv4-address-list",
+ "l3-interface-ipv6-address-list",
+ "l3-network",
+ "l-interface",
+ "owning-entity",
+ "pserver",
+ "service-instance",
+ "vnfc",
+ "vserver"
+})
+@XmlRootElement(name = "result")
+public class Result {
+
+ @XmlElement(name = "resource-type")
+ private String resourceType;
+ @XmlElement(name = "resource-link")
+ private String resourceLink;
+ @XmlElement(name = "url")
+ private String url;
+ @XmlElement(name = "cloud-region")
+ private CloudRegion cloudRegion;
+ @XmlElement(name = "complex")
+ private Complex complex;
+ @XmlElement(name = "configuration")
+ private Configuration configuration;
+ @XmlElement(name = "generic-vnf")
+ private GenericVnf genericVnf;
+ @XmlElement(name = "l3-interface-ipv4-address-list")
+ private L3InterfaceIpv4AddressList l3InterfaceIpv4AddressList;
+ @XmlElement(name = "l3-interface-ipv6-address-list")
+ private L3InterfaceIpv6AddressList l3InterfaceIpv6AddressList;
+ @XmlElement(name = "l3-network")
+ private L3Network l3Network;
+ @XmlElement(name = "l-interface")
+ private LInterface lInterface;
+// @XmlElement(name = "owning-entity")
+// private OwningEntity owningEntity;
+ @XmlElement(name = "pserver")
+ private Pserver pserver;
+ @XmlElement(name = "service-instance")
+ private ServiceInstance serviceInstance;
+ @XmlElement(name = "vnfc")
+ private Vnfc vnfc;
+ @XmlElement(name = "vserver")
+ private Vserver vserver;
+ @JsonIgnore
+ private Map<String, Object> additionalProperties = new HashMap<String, Object>();
+
+ @XmlElement(name = "cloud-region")
+ public CloudRegion getCloudRegion() {
+ return cloudRegion;
+ }
+
+ @XmlElement(name = "cloud-region")
+ public void setCloudRegion(CloudRegion cloudRegion) {
+ this.cloudRegion = cloudRegion;
+ }
+
+ @XmlElement(name = "complex")
+ public Complex getComplex() {
+ return complex;
+ }
+
+ @XmlElement(name = "complex")
+ public void setComplex(Complex complex) {
+ this.complex = complex;
+ }
+
+ @XmlElement(name = "configuration")
+ public Configuration getConfiguration() {
+ return configuration;
+ }
+
+ @XmlElement(name = "configuration")
+ public void setConfiguration(Configuration configuration) {
+ this.configuration = configuration;
+ }
+
+ @XmlElement(name = "generic-vnf")
+ public GenericVnf getGenericVnf ()
+ {
+ return genericVnf;
+ }
+
+ @XmlElement(name = "generic-vnf")
+ public void setGenericVnf (GenericVnf genericVnf)
+ {
+ this.genericVnf = genericVnf;
+ }
+
+ @JsonProperty("l3-interface-ipv4-address-list")
+ public L3InterfaceIpv4AddressList getL3InterfaceIpv4AddressList() {
+ return l3InterfaceIpv4AddressList;
+ }
+
+ @JsonProperty("l3-interface-ipv4-address-list")
+ public void setL3InterfaceIpv4AddressList(L3InterfaceIpv4AddressList l3InterfaceIpv4AddressList) {
+ this.l3InterfaceIpv4AddressList = l3InterfaceIpv4AddressList;
+ }
+
+ @JsonProperty("l3-interface-ipv6-address-list")
+ public L3InterfaceIpv6AddressList getL3InterfaceIpv6AddressList() {
+ return l3InterfaceIpv6AddressList;
+ }
+
+ @JsonProperty("l3-interface-ipv6-address-list")
+ public void setL3InterfaceIpv6AddressList(L3InterfaceIpv6AddressList l3InterfaceIpv6AddressList) {
+ this.l3InterfaceIpv6AddressList = l3InterfaceIpv6AddressList;
+ }
+
+ @XmlElement(name = "l3-network")
+ public L3Network getL3Network() {
+ return l3Network;
+ }
+
+ @XmlElement(name = "l3-network")
+ public void setL3Network(L3Network l3Network) {
+ this.l3Network = l3Network;
+ }
+
+ @XmlElement(name = "l-interface")
+ public LInterface getLInterface() {
+ return lInterface;
+ }
+ @XmlElement(name = "l-interface")
+ public void setLInterface(LInterface linterface) {
+ this.lInterface = linterface;
+ }
+
+// @XmlElement(name = "owning-entity")
+// public OwningEntity getOwningEntity() {
+// return owningEntity;
+// }
+
+// @XmlElement(name = "owning-entity")
+// public void setOwningEntity(OwningEntity owningEntity) {
+// this.owningEntity = owningEntity;
+// }
+
+ @XmlElement(name = "pserver")
+ public Pserver getPserver() {
+ return pserver;
+ }
+ @XmlElement(name = "pserver")
+ public void setPserver(Pserver pserver) {
+ this.pserver = pserver;
+ }
+
+ @XmlElement(name = "service-instance")
+ public ServiceInstance getServiceInstance() {
+ return serviceInstance;
+ }
+
+ @XmlElement(name = "service-instance")
+ public void setServiceInstance(ServiceInstance serviceInstance) {
+ this.serviceInstance = serviceInstance;
+ }
+
+ @XmlElement(name = "vnfc")
+ public Vnfc getVnfc() {
+ return vnfc;
+ }
+
+ @XmlElement(name = "vnfc")
+ public void setVnfc(Vnfc vnfc) {
+ this.vnfc = vnfc;
+ }
+
+ @XmlElement(name = "vserver")
+ public Vserver getVserver() {
+ return vserver;
+ }
+
+ @XmlElement(name = "vserver")
+ public void setVserver(Vserver vserver) {
+ this.vserver = vserver;
+ }
+
+ @Override
+ public String toString()
+ {
+ return " [generic-vnf = "+genericVnf+"]";
+ }
+
+ @JsonAnyGetter
+ public Map<String, Object> getAdditionalProperties() {
+ return this.additionalProperties;
+ }
+
+ @JsonAnySetter
+ public void setAdditionalProperty(String name, Object value) {
+ this.additionalProperties.put(name, value);
+ }
+ @XmlElement(name = "resource-type")
+ public String getResourceType() {
+ return resourceType;
+ }
+ @XmlElement(name = "resource-type")
+ public void setResourceType(String resourceType) {
+ this.resourceType = resourceType;
+ }
+ @XmlElement(name = "resource-link")
+ public String getResourceLink() {
+ return resourceLink;
+ }
+ @XmlElement(name = "resource-link")
+ public void setResourceLink(String resourceLink) {
+ this.resourceLink = resourceLink;
+ }
+ @XmlElement(name = "url")
+ public String getUrl() {
+ return url;
+ }
+ @XmlElement(name = "url")
+ public void setUrl(String url) {
+ this.url = url;
+ }
+}
diff --git a/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/update/Action.java b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/update/Action.java
new file mode 100644
index 000000000..376da0d01
--- /dev/null
+++ b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/update/Action.java
@@ -0,0 +1,101 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.aai.update;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.annotation.Generated;
+import com.fasterxml.jackson.annotation.JsonAnyGetter;
+import com.fasterxml.jackson.annotation.JsonAnySetter;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@Generated("org.jsonschema2pojo")
+@JsonPropertyOrder({
+ "action-data",
+ "action-type"
+})
+public class Action {
+
+ @JsonProperty("action-data")
+ private List<ActionDatum> actionData = new ArrayList<ActionDatum>();
+ @JsonProperty("action-type")
+ private String actionType;
+ @JsonIgnore
+ private Map<String, Object> additionalProperties = new HashMap<String, Object>();
+
+ /**
+ *
+ * @return
+ * The actionData
+ */
+ @JsonProperty("action-data")
+ public List<ActionDatum> getActionData() {
+ return actionData;
+ }
+
+ /**
+ *
+ * @param actionData
+ * The action-data
+ */
+ @JsonProperty("action-data")
+ public void setActionData(List<ActionDatum> actionData) {
+ this.actionData = actionData;
+ }
+
+ /**
+ *
+ * @return
+ * The actionType
+ */
+ @JsonProperty("action-type")
+ public String getActionType() {
+ return actionType;
+ }
+
+ /**
+ *
+ * @param actionType
+ * The action-type
+ */
+ @JsonProperty("action-type")
+ public void setActionType(String actionType) {
+ this.actionType = actionType;
+ }
+
+ @JsonAnyGetter
+ public Map<String, Object> getAdditionalProperties() {
+ return this.additionalProperties;
+ }
+
+ @JsonAnySetter
+ public void setAdditionalProperty(String name, Object value) {
+ this.additionalProperties.put(name, value);
+ }
+
+}
diff --git a/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/update/ActionDatum.java b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/update/ActionDatum.java
new file mode 100644
index 000000000..67c6246c7
--- /dev/null
+++ b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/update/ActionDatum.java
@@ -0,0 +1,99 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.aai.update;
+
+import java.util.HashMap;
+import java.util.Map;
+import javax.annotation.Generated;
+import com.fasterxml.jackson.annotation.JsonAnyGetter;
+import com.fasterxml.jackson.annotation.JsonAnySetter;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@Generated("org.jsonschema2pojo")
+@JsonPropertyOrder({
+ "property-name",
+ "property-value"
+})
+public class ActionDatum {
+
+ @JsonProperty("property-name")
+ private String propertyName;
+ @JsonProperty("property-value")
+ private String propertyValue;
+ @JsonIgnore
+ private Map<String, Object> additionalProperties = new HashMap<String, Object>();
+
+ /**
+ *
+ * @return
+ * The propertyName
+ */
+ @JsonProperty("property-name")
+ public String getPropertyName() {
+ return propertyName;
+ }
+
+ /**
+ *
+ * @param propertyName
+ * The property-name
+ */
+ @JsonProperty("property-name")
+ public void setPropertyName(String propertyName) {
+ this.propertyName = propertyName;
+ }
+
+ /**
+ *
+ * @return
+ * The propertyValue
+ */
+ @JsonProperty("property-value")
+ public String getPropertyValue() {
+ return propertyValue;
+ }
+
+ /**
+ *
+ * @param propertyValue
+ * The property-value
+ */
+ @JsonProperty("property-value")
+ public void setPropertyValue(String propertyValue) {
+ this.propertyValue = propertyValue;
+ }
+
+ @JsonAnyGetter
+ public Map<String, Object> getAdditionalProperties() {
+ return this.additionalProperties;
+ }
+
+ @JsonAnySetter
+ public void setAdditionalProperty(String name, Object value) {
+ this.additionalProperties.put(name, value);
+ }
+
+}
diff --git a/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/update/Update.java b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/update/Update.java
new file mode 100644
index 000000000..80bb75694
--- /dev/null
+++ b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/update/Update.java
@@ -0,0 +1,124 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.aai.update;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import javax.annotation.Generated;
+import com.fasterxml.jackson.annotation.JsonAnyGetter;
+import com.fasterxml.jackson.annotation.JsonAnySetter;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@Generated("org.jsonschema2pojo")
+@JsonPropertyOrder({
+ "update-node-type",
+ "update-node-key",
+ "action"
+})
+public class Update {
+
+ @JsonProperty("update-node-type")
+ private String updateNodeType;
+ @JsonProperty("action")
+ private List<Action> action = new ArrayList<Action>();
+ @JsonProperty("update-node-key")
+ private List<UpdateNodeKey> updateNodeKey = new ArrayList<UpdateNodeKey>();
+ @JsonIgnore
+ private Map<String, Object> additionalProperties = new HashMap<String, Object>();
+
+ /**
+ *
+ * @return
+ * The updateNodeType
+ */
+ @JsonProperty("update-node-type")
+ public String getUpdateNodeType() {
+ return updateNodeType;
+ }
+
+ /**
+ *
+ * @param updateNodeType
+ * The update-node-type
+ */
+ @JsonProperty("update-node-type")
+ public void setUpdateNodeType(String updateNodeType) {
+ this.updateNodeType = updateNodeType;
+ }
+
+ /**
+ *
+ * @return
+ * The action
+ */
+ @JsonProperty("action")
+ public List<Action> getAction() {
+ return action;
+ }
+
+ /**
+ *
+ * @param action
+ * The action
+ */
+ @JsonProperty("action")
+ public void setAction(List<Action> action) {
+ this.action = action;
+ }
+
+ /**
+ *
+ * @return
+ * The updateNodeKey
+ */
+ @JsonProperty("update-node-key")
+ public List<UpdateNodeKey> getUpdateNodeKey() {
+ return updateNodeKey;
+ }
+
+ /**
+ *
+ * @param updateNodeKey
+ * The update-node-key
+ */
+ @JsonProperty("update-node-key")
+ public void setUpdateNodeKey(List<UpdateNodeKey> updateNodeKey) {
+ this.updateNodeKey = updateNodeKey;
+ }
+
+ @JsonAnyGetter
+ public Map<String, Object> getAdditionalProperties() {
+ return this.additionalProperties;
+ }
+
+ @JsonAnySetter
+ public void setAdditionalProperty(String name, Object value) {
+ this.additionalProperties.put(name, value);
+ }
+
+}
diff --git a/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/update/UpdateNodeKey.java b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/update/UpdateNodeKey.java
new file mode 100644
index 000000000..6803ea2c2
--- /dev/null
+++ b/adaptors/aai-service/provider/src/main/java/org/onap/ccsdk/sli/adaptors/aai/update/UpdateNodeKey.java
@@ -0,0 +1,99 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.aai.update;
+
+import java.util.HashMap;
+import java.util.Map;
+import javax.annotation.Generated;
+import com.fasterxml.jackson.annotation.JsonAnyGetter;
+import com.fasterxml.jackson.annotation.JsonAnySetter;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonPropertyOrder;
+
+@JsonInclude(JsonInclude.Include.NON_NULL)
+@Generated("org.jsonschema2pojo")
+@JsonPropertyOrder({
+ "key-name",
+ "key-value"
+})
+public class UpdateNodeKey {
+
+ @JsonProperty("key-name")
+ private String keyName;
+ @JsonProperty("key-value")
+ private String keyValue;
+ @JsonIgnore
+ private Map<String, Object> additionalProperties = new HashMap<String, Object>();
+
+ /**
+ *
+ * @return
+ * The keyName
+ */
+ @JsonProperty("key-name")
+ public String getKeyName() {
+ return keyName;
+ }
+
+ /**
+ *
+ * @param keyName
+ * The key-name
+ */
+ @JsonProperty("key-name")
+ public void setKeyName(String keyName) {
+ this.keyName = keyName;
+ }
+
+ /**
+ *
+ * @return
+ * The keyValue
+ */
+ @JsonProperty("key-value")
+ public String getKeyValue() {
+ return keyValue;
+ }
+
+ /**
+ *
+ * @param keyValue
+ * The key-value
+ */
+ @JsonProperty("key-value")
+ public void setKeyValue(String keyValue) {
+ this.keyValue = keyValue;
+ }
+
+ @JsonAnyGetter
+ public Map<String, Object> getAdditionalProperties() {
+ return this.additionalProperties;
+ }
+
+ @JsonAnySetter
+ public void setAdditionalProperty(String name, Object value) {
+ this.additionalProperties.put(name, value);
+ }
+
+}
diff --git a/adaptors/aai-service/provider/src/main/resources/OSGI-INF/blueprint/aaiservice-blueprint.xml b/adaptors/aai-service/provider/src/main/resources/OSGI-INF/blueprint/aaiservice-blueprint.xml
new file mode 100755
index 000000000..970936610
--- /dev/null
+++ b/adaptors/aai-service/provider/src/main/resources/OSGI-INF/blueprint/aaiservice-blueprint.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ============LICENSE_START=======================================================
+ openECOMP : SDN-C
+ ================================================================================
+ Copyright (C) 2017 - 2018 AT&T Intellectual Property. All rights
+ reserved.
+ ================================================================================
+ 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.
+ ============LICENSE_END=========================================================
+ -->
+
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+ xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0"
+ odl:use-default-for-reference-types="true">
+
+ <bean id="provider" class="org.onap.ccsdk.sli.adaptors.aai.AAIServiceProvider" />
+
+ <bean id="aaiService" class="org.onap.ccsdk.sli.adaptors.aai.AAIService">
+ <argument ref="provider" />
+ </bean>
+ <service ref="aaiService">
+ <interfaces>
+ <value>org.onap.ccsdk.sli.adaptors.aai.AAIService</value>
+ <value>org.onap.ccsdk.sli.adaptors.aai.AAIClient</value>
+ </interfaces>
+ </service>
+
+</blueprint>
diff --git a/adaptors/aai-service/provider/src/main/resources/aai-path.properties b/adaptors/aai-service/provider/src/main/resources/aai-path.properties
new file mode 100755
index 000000000..e597d7e0a
--- /dev/null
+++ b/adaptors/aai-service/provider/src/main/resources/aai-path.properties
@@ -0,0 +1,353 @@
+###
+# ============LICENSE_START=======================================================
+# openECOMP : SDN-C
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights
+# reserved.
+# ================================================================================
+# 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.
+# ============LICENSE_END=========================================================
+###
+
+cloud-regions = /aai/v21/cloud-infrastructure/cloud-regions
+cloud-region = /aai/v21/cloud-infrastructure/cloud-regions/cloud-region/{cloud-owner}/{cloud-region-id}
+cloud-region|availability-zones = /aai/v21/cloud-infrastructure/cloud-regions/cloud-region/{cloud-owner}/{cloud-region-id}/availability-zones
+cloud-region|availability-zone = /aai/v21/cloud-infrastructure/cloud-regions/cloud-region/{cloud-owner}/{cloud-region-id}/availability-zones/availability-zone/{availability-zone-name}
+cloud-region|dvs-switches = /aai/v21/cloud-infrastructure/cloud-regions/cloud-region/{cloud-owner}/{cloud-region-id}/dvs-switches
+cloud-region|dvs-switch = /aai/v21/cloud-infrastructure/cloud-regions/cloud-region/{cloud-owner}/{cloud-region-id}/dvs-switches/dvs-switch/{switch-name}
+cloud-region|flavors = /aai/v21/cloud-infrastructure/cloud-regions/cloud-region/{cloud-owner}/{cloud-region-id}/flavors
+cloud-region|flavor = /aai/v21/cloud-infrastructure/cloud-regions/cloud-region/{cloud-owner}/{cloud-region-id}/flavors/flavor/{flavor-id}
+cloud-region|flavor|hpa-capabilities = /aai/v21/cloud-infrastructure/cloud-regions/cloud-region/{cloud-owner}/{cloud-region-id}/flavors/flavor/{flavor-id}/hpa-capabilities
+cloud-region|flavor|hpa-capability = /aai/v21/cloud-infrastructure/cloud-regions/cloud-region/{cloud-owner}/{cloud-region-id}/flavors/flavor/{flavor-id}/hpa-capabilities/hpa-capability/{hpa-capability-id}
+cloud-region|flavor|hpa-capability|hpa-feature-attributes = /aai/v21/cloud-infrastructure/cloud-regions/cloud-region/{cloud-owner}/{cloud-region-id}/flavors/flavor/{flavor-id}/hpa-capabilities/hpa-capability/{hpa-capability-id}/hpa-feature-attributes/{hpa-attribute-key}
+cloud-region|group-assignments = /aai/v21/cloud-infrastructure/cloud-regions/cloud-region/{cloud-owner}/{cloud-region-id}/group-assignments
+cloud-region|group-assignment = /aai/v21/cloud-infrastructure/cloud-regions/cloud-region/{cloud-owner}/{cloud-region-id}/group-assignments/group-assignment/{group-id}
+cloud-region|hpa-capabilities = /aai/v21/cloud-infrastructure/cloud-regions/cloud-region/{cloud-owner}/{cloud-region-id}/hpa-capabilities
+cloud-region|hpa-capability = /aai/v21/cloud-infrastructure/cloud-regions/cloud-region/{cloud-owner}/{cloud-region-id}/hpa-capabilities/hpa-capability/{hpa-capability-id}
+cloud-region|hpa-capability|hpa-feature-attributes = /aai/v21/cloud-infrastructure/cloud-regions/cloud-region/{cloud-owner}/{cloud-region-id}/hpa-capabilities/hpa-capability/{hpa-capability-id}/hpa-feature-attributes/{hpa-attribute-key}
+cloud-region|images = /aai/v21/cloud-infrastructure/cloud-regions/cloud-region/{cloud-owner}/{cloud-region-id}/images
+cloud-region|image = /aai/v21/cloud-infrastructure/cloud-regions/cloud-region/{cloud-owner}/{cloud-region-id}/images/image/{image-id}
+cloud-region|image|metadata = /aai/v21/cloud-infrastructure/cloud-regions/cloud-region/{cloud-owner}/{cloud-region-id}/images/image/{image-id}/metadata
+cloud-region|image|metadatum = /aai/v21/cloud-infrastructure/cloud-regions/cloud-region/{cloud-owner}/{cloud-region-id}/images/image/{image-id}/metadata/metadatum/{metaname}
+cloud-region|oam-networks = /aai/v21/cloud-infrastructure/cloud-regions/cloud-region/{cloud-owner}/{cloud-region-id}/oam-networks
+cloud-region|oam-network = /aai/v21/cloud-infrastructure/cloud-regions/cloud-region/{cloud-owner}/{cloud-region-id}/oam-networks/oam-network/{network-uuid}
+cloud-region|snapshots = /aai/v21/cloud-infrastructure/cloud-regions/cloud-region/{cloud-owner}/{cloud-region-id}/snapshots
+cloud-region|snapshot = /aai/v21/cloud-infrastructure/cloud-regions/cloud-region/{cloud-owner}/{cloud-region-id}/snapshots/snapshot/{snapshot-id}
+cloud-region|tenants = /aai/v21/cloud-infrastructure/cloud-regions/cloud-region/{cloud-owner}/{cloud-region-id}/tenants
+cloud-region|tenant = /aai/v21/cloud-infrastructure/cloud-regions/cloud-region/{cloud-owner}/{cloud-region-id}/tenants/tenant/{tenant-id}
+cloud-region|tenant|vservers = /aai/v21/cloud-infrastructure/cloud-regions/cloud-region/{cloud-owner}/{cloud-region-id}/tenants/tenant/{tenant-id}/vservers
+cloud-region|tenant|vserver = /aai/v21/cloud-infrastructure/cloud-regions/cloud-region/{cloud-owner}/{cloud-region-id}/tenants/tenant/{tenant-id}/vservers/vserver/{vserver-id}
+cloud-region|tenant|vserver|l-interfaces = /aai/v21/cloud-infrastructure/cloud-regions/cloud-region/{cloud-owner}/{cloud-region-id}/tenants/tenant/{tenant-id}/vservers/vserver/{vserver-id}/l-interfaces
+cloud-region|tenant|vserver|l-interface = /aai/v21/cloud-infrastructure/cloud-regions/cloud-region/{cloud-owner}/{cloud-region-id}/tenants/tenant/{tenant-id}/vservers/vserver/{vserver-id}/l-interfaces/l-interface/{interface-name}
+cloud-region|tenant|vserver|l-interface|l3-interface-ipv4-address-list = /aai/v21/cloud-infrastructure/cloud-regions/cloud-region/{cloud-owner}/{cloud-region-id}/tenants/tenant/{tenant-id}/vservers/vserver/{vserver-id}/l-interfaces/l-interface/{interface-name}/l3-interface-ipv4-address-list/{l3-interface-ipv4-address}
+cloud-region|tenant|vserver|l-interface|l3-interface-ipv6-address-list = /aai/v21/cloud-infrastructure/cloud-regions/cloud-region/{cloud-owner}/{cloud-region-id}/tenants/tenant/{tenant-id}/vservers/vserver/{vserver-id}/l-interfaces/l-interface/{interface-name}/l3-interface-ipv6-address-list/{l3-interface-ipv6-address}
+cloud-region|tenant|vserver|l-interface|sriov-vfs = /aai/v21/cloud-infrastructure/cloud-regions/cloud-region/{cloud-owner}/{cloud-region-id}/tenants/tenant/{tenant-id}/vservers/vserver/{vserver-id}/l-interfaces/l-interface/{interface-name}/sriov-vfs
+cloud-region|tenant|vserver|l-interface|sriov-vf = /aai/v21/cloud-infrastructure/cloud-regions/cloud-region/{cloud-owner}/{cloud-region-id}/tenants/tenant/{tenant-id}/vservers/vserver/{vserver-id}/l-interfaces/l-interface/{interface-name}/sriov-vfs/sriov-vf/{pci-id}
+cloud-region|tenant|vserver|l-interface|vlans = /aai/v21/cloud-infrastructure/cloud-regions/cloud-region/{cloud-owner}/{cloud-region-id}/tenants/tenant/{tenant-id}/vservers/vserver/{vserver-id}/l-interfaces/l-interface/{interface-name}/vlans
+cloud-region|tenant|vserver|l-interface|vlan = /aai/v21/cloud-infrastructure/cloud-regions/cloud-region/{cloud-owner}/{cloud-region-id}/tenants/tenant/{tenant-id}/vservers/vserver/{vserver-id}/l-interfaces/l-interface/{interface-name}/vlans/vlan/{vlan-interface}
+cloud-region|tenant|vserver|l-interface|vlan|l3-interface-ipv4-address-list = /aai/v21/cloud-infrastructure/cloud-regions/cloud-region/{cloud-owner}/{cloud-region-id}/tenants/tenant/{tenant-id}/vservers/vserver/{vserver-id}/l-interfaces/l-interface/{interface-name}/vlans/vlan/{vlan-interface}/l3-interface-ipv4-address-list/{l3-interface-ipv4-address}
+cloud-region|tenant|vserver|l-interface|vlan|l3-interface-ipv6-address-list = /aai/v21/cloud-infrastructure/cloud-regions/cloud-region/{cloud-owner}/{cloud-region-id}/tenants/tenant/{tenant-id}/vservers/vserver/{vserver-id}/l-interfaces/l-interface/{interface-name}/vlans/vlan/{vlan-interface}/l3-interface-ipv6-address-list/{l3-interface-ipv6-address}
+cloud-region|tenant|vserver|volumes = /aai/v21/cloud-infrastructure/cloud-regions/cloud-region/{cloud-owner}/{cloud-region-id}/tenants/tenant/{tenant-id}/vservers/vserver/{vserver-id}/volumes
+cloud-region|tenant|vserver|volume = /aai/v21/cloud-infrastructure/cloud-regions/cloud-region/{cloud-owner}/{cloud-region-id}/tenants/tenant/{tenant-id}/vservers/vserver/{vserver-id}/volumes/volume/{volume-id}
+cloud-region|vip-ipv4-address-list = /aai/v21/cloud-infrastructure/cloud-regions/cloud-region/{cloud-owner}/{cloud-region-id}/vip-ipv4-address-list/{vip-ipv4-address}
+cloud-region|vip-ipv6-address-list = /aai/v21/cloud-infrastructure/cloud-regions/cloud-region/{cloud-owner}/{cloud-region-id}/vip-ipv6-address-list/{vip-ipv6-address}
+cloud-region|volume-groups = /aai/v21/cloud-infrastructure/cloud-regions/cloud-region/{cloud-owner}/{cloud-region-id}/volume-groups
+cloud-region|volume-group = /aai/v21/cloud-infrastructure/cloud-regions/cloud-region/{cloud-owner}/{cloud-region-id}/volume-groups/volume-group/{volume-group-id}
+complexes = /aai/v21/cloud-infrastructure/complexes
+complex = /aai/v21/cloud-infrastructure/complexes/complex/{physical-location-id}
+complex|ctag-pools = /aai/v21/cloud-infrastructure/complexes/complex/{physical-location-id}/ctag-pools
+complex|ctag-pool = /aai/v21/cloud-infrastructure/complexes/complex/{physical-location-id}/ctag-pools/ctag-pool/{target-pe}/{availability-zone-name}
+network-profiles = /aai/v21/cloud-infrastructure/network-profiles
+network-profile = /aai/v21/cloud-infrastructure/network-profiles/network-profile/{nm-profile-name}
+operational-environments = /aai/v21/cloud-infrastructure/operational-environments
+operational-environment = /aai/v21/cloud-infrastructure/operational-environments/operational-environment/{operational-environment-id}
+pservers = /aai/v21/cloud-infrastructure/pservers
+pserver = /aai/v21/cloud-infrastructure/pservers/pserver/{hostname}
+pserver|lag-interfaces = /aai/v21/cloud-infrastructure/pservers/pserver/{hostname}/lag-interfaces
+pserver|lag-interface = /aai/v21/cloud-infrastructure/pservers/pserver/{hostname}/lag-interfaces/lag-interface/{interface-name}
+pserver|lag-interface|l-interfaces = /aai/v21/cloud-infrastructure/pservers/pserver/{hostname}/lag-interfaces/lag-interface/{interface-name}/l-interfaces
+pserver|lag-interface|l-interface = /aai/v21/cloud-infrastructure/pservers/pserver/{hostname}/lag-interfaces/lag-interface/{interface-name}/l-interfaces/l-interface/{interface-name}
+pserver|lag-interface|l-interface|l3-interface-ipv4-address-list = /aai/v21/cloud-infrastructure/pservers/pserver/{hostname}/lag-interfaces/lag-interface/{interface-name}/l-interfaces/l-interface/{interface-name}/l3-interface-ipv4-address-list/{l3-interface-ipv4-address}
+pserver|lag-interface|l-interface|l3-interface-ipv6-address-list = /aai/v21/cloud-infrastructure/pservers/pserver/{hostname}/lag-interfaces/lag-interface/{interface-name}/l-interfaces/l-interface/{interface-name}/l3-interface-ipv6-address-list/{l3-interface-ipv6-address}
+pserver|lag-interface|l-interface|sriov-vfs = /aai/v21/cloud-infrastructure/pservers/pserver/{hostname}/lag-interfaces/lag-interface/{interface-name}/l-interfaces/l-interface/{interface-name}/sriov-vfs
+pserver|lag-interface|l-interface|sriov-vf = /aai/v21/cloud-infrastructure/pservers/pserver/{hostname}/lag-interfaces/lag-interface/{interface-name}/l-interfaces/l-interface/{interface-name}/sriov-vfs/sriov-vf/{pci-id}
+pserver|lag-interface|l-interface|vlans = /aai/v21/cloud-infrastructure/pservers/pserver/{hostname}/lag-interfaces/lag-interface/{interface-name}/l-interfaces/l-interface/{interface-name}/vlans
+pserver|lag-interface|l-interface|vlan = /aai/v21/cloud-infrastructure/pservers/pserver/{hostname}/lag-interfaces/lag-interface/{interface-name}/l-interfaces/l-interface/{interface-name}/vlans/vlan/{vlan-interface}
+pserver|lag-interface|l-interface|vlan|l3-interface-ipv4-address-list = /aai/v21/cloud-infrastructure/pservers/pserver/{hostname}/lag-interfaces/lag-interface/{interface-name}/l-interfaces/l-interface/{interface-name}/vlans/vlan/{vlan-interface}/l3-interface-ipv4-address-list/{l3-interface-ipv4-address}
+pserver|lag-interface|l-interface|vlan|l3-interface-ipv6-address-list = /aai/v21/cloud-infrastructure/pservers/pserver/{hostname}/lag-interfaces/lag-interface/{interface-name}/l-interfaces/l-interface/{interface-name}/vlans/vlan/{vlan-interface}/l3-interface-ipv6-address-list/{l3-interface-ipv6-address}
+pserver|p-interfaces = /aai/v21/cloud-infrastructure/pservers/pserver/{hostname}/p-interfaces
+pserver|p-interface = /aai/v21/cloud-infrastructure/pservers/pserver/{hostname}/p-interfaces/p-interface/{interface-name}
+pserver|p-interface|l-interfaces = /aai/v21/cloud-infrastructure/pservers/pserver/{hostname}/p-interfaces/p-interface/{interface-name}/l-interfaces
+pserver|p-interface|l-interface = /aai/v21/cloud-infrastructure/pservers/pserver/{hostname}/p-interfaces/p-interface/{interface-name}/l-interfaces/l-interface/{interface-name}
+pserver|p-interface|l-interface|l3-interface-ipv4-address-list = /aai/v21/cloud-infrastructure/pservers/pserver/{hostname}/p-interfaces/p-interface/{interface-name}/l-interfaces/l-interface/{interface-name}/l3-interface-ipv4-address-list/{l3-interface-ipv4-address}
+pserver|p-interface|l-interface|l3-interface-ipv6-address-list = /aai/v21/cloud-infrastructure/pservers/pserver/{hostname}/p-interfaces/p-interface/{interface-name}/l-interfaces/l-interface/{interface-name}/l3-interface-ipv6-address-list/{l3-interface-ipv6-address}
+pserver|p-interface|l-interface|sriov-vfs = /aai/v21/cloud-infrastructure/pservers/pserver/{hostname}/p-interfaces/p-interface/{interface-name}/l-interfaces/l-interface/{interface-name}/sriov-vfs
+pserver|p-interface|l-interface|sriov-vf = /aai/v21/cloud-infrastructure/pservers/pserver/{hostname}/p-interfaces/p-interface/{interface-name}/l-interfaces/l-interface/{interface-name}/sriov-vfs/sriov-vf/{pci-id}
+pserver|p-interface|l-interface|vlans = /aai/v21/cloud-infrastructure/pservers/pserver/{hostname}/p-interfaces/p-interface/{interface-name}/l-interfaces/l-interface/{interface-name}/vlans
+pserver|p-interface|l-interface|vlan = /aai/v21/cloud-infrastructure/pservers/pserver/{hostname}/p-interfaces/p-interface/{interface-name}/l-interfaces/l-interface/{interface-name}/vlans/vlan/{vlan-interface}
+pserver|p-interface|l-interface|vlan|l3-interface-ipv4-address-list = /aai/v21/cloud-infrastructure/pservers/pserver/{hostname}/p-interfaces/p-interface/{interface-name}/l-interfaces/l-interface/{interface-name}/vlans/vlan/{vlan-interface}/l3-interface-ipv4-address-list/{l3-interface-ipv4-address}
+pserver|p-interface|l-interface|vlan|l3-interface-ipv6-address-list = /aai/v21/cloud-infrastructure/pservers/pserver/{hostname}/p-interfaces/p-interface/{interface-name}/l-interfaces/l-interface/{interface-name}/vlans/vlan/{vlan-interface}/l3-interface-ipv6-address-list/{l3-interface-ipv6-address}
+pserver|p-interface|sriov-pfs = /aai/v21/cloud-infrastructure/pservers/pserver/{hostname}/p-interfaces/p-interface/{interface-name}/sriov-pfs
+pserver|p-interface|sriov-pf = /aai/v21/cloud-infrastructure/pservers/pserver/{hostname}/p-interfaces/p-interface/{interface-name}/sriov-pfs/sriov-pf/{pf-pci-id}
+virtual-data-centers = /aai/v21/cloud-infrastructure/virtual-data-centers
+virtual-data-center = /aai/v21/cloud-infrastructure/virtual-data-centers/virtual-data-center/{vdc-id}
+connectors = /aai/v21/business/connectors
+connector = /aai/v21/business/connectors/connector/{resource-instance-id}
+connector|metadata = /aai/v21/business/connectors/connector/{resource-instance-id}/metadata
+connector|metadatum = /aai/v21/business/connectors/connector/{resource-instance-id}/metadata/metadatum/{metaname}
+customers = /aai/v21/business/customers
+customer = /aai/v21/business/customers/customer/{global-customer-id}
+customer|service-subscriptions = /aai/v21/business/customers/customer/{global-customer-id}/service-subscriptions
+customer|service-subscription = /aai/v21/business/customers/customer/{global-customer-id}/service-subscriptions/service-subscription/{service-type}
+customer|service-subscription|service-instances = /aai/v21/business/customers/customer/{global-customer-id}/service-subscriptions/service-subscription/{service-type}/service-instances
+customer|service-subscription|service-instance = /aai/v21/business/customers/customer/{global-customer-id}/service-subscriptions/service-subscription/{service-type}/service-instances/service-instance/{service-instance-id}
+customer|service-subscription|service-instance|allotted-resources = /aai/v21/business/customers/customer/{global-customer-id}/service-subscriptions/service-subscription/{service-type}/service-instances/service-instance/{service-instance-id}/allotted-resources
+customer|service-subscription|service-instance|allotted-resource = /aai/v21/business/customers/customer/{global-customer-id}/service-subscriptions/service-subscription/{service-type}/service-instances/service-instance/{service-instance-id}/allotted-resources/allotted-resource/{id}
+customer|service-subscription|service-instance|allotted-resource|tunnel-xconnects = /aai/v21/business/customers/customer/{global-customer-id}/service-subscriptions/service-subscription/{service-type}/service-instances/service-instance/{service-instance-id}/allotted-resources/allotted-resource/{id}/tunnel-xconnects
+customer|service-subscription|service-instance|allotted-resource|tunnel-xconnect = /aai/v21/business/customers/customer/{global-customer-id}/service-subscriptions/service-subscription/{service-type}/service-instances/service-instance/{service-instance-id}/allotted-resources/allotted-resource/{id}/tunnel-xconnects/tunnel-xconnect/{id}
+customer|service-subscription|service-instance|metadata = /aai/v21/business/customers/customer/{global-customer-id}/service-subscriptions/service-subscription/{service-type}/service-instances/service-instance/{service-instance-id}/metadata
+customer|service-subscription|service-instance|metadatum = /aai/v21/business/customers/customer/{global-customer-id}/service-subscriptions/service-subscription/{service-type}/service-instances/service-instance/{service-instance-id}/metadata/metadatum/{metaname}
+configurations = /aai/v21/network/configurations
+configuration = /aai/v21/network/configurations/configuration/{configuration-id}
+configuration|evcs = /aai/v21/network/configurations/configuration/{configuration-id}/evcs
+configuration|evc = /aai/v21/network/configurations/configuration/{configuration-id}/evcs/evc/{evc-id}
+configuration|forwarder-evcs = /aai/v21/network/configurations/configuration/{configuration-id}/forwarder-evcs
+configuration|forwarder-evc = /aai/v21/network/configurations/configuration/{configuration-id}/forwarder-evcs/forwarder-evc/{forwarder-evc-id}
+configuration|metadata = /aai/v21/network/configurations/configuration/{configuration-id}/metadata
+configuration|metadatum = /aai/v21/network/configurations/configuration/{configuration-id}/metadata/metadatum/{metaname}
+connectivities = /aai/v21/network/connectivities
+connectivity = /aai/v21/network/connectivities/connectivity/{connectivity-id}
+devices = /aai/v21/network/devices
+device = /aai/v21/network/devices/device/{device-id}
+esr-thirdparty-sdnc = /aai/v21/external-system/esr-thirdparty-sdnc-list/esr-thirdparty-sdnc/{thirdparty-sdnc-id}
+esr-thirdparty-sdnc-list = /aai/v21/external-system/esr-thirdparty-sdnc-list
+forwarding-paths = /aai/v21/network/forwarding-paths
+forwarding-path = /aai/v21/network/forwarding-paths/forwarding-path/{forwarding-path-id}
+forwarding-path|forwarders = /aai/v21/network/forwarding-paths/forwarding-path/{forwarding-path-id}/forwarders
+forwarding-path|forwarder = /aai/v21/network/forwarding-paths/forwarding-path/{forwarding-path-id}/forwarders/forwarder/{sequence}
+generic-vnfs = /aai/v21/network/generic-vnfs
+generic-vnf = /aai/v21/network/generic-vnfs/generic-vnf/{vnf-id}
+generic-vnf|entitlements = /aai/v21/network/generic-vnfs/generic-vnf/{vnf-id}/entitlements
+generic-vnf|entitlement = /aai/v21/network/generic-vnfs/generic-vnf/{vnf-id}/entitlements/entitlement/{group-uuid}/{resource-uuid}
+generic-vnf|l-interfaces = /aai/v21/network/generic-vnfs/generic-vnf/{vnf-id}/l-interfaces
+generic-vnf|l-interface = /aai/v21/network/generic-vnfs/generic-vnf/{vnf-id}/l-interfaces/l-interface/{interface-name}
+generic-vnf|l-interface|l3-interface-ipv4-address-list = /aai/v21/network/generic-vnfs/generic-vnf/{vnf-id}/l-interfaces/l-interface/{interface-name}/l3-interface-ipv4-address-list/{l3-interface-ipv4-address}
+generic-vnf|l-interface|l3-interface-ipv6-address-list = /aai/v21/network/generic-vnfs/generic-vnf/{vnf-id}/l-interfaces/l-interface/{interface-name}/l3-interface-ipv6-address-list/{l3-interface-ipv6-address}
+generic-vnf|l-interface|sriov-vfs = /aai/v21/network/generic-vnfs/generic-vnf/{vnf-id}/l-interfaces/l-interface/{interface-name}/sriov-vfs
+generic-vnf|l-interface|sriov-vf = /aai/v21/network/generic-vnfs/generic-vnf/{vnf-id}/l-interfaces/l-interface/{interface-name}/sriov-vfs/sriov-vf/{pci-id}
+generic-vnf|l-interface|vlans = /aai/v21/network/generic-vnfs/generic-vnf/{vnf-id}/l-interfaces/l-interface/{interface-name}/vlans
+generic-vnf|l-interface|vlan = /aai/v21/network/generic-vnfs/generic-vnf/{vnf-id}/l-interfaces/l-interface/{interface-name}/vlans/vlan/{vlan-interface}
+generic-vnf|l-interface|vlan|l3-interface-ipv4-address-list = /aai/v21/network/generic-vnfs/generic-vnf/{vnf-id}/l-interfaces/l-interface/{interface-name}/vlans/vlan/{vlan-interface}/l3-interface-ipv4-address-list/{l3-interface-ipv4-address}
+generic-vnf|l-interface|vlan|l3-interface-ipv6-address-list = /aai/v21/network/generic-vnfs/generic-vnf/{vnf-id}/l-interfaces/l-interface/{interface-name}/vlans/vlan/{vlan-interface}/l3-interface-ipv6-address-list/{l3-interface-ipv6-address}
+generic-vnf|lag-interfaces = /aai/v21/network/generic-vnfs/generic-vnf/{vnf-id}/lag-interfaces
+generic-vnf|lag-interface = /aai/v21/network/generic-vnfs/generic-vnf/{vnf-id}/lag-interfaces/lag-interface/{interface-name}
+generic-vnf|lag-interface|l-interfaces = /aai/v21/network/generic-vnfs/generic-vnf/{vnf-id}/lag-interfaces/lag-interface/{interface-name}/l-interfaces
+generic-vnf|lag-interface|l-interface = /aai/v21/network/generic-vnfs/generic-vnf/{vnf-id}/lag-interfaces/lag-interface/{interface-name}/l-interfaces/l-interface/{interface-name}
+generic-vnf|lag-interface|l-interface|l3-interface-ipv4-address-list = /aai/v21/network/generic-vnfs/generic-vnf/{vnf-id}/lag-interfaces/lag-interface/{interface-name}/l-interfaces/l-interface/{interface-name}/l3-interface-ipv4-address-list/{l3-interface-ipv4-address}
+generic-vnf|lag-interface|l-interface|l3-interface-ipv6-address-list = /aai/v21/network/generic-vnfs/generic-vnf/{vnf-id}/lag-interfaces/lag-interface/{interface-name}/l-interfaces/l-interface/{interface-name}/l3-interface-ipv6-address-list/{l3-interface-ipv6-address}
+generic-vnf|lag-interface|l-interface|sriov-vfs = /aai/v21/network/generic-vnfs/generic-vnf/{vnf-id}/lag-interfaces/lag-interface/{interface-name}/l-interfaces/l-interface/{interface-name}/sriov-vfs
+generic-vnf|lag-interface|l-interface|sriov-vf = /aai/v21/network/generic-vnfs/generic-vnf/{vnf-id}/lag-interfaces/lag-interface/{interface-name}/l-interfaces/l-interface/{interface-name}/sriov-vfs/sriov-vf/{pci-id}
+generic-vnf|lag-interface|l-interface|vlans = /aai/v21/network/generic-vnfs/generic-vnf/{vnf-id}/lag-interfaces/lag-interface/{interface-name}/l-interfaces/l-interface/{interface-name}/vlans
+generic-vnf|lag-interface|l-interface|vlan = /aai/v21/network/generic-vnfs/generic-vnf/{vnf-id}/lag-interfaces/lag-interface/{interface-name}/l-interfaces/l-interface/{interface-name}/vlans/vlan/{vlan-interface}
+generic-vnf|lag-interface|l-interface|vlan|l3-interface-ipv4-address-list = /aai/v21/network/generic-vnfs/generic-vnf/{vnf-id}/lag-interfaces/lag-interface/{interface-name}/l-interfaces/l-interface/{interface-name}/vlans/vlan/{vlan-interface}/l3-interface-ipv4-address-list/{l3-interface-ipv4-address}
+generic-vnf|lag-interface|l-interface|vlan|l3-interface-ipv6-address-list = /aai/v21/network/generic-vnfs/generic-vnf/{vnf-id}/lag-interfaces/lag-interface/{interface-name}/l-interfaces/l-interface/{interface-name}/vlans/vlan/{vlan-interface}/l3-interface-ipv6-address-list/{l3-interface-ipv6-address}
+generic-vnf|licenses = /aai/v21/network/generic-vnfs/generic-vnf/{vnf-id}/licenses
+generic-vnf|license = /aai/v21/network/generic-vnfs/generic-vnf/{vnf-id}/licenses/license/{group-uuid}/{resource-uuid}
+generic-vnf|vf-modules = /aai/v21/network/generic-vnfs/generic-vnf/{vnf-id}/vf-modules
+generic-vnf|vf-module = /aai/v21/network/generic-vnfs/generic-vnf/{vnf-id}/vf-modules/vf-module/{vf-module-id}
+instance-groups = /aai/v21/network/instance-groups
+instance-group = /aai/v21/network/instance-groups/instance-group/{id}
+interlayer-attachments = /aai/v21/network/interlayer-attachments
+interlayer-attachment = /aai/v21/network/interlayer-attachments/interlayer-attachment/{id}
+ipsec-configurations = /aai/v21/network/ipsec-configurations
+ipsec-configuration = /aai/v21/network/ipsec-configurations/ipsec-configuration/{ipsec-configuration-id}
+ipsec-configuration|vig-servers = /aai/v21/network/ipsec-configurations/ipsec-configuration/{ipsec-configuration-id}/vig-servers
+ipsec-configuration|vig-server = /aai/v21/network/ipsec-configurations/ipsec-configuration/{ipsec-configuration-id}/vig-servers/vig-server/{vig-address-type}
+l3-networks = /aai/v21/network/l3-networks
+l3-network = /aai/v21/network/l3-networks/l3-network/{network-id}
+l3-network|ctag-assignments = /aai/v21/network/l3-networks/l3-network/{network-id}/ctag-assignments
+l3-network|ctag-assignment = /aai/v21/network/l3-networks/l3-network/{network-id}/ctag-assignments/ctag-assignment/{vlan-id-inner}
+l3-network|segmentation-assignments = /aai/v21/network/l3-networks/l3-network/{network-id}/segmentation-assignments
+l3-network|segmentation-assignment = /aai/v21/network/l3-networks/l3-network/{network-id}/segmentation-assignments/segmentation-assignment/{segmentation-id}
+l3-network|subnets = /aai/v21/network/l3-networks/l3-network/{network-id}/subnets
+l3-network|subnet = /aai/v21/network/l3-networks/l3-network/{network-id}/subnets/subnet/{subnet-id}
+l3-network|subnet|host-routes = /aai/v21/network/l3-networks/l3-network/{network-id}/subnets/subnet/{subnet-id}/host-routes
+l3-network|subnet|host-route = /aai/v21/network/l3-networks/l3-network/{network-id}/subnets/subnet/{subnet-id}/host-routes/host-route/{host-route-id}
+label-restrictions = /aai/v21/network/label-restrictions
+label-restriction = /aai/v21/network/label-restrictions/label-restriction/{id}
+lag-links = /aai/v21/network/lag-links
+lag-link = /aai/v21/network/lag-links/lag-link/{link-name}
+lines-of-business = /aai/v21/business/lines-of-business
+line-of-business = /aai/v21/business/lines-of-business/line-of-business/{line-of-business-name}
+logical-links = /aai/v21/network/logical-links
+logical-link = /aai/v21/network/logical-links/logical-link/{link-name}
+models = /aai/v21/service-design-and-creation/models
+model = /aai/v21/service-design-and-creation/models/model/{model-invariant-id}
+model|model-vers = /aai/v21/service-design-and-creation/models/model/{model-invariant-id}/model-vers
+model|model-ver = /aai/v21/service-design-and-creation/models/model/{model-invariant-id}/model-vers/model-ver/{model-version-id}
+model|model-ver|metadata = /aai/v21/service-design-and-creation/models/model/{model-invariant-id}/model-vers/model-ver/{model-version-id}/metadata
+model|model-ver|metadatum = /aai/v21/service-design-and-creation/models/model/{model-invariant-id}/model-vers/model-ver/{model-version-id}/metadata/metadatum/{metaname}
+model|model-ver|model-elements = /aai/v21/service-design-and-creation/models/model/{model-invariant-id}/model-vers/model-ver/{model-version-id}/model-elements
+model|model-ver|model-element = /aai/v21/service-design-and-creation/models/model/{model-invariant-id}/model-vers/model-ver/{model-version-id}/model-elements/model-element/{model-element-uuid}
+model|model-ver|model-element|model-constraints = /aai/v21/service-design-and-creation/models/model/{model-invariant-id}/model-vers/model-ver/{model-version-id}/model-elements/model-element/{model-element-uuid}/model-constraints
+model|model-ver|model-element|model-constraint = /aai/v21/service-design-and-creation/models/model/{model-invariant-id}/model-vers/model-ver/{model-version-id}/model-elements/model-element/{model-element-uuid}/model-constraints/model-constraint/{model-constraint-uuid}
+model|model-ver|model-element|model-constraint|constrained-element-sets = /aai/v21/service-design-and-creation/models/model/{model-invariant-id}/model-vers/model-ver/{model-version-id}/model-elements/model-element/{model-element-uuid}/model-constraints/model-constraint/{model-constraint-uuid}/constrained-element-sets
+model|model-ver|model-element|model-constraint|constrained-element-set = /aai/v21/service-design-and-creation/models/model/{model-invariant-id}/model-vers/model-ver/{model-version-id}/model-elements/model-element/{model-element-uuid}/model-constraints/model-constraint/{model-constraint-uuid}/constrained-element-sets/constrained-element-set/{constrained-element-set-uuid}
+model|model-ver|model-element|model-constraint|constrained-element-set|element-choice-sets = /aai/v21/service-design-and-creation/models/model/{model-invariant-id}/model-vers/model-ver/{model-version-id}/model-elements/model-element/{model-element-uuid}/model-constraints/model-constraint/{model-constraint-uuid}/constrained-element-sets/constrained-element-set/{constrained-element-set-uuid}/element-choice-sets
+model|model-ver|model-element|model-constraint|constrained-element-set|element-choice-set = /aai/v21/service-design-and-creation/models/model/{model-invariant-id}/model-vers/model-ver/{model-version-id}/model-elements/model-element/{model-element-uuid}/model-constraints/model-constraint/{model-constraint-uuid}/constrained-element-sets/constrained-element-set/{constrained-element-set-uuid}/element-choice-sets/element-choice-set/{element-choice-set-uuid}
+multicast-configurations = /aai/v21/network/multicast-configurations
+multicast-configuration = /aai/v21/network/multicast-configurations/multicast-configuration/{multicast-configuration-id}
+named-queries = /aai/v21/service-design-and-creation/named-queries
+named-query = /aai/v21/service-design-and-creation/named-queries/named-query/{named-query-uuid}
+named-query|named-query-elements = /aai/v21/service-design-and-creation/named-queries/named-query/{named-query-uuid}/named-query-elements
+named-query|named-query-element = /aai/v21/service-design-and-creation/named-queries/named-query/{named-query-uuid}/named-query-elements/named-query-element/{named-query-element-uuid}
+named-query|named-query-element|property-constraints = /aai/v21/service-design-and-creation/named-queries/named-query/{named-query-uuid}/named-query-elements/named-query-element/{named-query-element-uuid}/property-constraints
+named-query|named-query-element|property-constraint = /aai/v21/service-design-and-creation/named-queries/named-query/{named-query-uuid}/named-query-elements/named-query-element/{named-query-element-uuid}/property-constraints/property-constraint/{property-constraint-uuid}
+named-query|named-query-element|related-lookups = /aai/v21/service-design-and-creation/named-queries/named-query/{named-query-uuid}/named-query-elements/named-query-element/{named-query-element-uuid}/related-lookups
+named-query|named-query-element|related-lookup = /aai/v21/service-design-and-creation/named-queries/named-query/{named-query-uuid}/named-query-elements/named-query-element/{named-query-element-uuid}/related-lookups/related-lookup/{related-lookup-uuid}
+network-policies = /aai/v21/network/network-policies
+network-policy = /aai/v21/network/network-policies/network-policy/{network-policy-id}
+network-resources = /aai/v21/network/network-resources
+network-resource = /aai/v21/network/network-resources/network-resource/{network-id}
+newvces = /aai/v21/network/newvces
+newvce = /aai/v21/network/newvces/newvce/{vnf-id2}
+newvce|l-interfaces = /aai/v21/network/newvces/newvce/{vnf-id2}/l-interfaces
+newvce|l-interface = /aai/v21/network/newvces/newvce/{vnf-id2}/l-interfaces/l-interface/{interface-name}
+newvce|l-interface|l3-interface-ipv4-address-list = /aai/v21/network/newvces/newvce/{vnf-id2}/l-interfaces/l-interface/{interface-name}/l3-interface-ipv4-address-list/{l3-interface-ipv4-address}
+newvce|l-interface|l3-interface-ipv6-address-list = /aai/v21/network/newvces/newvce/{vnf-id2}/l-interfaces/l-interface/{interface-name}/l3-interface-ipv6-address-list/{l3-interface-ipv6-address}
+newvce|l-interface|sriov-vfs = /aai/v21/network/newvces/newvce/{vnf-id2}/l-interfaces/l-interface/{interface-name}/sriov-vfs
+newvce|l-interface|sriov-vf = /aai/v21/network/newvces/newvce/{vnf-id2}/l-interfaces/l-interface/{interface-name}/sriov-vfs/sriov-vf/{pci-id}
+newvce|l-interface|vlans = /aai/v21/network/newvces/newvce/{vnf-id2}/l-interfaces/l-interface/{interface-name}/vlans
+newvce|l-interface|vlan = /aai/v21/network/newvces/newvce/{vnf-id2}/l-interfaces/l-interface/{interface-name}/vlans/vlan/{vlan-interface}
+newvce|l-interface|vlan|l3-interface-ipv4-address-list = /aai/v21/network/newvces/newvce/{vnf-id2}/l-interfaces/l-interface/{interface-name}/vlans/vlan/{vlan-interface}/l3-interface-ipv4-address-list/{l3-interface-ipv4-address}
+newvce|l-interface|vlan|l3-interface-ipv6-address-list = /aai/v21/network/newvces/newvce/{vnf-id2}/l-interfaces/l-interface/{interface-name}/vlans/vlan/{vlan-interface}/l3-interface-ipv6-address-list/{l3-interface-ipv6-address}
+owning-entities = /aai/v21/business/owning-entities
+owning-entity = /aai/v21/business/owning-entities/owning-entity/{owning-entity-id}
+physical-links = /aai/v21/network/physical-links
+physical-link = /aai/v21/network/physical-links/physical-link/{link-name}
+platforms = /aai/v21/business/platforms
+platform = /aai/v21/business/platforms/platform/{platform-name}
+pnfs = /aai/v21/network/pnfs
+pnf = /aai/v21/network/pnfs/pnf/{pnf-name}
+pnf|lag-interfaces = /aai/v21/network/pnfs/pnf/{pnf-name}/lag-interfaces
+pnf|lag-interface = /aai/v21/network/pnfs/pnf/{pnf-name}/lag-interfaces/lag-interface/{interface-name}
+pnf|lag-interface|l-interfaces = /aai/v21/network/pnfs/pnf/{pnf-name}/lag-interfaces/lag-interface/{interface-name}/l-interfaces
+pnf|lag-interface|l-interface = /aai/v21/network/pnfs/pnf/{pnf-name}/lag-interfaces/lag-interface/{interface-name}/l-interfaces/l-interface/{interface-name}
+pnf|lag-interface|l-interface|l3-interface-ipv4-address-list = /aai/v21/network/pnfs/pnf/{pnf-name}/lag-interfaces/lag-interface/{interface-name}/l-interfaces/l-interface/{interface-name}/l3-interface-ipv4-address-list/{l3-interface-ipv4-address}
+pnf|lag-interface|l-interface|l3-interface-ipv6-address-list = /aai/v21/network/pnfs/pnf/{pnf-name}/lag-interfaces/lag-interface/{interface-name}/l-interfaces/l-interface/{interface-name}/l3-interface-ipv6-address-list/{l3-interface-ipv6-address}
+pnf|lag-interface|l-interface|sriov-vfs = /aai/v21/network/pnfs/pnf/{pnf-name}/lag-interfaces/lag-interface/{interface-name}/l-interfaces/l-interface/{interface-name}/sriov-vfs
+pnf|lag-interface|l-interface|sriov-vf = /aai/v21/network/pnfs/pnf/{pnf-name}/lag-interfaces/lag-interface/{interface-name}/l-interfaces/l-interface/{interface-name}/sriov-vfs/sriov-vf/{pci-id}
+pnf|lag-interface|l-interface|vlans = /aai/v21/network/pnfs/pnf/{pnf-name}/lag-interfaces/lag-interface/{interface-name}/l-interfaces/l-interface/{interface-name}/vlans
+pnf|lag-interface|l-interface|vlan = /aai/v21/network/pnfs/pnf/{pnf-name}/lag-interfaces/lag-interface/{interface-name}/l-interfaces/l-interface/{interface-name}/vlans/vlan/{vlan-interface}
+pnf|lag-interface|l-interface|vlan|l3-interface-ipv4-address-list = /aai/v21/network/pnfs/pnf/{pnf-name}/lag-interfaces/lag-interface/{interface-name}/l-interfaces/l-interface/{interface-name}/vlans/vlan/{vlan-interface}/l3-interface-ipv4-address-list/{l3-interface-ipv4-address}
+pnf|lag-interface|l-interface|vlan|l3-interface-ipv6-address-list = /aai/v21/network/pnfs/pnf/{pnf-name}/lag-interfaces/lag-interface/{interface-name}/l-interfaces/l-interface/{interface-name}/vlans/vlan/{vlan-interface}/l3-interface-ipv6-address-list/{l3-interface-ipv6-address}
+pnf|p-interfaces = /aai/v21/network/pnfs/pnf/{pnf-name}/p-interfaces
+pnf|p-interface = /aai/v21/network/pnfs/pnf/{pnf-name}/p-interfaces/p-interface/{interface-name}
+pnf|p-interface|l-interfaces = /aai/v21/network/pnfs/pnf/{pnf-name}/p-interfaces/p-interface/{interface-name}/l-interfaces
+pnf|p-interface|l-interface = /aai/v21/network/pnfs/pnf/{pnf-name}/p-interfaces/p-interface/{interface-name}/l-interfaces/l-interface/{interface-name}
+pnf|p-interface|l-interface|l3-interface-ipv4-address-list = /aai/v21/network/pnfs/pnf/{pnf-name}/p-interfaces/p-interface/{interface-name}/l-interfaces/l-interface/{interface-name}/l3-interface-ipv4-address-list/{l3-interface-ipv4-address}
+pnf|p-interface|l-interface|l3-interface-ipv6-address-list = /aai/v21/network/pnfs/pnf/{pnf-name}/p-interfaces/p-interface/{interface-name}/l-interfaces/l-interface/{interface-name}/l3-interface-ipv6-address-list/{l3-interface-ipv6-address}
+pnf|p-interface|l-interface|sriov-vfs = /aai/v21/network/pnfs/pnf/{pnf-name}/p-interfaces/p-interface/{interface-name}/l-interfaces/l-interface/{interface-name}/sriov-vfs
+pnf|p-interface|l-interface|sriov-vf = /aai/v21/network/pnfs/pnf/{pnf-name}/p-interfaces/p-interface/{interface-name}/l-interfaces/l-interface/{interface-name}/sriov-vfs/sriov-vf/{pci-id}
+pnf|p-interface|l-interface|vlans = /aai/v21/network/pnfs/pnf/{pnf-name}/p-interfaces/p-interface/{interface-name}/l-interfaces/l-interface/{interface-name}/vlans
+pnf|p-interface|l-interface|vlan = /aai/v21/network/pnfs/pnf/{pnf-name}/p-interfaces/p-interface/{interface-name}/l-interfaces/l-interface/{interface-name}/vlans/vlan/{vlan-interface}
+pnf|p-interface|l-interface|vlan|l3-interface-ipv4-address-list = /aai/v21/network/pnfs/pnf/{pnf-name}/p-interfaces/p-interface/{interface-name}/l-interfaces/l-interface/{interface-name}/vlans/vlan/{vlan-interface}/l3-interface-ipv4-address-list/{l3-interface-ipv4-address}
+pnf|p-interface|l-interface|vlan|l3-interface-ipv6-address-list = /aai/v21/network/pnfs/pnf/{pnf-name}/p-interfaces/p-interface/{interface-name}/l-interfaces/l-interface/{interface-name}/vlans/vlan/{vlan-interface}/l3-interface-ipv6-address-list/{l3-interface-ipv6-address}
+pnf|p-interface|sriov-pfs = /aai/v21/network/pnfs/pnf/{pnf-name}/p-interfaces/p-interface/{interface-name}/sriov-pfs
+pnf|p-interface|sriov-pf = /aai/v21/network/pnfs/pnf/{pnf-name}/p-interfaces/p-interface/{interface-name}/sriov-pfs/sriov-pf/{pf-pci-id}
+projects = /aai/v21/business/projects
+project = /aai/v21/business/projects/project/{project-name}
+route-table-references = /aai/v21/network/route-table-references
+route-table-reference = /aai/v21/network/route-table-references/route-table-reference/{route-table-reference-id}
+sdwan-vpns = /aai/v21/network/sdwan-vpns
+sdwan-vpn = /aai/v21/network/sdwan-vpns/sdwan-vpn/{sdwan-vpn-id}
+service-capabilities = /aai/v21/service-design-and-creation/service-capabilities
+service-capability = /aai/v21/service-design-and-creation/service-capabilities/service-capability/{service-type}/{vnf-type}
+services = /aai/v21/service-design-and-creation/services
+service = /aai/v21/service-design-and-creation/services/service/{service-id}
+site-pair-sets = /aai/v21/network/site-pair-sets
+site-pair-set = /aai/v21/network/site-pair-sets/site-pair-set/{site-pair-set-id}
+site-pair-set|routing-instances = /aai/v21/network/site-pair-sets/site-pair-set/{site-pair-set-id}/routing-instances
+site-pair-set|routing-instance = /aai/v21/network/site-pair-sets/site-pair-set/{site-pair-set-id}/routing-instances/routing-instance/{routing-instance-id}
+site-pair-set|routing-instance|site-pairs = /aai/v21/network/site-pair-sets/site-pair-set/{site-pair-set-id}/routing-instances/routing-instance/{routing-instance-id}/site-pairs
+site-pair-set|routing-instance|site-pair = /aai/v21/network/site-pair-sets/site-pair-set/{site-pair-set-id}/routing-instances/routing-instance/{routing-instance-id}/site-pairs/site-pair/{site-pair-id}
+site-pair-set|routing-instance|site-pair|classes-of-service = /aai/v21/network/site-pair-sets/site-pair-set/{site-pair-set-id}/routing-instances/routing-instance/{routing-instance-id}/site-pairs/site-pair/{site-pair-id}/classes-of-service
+site-pair-set|routing-instance|site-pair|class-of-service = /aai/v21/network/site-pair-sets/site-pair-set/{site-pair-set-id}/routing-instances/routing-instance/{routing-instance-id}/site-pairs/site-pair/{site-pair-id}/classes-of-service/class-of-service/{cos}
+site-resources = /aai/v21/network/site-resources
+site-resource = /aai/v21/network/site-resources/site-resource/{site-resource-id}
+te-link-attributes = /aai/v21/network/te-link-attributes
+te-link-attribute = /aai/v21/network/te-link-attributes/te-link-attribute/{id}
+tunnel-termination-points = /aai/v21/network/tunnel-termination-points
+tunnel-termination-point = /aai/v21/network/tunnel-termination-points/tunnel-termination-point/{ttp-id}
+unis = /aai/v21/network/unis
+uni = /aai/v21/network/unis/uni/{id}
+vces = /aai/v21/network/vces
+vce = /aai/v21/network/vces/vce/{vnf-id}
+vce|entitlements = /aai/v21/network/vces/vce/{vnf-id}/entitlements
+vce|entitlement = /aai/v21/network/vces/vce/{vnf-id}/entitlements/entitlement/{group-uuid}/{resource-uuid}
+vce|licenses = /aai/v21/network/vces/vce/{vnf-id}/licenses
+vce|license = /aai/v21/network/vces/vce/{vnf-id}/licenses/license/{group-uuid}/{resource-uuid}
+vce|port-groups = /aai/v21/network/vces/vce/{vnf-id}/port-groups
+vce|port-group = /aai/v21/network/vces/vce/{vnf-id}/port-groups/port-group/{interface-id}
+vce|port-group|cvlan-tags = /aai/v21/network/vces/vce/{vnf-id}/port-groups/port-group/{interface-id}/cvlan-tags
+vce|port-group|cvlan-tag-entry = /aai/v21/network/vces/vce/{vnf-id}/port-groups/port-group/{interface-id}/cvlan-tags/cvlan-tag-entry/{cvlan-tag}
+vnf-images = /aai/v21/service-design-and-creation/vnf-images
+vnf-image = /aai/v21/service-design-and-creation/vnf-images/vnf-image/{vnf-image-uuid}
+vnfcs = /aai/v21/network/vnfcs
+vnfc = /aai/v21/network/vnfcs/vnfc/{vnfc-name}
+vnfc|cps = /aai/v21/network/vnfcs/vnfc/{vnfc-name}/cps
+vnfc|cp = /aai/v21/network/vnfcs/vnfc/{vnfc-name}/cps/cp/{cp-instance-id}
+vnfc|cp|l3-interface-ipv4-address-list = /aai/v21/network/vnfcs/vnfc/{vnfc-name}/cps/cp/{cp-instance-id}/l3-interface-ipv4-address-list/{l3-interface-ipv4-address}
+vnfc|cp|l3-interface-ipv6-address-list = /aai/v21/network/vnfcs/vnfc/{vnfc-name}/cps/cp/{cp-instance-id}/l3-interface-ipv6-address-list/{l3-interface-ipv6-address}
+vnfc|l3-interface-ipv4-address-list = /aai/v21/network/vnfcs/vnfc/{vnfc-name}/l3-interface-ipv4-address-list/{l3-interface-ipv4-address}
+vnfc|l3-interface-ipv6-address-list = /aai/v21/network/vnfcs/vnfc/{vnfc-name}/l3-interface-ipv6-address-list/{l3-interface-ipv6-address}
+vpls-pes = /aai/v21/network/vpls-pes
+vpls-pe = /aai/v21/network/vpls-pes/vpls-pe/{equipment-name}
+vpls-pe|lag-interfaces = /aai/v21/network/vpls-pes/vpls-pe/{equipment-name}/lag-interfaces
+vpls-pe|lag-interface = /aai/v21/network/vpls-pes/vpls-pe/{equipment-name}/lag-interfaces/lag-interface/{interface-name}
+vpls-pe|lag-interface|l-interfaces = /aai/v21/network/vpls-pes/vpls-pe/{equipment-name}/lag-interfaces/lag-interface/{interface-name}/l-interfaces
+vpls-pe|lag-interface|l-interface = /aai/v21/network/vpls-pes/vpls-pe/{equipment-name}/lag-interfaces/lag-interface/{interface-name}/l-interfaces/l-interface/{interface-name}
+vpls-pe|lag-interface|l-interface|l3-interface-ipv4-address-list = /aai/v21/network/vpls-pes/vpls-pe/{equipment-name}/lag-interfaces/lag-interface/{interface-name}/l-interfaces/l-interface/{interface-name}/l3-interface-ipv4-address-list/{l3-interface-ipv4-address}
+vpls-pe|lag-interface|l-interface|l3-interface-ipv6-address-list = /aai/v21/network/vpls-pes/vpls-pe/{equipment-name}/lag-interfaces/lag-interface/{interface-name}/l-interfaces/l-interface/{interface-name}/l3-interface-ipv6-address-list/{l3-interface-ipv6-address}
+vpls-pe|lag-interface|l-interface|sriov-vfs = /aai/v21/network/vpls-pes/vpls-pe/{equipment-name}/lag-interfaces/lag-interface/{interface-name}/l-interfaces/l-interface/{interface-name}/sriov-vfs
+vpls-pe|lag-interface|l-interface|sriov-vf = /aai/v21/network/vpls-pes/vpls-pe/{equipment-name}/lag-interfaces/lag-interface/{interface-name}/l-interfaces/l-interface/{interface-name}/sriov-vfs/sriov-vf/{pci-id}
+vpls-pe|lag-interface|l-interface|vlans = /aai/v21/network/vpls-pes/vpls-pe/{equipment-name}/lag-interfaces/lag-interface/{interface-name}/l-interfaces/l-interface/{interface-name}/vlans
+vpls-pe|lag-interface|l-interface|vlan = /aai/v21/network/vpls-pes/vpls-pe/{equipment-name}/lag-interfaces/lag-interface/{interface-name}/l-interfaces/l-interface/{interface-name}/vlans/vlan/{vlan-interface}
+vpls-pe|lag-interface|l-interface|vlan|l3-interface-ipv4-address-list = /aai/v21/network/vpls-pes/vpls-pe/{equipment-name}/lag-interfaces/lag-interface/{interface-name}/l-interfaces/l-interface/{interface-name}/vlans/vlan/{vlan-interface}/l3-interface-ipv4-address-list/{l3-interface-ipv4-address}
+vpls-pe|lag-interface|l-interface|vlan|l3-interface-ipv6-address-list = /aai/v21/network/vpls-pes/vpls-pe/{equipment-name}/lag-interfaces/lag-interface/{interface-name}/l-interfaces/l-interface/{interface-name}/vlans/vlan/{vlan-interface}/l3-interface-ipv6-address-list/{l3-interface-ipv6-address}
+vpls-pe|p-interfaces = /aai/v21/network/vpls-pes/vpls-pe/{equipment-name}/p-interfaces
+vpls-pe|p-interface = /aai/v21/network/vpls-pes/vpls-pe/{equipment-name}/p-interfaces/p-interface/{interface-name}
+vpls-pe|p-interface|l-interfaces = /aai/v21/network/vpls-pes/vpls-pe/{equipment-name}/p-interfaces/p-interface/{interface-name}/l-interfaces
+vpls-pe|p-interface|l-interface = /aai/v21/network/vpls-pes/vpls-pe/{equipment-name}/p-interfaces/p-interface/{interface-name}/l-interfaces/l-interface/{interface-name}
+vpls-pe|p-interface|l-interface|l3-interface-ipv4-address-list = /aai/v21/network/vpls-pes/vpls-pe/{equipment-name}/p-interfaces/p-interface/{interface-name}/l-interfaces/l-interface/{interface-name}/l3-interface-ipv4-address-list/{l3-interface-ipv4-address}
+vpls-pe|p-interface|l-interface|l3-interface-ipv6-address-list = /aai/v21/network/vpls-pes/vpls-pe/{equipment-name}/p-interfaces/p-interface/{interface-name}/l-interfaces/l-interface/{interface-name}/l3-interface-ipv6-address-list/{l3-interface-ipv6-address}
+vpls-pe|p-interface|l-interface|sriov-vfs = /aai/v21/network/vpls-pes/vpls-pe/{equipment-name}/p-interfaces/p-interface/{interface-name}/l-interfaces/l-interface/{interface-name}/sriov-vfs
+vpls-pe|p-interface|l-interface|sriov-vf = /aai/v21/network/vpls-pes/vpls-pe/{equipment-name}/p-interfaces/p-interface/{interface-name}/l-interfaces/l-interface/{interface-name}/sriov-vfs/sriov-vf/{pci-id}
+vpls-pe|p-interface|l-interface|vlans = /aai/v21/network/vpls-pes/vpls-pe/{equipment-name}/p-interfaces/p-interface/{interface-name}/l-interfaces/l-interface/{interface-name}/vlans
+vpls-pe|p-interface|l-interface|vlan = /aai/v21/network/vpls-pes/vpls-pe/{equipment-name}/p-interfaces/p-interface/{interface-name}/l-interfaces/l-interface/{interface-name}/vlans/vlan/{vlan-interface}
+vpls-pe|p-interface|l-interface|vlan|l3-interface-ipv4-address-list = /aai/v21/network/vpls-pes/vpls-pe/{equipment-name}/p-interfaces/p-interface/{interface-name}/l-interfaces/l-interface/{interface-name}/vlans/vlan/{vlan-interface}/l3-interface-ipv4-address-list/{l3-interface-ipv4-address}
+vpls-pe|p-interface|l-interface|vlan|l3-interface-ipv6-address-list = /aai/v21/network/vpls-pes/vpls-pe/{equipment-name}/p-interfaces/p-interface/{interface-name}/l-interfaces/l-interface/{interface-name}/vlans/vlan/{vlan-interface}/l3-interface-ipv6-address-list/{l3-interface-ipv6-address}
+vpls-pe|p-interface|sriov-pfs = /aai/v21/network/vpls-pes/vpls-pe/{equipment-name}/p-interfaces/p-interface/{interface-name}/sriov-pfs
+vpls-pe|p-interface|sriov-pf = /aai/v21/network/vpls-pes/vpls-pe/{equipment-name}/p-interfaces/p-interface/{interface-name}/sriov-pfs/sriov-pf/{pf-pci-id}
+vpn-bindings = /aai/v21/network/vpn-bindings
+vpn-binding = /aai/v21/network/vpn-bindings/vpn-binding/{vpn-id}
+vpn-binding|route-targets = /aai/v21/network/vpn-bindings/vpn-binding/{vpn-id}/route-targets
+vpn-binding|route-target = /aai/v21/network/vpn-bindings/vpn-binding/{vpn-id}/route-targets/route-target/{global-route-target}/{route-target-role}
+wan-port-configs = /aai/v21/network/wan-port-configs
+wan-port-config = /aai/v21/network/wan-port-configs/wan-port-config/{wan-port-config-id}
+lan-port-configs = /aai/v21/network/lan-port-configs
+lan-port-config = /aai/v21/network/lan-port-configs/lan-port-config/{lan-port-config-id}
+zones = /aai/v21/network/zones
+zone = /aai/v21/network/zones/zone/{zone-id}
+network-routes = /aai/v21/network/network-routes
+network-route = /aai/v21/network/network-routes/network-route/{route-id}
diff --git a/adaptors/aai-service/provider/src/main/resources/aai-schema-bindings.xjb b/adaptors/aai-service/provider/src/main/resources/aai-schema-bindings.xjb
new file mode 100755
index 000000000..996a74afd
--- /dev/null
+++ b/adaptors/aai-service/provider/src/main/resources/aai-schema-bindings.xjb
@@ -0,0 +1,11 @@
+<jxb:bindings version="1.0"
+ xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
+ jxb:extensionBindingPrefixes="xjc">
+ <jxb:bindings schemaLocation="aai_schema_v21.xsd" node="/xs:schema">
+ <jxb:globalBindings>
+ <xjc:superInterface name="org.onap.ccsdk.sli.adaptors.aai.data.AAIDatum"/>
+ </jxb:globalBindings>
+ </jxb:bindings>
+</jxb:bindings>
diff --git a/adaptors/aai-service/provider/src/main/resources/aai_schema_v21.xsd b/adaptors/aai-service/provider/src/main/resources/aai_schema_v21.xsd
new file mode 100644
index 000000000..afdda3dc5
--- /dev/null
+++ b/adaptors/aai-service/provider/src/main/resources/aai_schema_v21.xsd
@@ -0,0 +1,14837 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<xs:schema elementFormDefault="qualified" version="1.0" targetNamespace="http://org.onap.aai.inventory/v21" xmlns:tns="http://org.onap.aai.inventory/v21" xmlns:xs="http://www.w3.org/2001/XMLSchema"
+xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
+ jaxb:version="2.1"
+ xmlns:annox="http://annox.dev.java.net"
+ jaxb:extensionBindingPrefixes="annox">
+
+ <xs:element name="inventory-item-data">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="property-name" type="xs:string" minOccurs="0"/>
+ <xs:element name="property-value" type="xs:string" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="inventory-item">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="inventory-item-type" type="xs:string" minOccurs="0"/>
+ <xs:element name="inventory-item-link" type="xs:string" minOccurs="0"/>
+ <xs:element ref="tns:inventory-item-data" minOccurs="0" maxOccurs="5000"/>
+ <xs:element ref="tns:tagged-inventory-item-list" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="tagged-inventory-item-list">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="tns:inventory-item" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="edge-tag-query-result">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="tns:tagged-inventory-item-list" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="start-node-filter">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="property-name" type="xs:string" minOccurs="0"/>
+ <xs:element name="property-value" type="xs:string" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="include-node-filter">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="include-node-type" type="xs:string" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="secondary-filter">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="property-name" type="xs:string" minOccurs="0"/>
+ <xs:element name="filter-type" type="xs:string" minOccurs="0"/>
+ <xs:element name="property-value" type="xs:string" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="edge-tag-query-request">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="edge-tag" type="xs:string" minOccurs="0"/>
+ <xs:element name="result-detail" type="xs:string" minOccurs="0"/>
+ <xs:element name="start-node-type" type="xs:string" minOccurs="0"/>
+ <xs:element ref="tns:start-node-filter" minOccurs="0" maxOccurs="5000"/>
+ <xs:element ref="tns:include-node-filter" minOccurs="0" maxOccurs="5000"/>
+ <xs:element ref="tns:secondary-filter" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="result-data">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="The URL to the specific resource")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="resource-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="The specific type of node in the A&amp;AI graph")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-link" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="The URL to the specific resource")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="search-results">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="tns:result-data" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="relationship-data">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Value of the attribute.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="relationship-key" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="A keyword provided by A&amp;AI to indicate an attribute.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="relationship-value" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Value of the attribute.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="related-to-property">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Value part of a key/value pair")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="property-key" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Key part of a key/value pair")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="property-value" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Value part of a key/value pair")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="relationship">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="URL to the object in A&amp;AI.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="related-to" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="A keyword provided by A&amp;AI to indicate type of node.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="relationship-label" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="The edge label for this relationship.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="related-link" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="URL to the object in A&amp;AI.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-data" minOccurs="0" maxOccurs="5000"/>
+ <xs:element ref="tns:related-to-property" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="relationship-list">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="tns:relationship" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="oam-network">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="OAM network, to be deprecated shortly. Do not use for new purposes. ",nameProps="network-name",indexedProps="cvlan-tag,network-uuid,network-name",dependentOn="cloud-region",container="oam-networks",uriTemplate="/oam-networks/oam-network/{network-uuid}",requiredProps="network-uuid,network-name,cvlan-tag")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="network-uuid" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="UUID of the network. Unique across a cloud-region")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="network-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Name of the network.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="cvlan-tag" type="xs:unsignedInt" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="cvlan-id")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ipv4-oam-gateway-address" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for VNF firewall rule so customer cannot send customer traffic over this oam network")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ipv4-oam-gateway-address-prefix-length" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for VNF firewall rule so customer cannot send customer traffic over this oam network")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="oam-networks">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of OAM networks, to be deprecated shortly. Do not use for new purposes. ")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:oam-network" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="dvs-switch">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Digital virtual switch metadata, used by SDN-C to configure VCEs. A&amp;AI needs to receive this data from the PO deployment team and administer it using the provisioningTool.sh into A&amp;AI. ",indexedProps="vcenter-url,switch-name",dependentOn="cloud-region",container="dvs-switches",uriTemplate="/dvs-switches/dvs-switch/{switch-name}",requiredProps="switch-name,vcenter-url")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="switch-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="DVS switch name")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vcenter-url" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="URL used to reach the vcenter")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="dvs-switches">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of digital virtual switch metadata used for vmWare VCEs and GenericVnfs.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:dvs-switch" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="availability-zone">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Availability zone, a collection of compute hosts/pservers",indexedProps="availability-zone-name",dependentOn="cloud-region",container="availability-zones",uriTemplate="/availability-zones/availability-zone/{availability-zone-name}",requiredProps="availability-zone-name,hypervisor-type")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="availability-zone-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Name of the availability zone. Unique across a cloud region")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="hypervisor-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Type of hypervisor. Source of truth should define valid values.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="operational-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="State that indicates whether the availability zone should be used, etc. Source of truth should define valid values.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="az-and-dvs-switches">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="tns:dvs-switches" minOccurs="0"/>
+ <xs:element ref="tns:availability-zone" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="sdn-zone-response">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="tns:oam-networks" minOccurs="0"/>
+ <xs:element ref="tns:az-and-dvs-switches" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="search">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="tns:edge-tag-query-result" minOccurs="0"/>
+ <xs:element ref="tns:edge-tag-query-request" minOccurs="0"/>
+ <xs:element ref="tns:search-results" minOccurs="0"/>
+ <xs:element ref="tns:sdn-zone-response" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="update-node-key">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="key-name" type="xs:string" minOccurs="0"/>
+ <xs:element name="key-value" type="xs:string" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="action-data">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="property-name" type="xs:string" minOccurs="0"/>
+ <xs:element name="property-value" type="xs:string" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="action">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="action-type" type="xs:string" minOccurs="0"/>
+ <xs:element ref="tns:action-data" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="update">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Serves a PATCH like function. Does not enforce concurrency control. Clear each usage with AAI team.",requiredProps="update-node-type")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="update-node-type" type="xs:string" minOccurs="0"/>
+ <xs:element ref="tns:update-node-key" minOccurs="0" maxOccurs="5000"/>
+ <xs:element name="update-node-uri" type="xs:string" minOccurs="0"/>
+ <xs:element ref="tns:action" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="key-data">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="key-name" type="xs:string" minOccurs="0"/>
+ <xs:element name="key-value" type="xs:string" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="notify">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="event-id" type="xs:string" minOccurs="0"/>
+ <xs:element name="node-type" type="xs:string" minOccurs="0"/>
+ <xs:element name="event-trigger" type="xs:string" minOccurs="0"/>
+ <xs:element ref="tns:key-data" minOccurs="0" maxOccurs="5000"/>
+ <xs:element name="selflink" type="xs:string" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="actions">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="APIs that are more action related than REST (e.g., notify, update).")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:update" minOccurs="0"/>
+ <xs:element ref="tns:notify" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="rack-unit">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Definition of rack-unit",indexedProps="rack-unit-name",dependentOn="rack",container="rack-units",uriTemplate="/rack-units/rack-unit/{rack-unit-name}",requiredProps="rack-unit-name")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="rack-unit-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="A unique name for the rack-unit (within the rack).")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="rack-units">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="tns:rack-unit" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="pdu">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Definition of pdu",uniqueProps="pdu-name",indexedProps="pdu-name",dependentOn="rack",container="pdus",uriTemplate="/pdus/pdu/{pdu-name}",requiredProps="pdu-name,pdu-type")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="pdu-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="A unique name for the power distribution unit.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="pdu-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="The type of pdu.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="pdus">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="tns:pdu" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="rack">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Definition of rack",uniqueProps="rack-name",indexedProps="rack-name",dependentOn="complex",container="racks",uriTemplate="/racks/rack/{rack-name}",requiredProps="rack-name,rack-type,rack-location,rack-power-diversity")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="rack-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="A unique name for the rack (within the location).")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="rack-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="The type of rack.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="rack-location" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="The location of the rack within the building.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="rack-position" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="The position of the rack (ex-floor-mounted).")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="rack-power-diversity" type="xs:boolean" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(defaultValue="false",description="")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ <xs:element ref="tns:rack-units" minOccurs="0"/>
+ <xs:element ref="tns:pdus" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="racks">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="tns:rack" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="cable">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Definition of cable",indexedProps="cable-name",dependentOn="complex",container="cables",uriTemplate="/cables/cable/{cable-name}",requiredProps="cable-name,cable-type")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="cable-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="A unique name for the channel-link relative to the physical-link.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="cable-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="The type of cable.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="cables">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="tns:cable" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="ctag-pool">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="A collection of C tags (vlan tags) grouped for a specific purpose.",indexedProps="availability-zone-name",dependentOn="complex",container="ctag-pools",uriTemplate="/ctag-pools/ctag-pool/{target-pe}/{availability-zone-name}",requiredProps="target-pe,availability-zone-name,ctag-pool-purpose")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="target-pe" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="The Target provider edge router")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="availability-zone-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Name of the availability zone")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ctag-pool-purpose" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Describes what the intended purpose of this pool is.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ctag-values" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Comma separated list of ctags")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="ctag-pools">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="tns:ctag-pool" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="complex">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of physical locations that can house cloud-regions.",indexedProps="identity-url,data-center-code,complex-name,physical-location-id",searchable="physical-location-id,data-center-code,complex-name,street1,street2,postal-code",uniqueProps="physical-location-id",container="complexes",namespace="cloud-infrastructure",uriTemplate="/cloud-infrastructure/complexes/complex/{physical-location-id}",requiredProps="physical-location-id,physical-location-type,street1,city,postal-code,country,region")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="physical-location-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Unique identifier for physical location, e.g., CLLI")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="data-center-code" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Data center code which can be an alternate way to identify a complex")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="complex-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Gamma complex name for LCP instance.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="identity-url" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="URL of the keystone identity service")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="physical-location-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Type, e.g., central office, data center.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="time-zone" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="The time zone where the complex is located.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="street1" type="xs:string" minOccurs="0"/>
+ <xs:element name="street2" type="xs:string" minOccurs="0"/>
+ <xs:element name="city" type="xs:string" minOccurs="0"/>
+ <xs:element name="state" type="xs:string" minOccurs="0"/>
+ <xs:element name="postal-code" type="xs:string" minOccurs="0"/>
+ <xs:element name="country" type="xs:string" minOccurs="0"/>
+ <xs:element name="region" type="xs:string" minOccurs="0"/>
+ <xs:element name="latitude" type="xs:string" minOccurs="0"/>
+ <xs:element name="longitude" type="xs:string" minOccurs="0"/>
+ <xs:element name="elevation" type="xs:string" minOccurs="0"/>
+ <xs:element name="lata" type="xs:string" minOccurs="0"/>
+ <xs:element ref="tns:racks" minOccurs="0"/>
+ <xs:element ref="tns:cables" minOccurs="0"/>
+ <xs:element ref="tns:ctag-pools" minOccurs="0"/>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="complexes">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of physical locations that can house cloud-regions.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:complex" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="volume-group">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Persistent block-level storage.",indexedProps="volume-group-name,vnf-type,heat-stack-id,volume-group-id,orchestration-status",searchable="volume-group-id,volume-group-name",dependentOn="cloud-region",container="volume-groups",uriTemplate="/volume-groups/volume-group/{volume-group-id}",requiredProps="volume-group-id,vnf-type")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="volume-group-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Unique ID of volume-group.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="volume-group-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Name of the volume group.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="heat-stack-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Heat stack id corresponding to this volume-group")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vnf-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="String capturing type of vnf, that was intended to identify the SDC resource. This field has been overloaded in service-specific ways and clients should expect changes to occur in the future to this field as ONAP matures.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="orchestration-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Orchestration status of this volume-group")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-customization-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="captures the id of all the configuration used to customize the resource for the service.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vf-module-model-customization-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="helps relate the volume group to the vf-module whose components will require the volume group")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="volume-groups">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of persistent block-level storage.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:volume-group" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="volume">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Ephemeral Block storage volume.",indexedProps="volume-id",dependentOn="vserver",container="volumes",uriTemplate="/volumes/volume/{volume-id}",requiredProps="volume-id,volume-selflink")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="volume-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Unique ID of block storage volume relative to the vserver.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="volume-selflink" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="URL to endpoint where AAI can get more details")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="volumes">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of ephemeral Block storage volumes.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:volume" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="l3-interface-ipv4-address-list">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="IPv4 Address Range",indexedProps="l3-interface-ipv4-address,vlan-id-inner,neutron-network-id,neutron-subnet-id",dependentOn="vlan,l-interface,vnfc,cp,lag-interface,p-interface",uriTemplate="/l3-interface-ipv4-address-list/{l3-interface-ipv4-address}",requiredProps="l3-interface-ipv4-address")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="l3-interface-ipv4-address" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="IP address")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="l3-interface-ipv4-prefix-length" type="xs:unsignedInt" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Prefix length, 32 for single address")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vlan-id-inner" type="xs:unsignedInt" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Inner VLAN tag")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vlan-id-outer" type="xs:unsignedInt" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Outer VLAN tag")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="is-floating" type="xs:boolean" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Indicator of fixed or floating address")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="neutron-network-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Neutron network id of the interface that address belongs to")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="neutron-subnet-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Neutron id of subnet that address belongs to")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ops-note" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Notes to aid OPs in troubleshooting, such as attribute aliases or additional descriptions/instructions about an object.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="l3-interface-ipv6-address-list">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="IPv6 Address Range",indexedProps="l3-interface-ipv6-address,vlan-id-inner,neutron-network-id,neutron-subnet-id",dependentOn="vlan,l-interface,vnfc,cp,lag-interface,p-interface",uriTemplate="/l3-interface-ipv6-address-list/{l3-interface-ipv6-address}",requiredProps="l3-interface-ipv6-address")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="l3-interface-ipv6-address" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="IP address")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="l3-interface-ipv6-prefix-length" type="xs:unsignedInt" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Prefix length, 128 for single address")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vlan-id-inner" type="xs:unsignedInt" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Inner VLAN tag")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vlan-id-outer" type="xs:unsignedInt" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Outer VLAN tag")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="is-floating" type="xs:boolean" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Indicator of fixed or floating address")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="neutron-network-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Neutron network id of the interface that address belongs to")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="neutron-subnet-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Neutron id of subnet that address belongs to")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ops-note" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Notes to aid OPs in troubleshooting, such as attribute aliases or additional descriptions/instructions about an object.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vlan">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Definition of vlan",indexedProps="vlan-interface,vlan-id-inner,vpn-key,orchestration-status,prov-status",dependentOn="l-interface",container="vlans",uriTemplate="/vlans/vlan/{vlan-interface}",requiredProps="vlan-interface,in-maint,is-ip-unnumbered,is-private")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="vlan-interface" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="String that identifies the interface")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vlan-id-inner" type="xs:unsignedInt" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Inner VLAN tag")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vlan-id-outer" type="xs:unsignedInt" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Outer VLAN tag")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="speed-value" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Captures the numeric part of the speed")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="speed-units" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Captures the units corresponding to the speed")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vlan-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="The type of vlan (eg. vxlan)")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vlan-description" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used to describe (the service associated with) the vlan")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="backdoor-connection" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Whether customer is going to use this VLAN for backdoor connection to another customer premise device.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vpn-key" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="This indicates the customers VPN ID associated with this vlan")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="orchestration-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Status of a vnf's vlan interface, on which the customer circuit resides, mastered by SDN-C.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="in-maint" type="xs:boolean" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(defaultValue="false",description="used to indicate whether or not this object is in maintenance mode (maintenance mode = true)")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="prov-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Prov Status of the VLAN configuration related to a logical interface. Valid values [PREPROV/NVTPROV/PROV].")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="is-ip-unnumbered" type="xs:boolean" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(defaultValue="false",description="Flag indicating the interface uses the IP Unnumbered configuration.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="is-private" type="xs:boolean" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(defaultValue="false",description="Private VLAN indicator.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ <xs:element ref="tns:l3-interface-ipv4-address-list" minOccurs="0" maxOccurs="5000"/>
+ <xs:element ref="tns:l3-interface-ipv6-address-list" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vlans">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="tns:vlan" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="sriov-vf">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="SR-IOV Virtual Function (not to be confused with virtual network function)",indexedProps="pci-id,vf-vlan-filter,vf-mac-filter,vf-vlan-strip,neutron-network-id",dependentOn="l-interface",container="sriov-vfs",uriTemplate="/sriov-vfs/sriov-vf/{pci-id}",requiredProps="pci-id")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="pci-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="PCI ID used to identify the sriov-vf")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vf-vlan-filter" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="This metadata provides option to specify list of VLAN filters applied on VF to pass the traffic to VM.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vf-mac-filter" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="When MAC filters are specified, VF-agent service configures VFs to do MAC level filtering before the traffic is passed to VM.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vf-vlan-strip" type="xs:boolean" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="When this field is set to true, VF will configured to strip the outer TAG before the traffic is passed to VM.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vf-vlan-anti-spoof-check" type="xs:boolean" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="This option ensures anti VLAN spoof checks are done at the VF level to comply with security. The disable check will also be honored per the VNF needs for trusted VMs.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vf-mac-anti-spoof-check" type="xs:boolean" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="This option ensures anti MAC spoof checks are done at the VF level to comply with security. The disable check will also be honored per the VNF needs for trusted VMs.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vf-mirrors" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="This option defines the set of Mirror objects which essentially mirrors the traffic from source to set of collector VNF Ports.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vf-broadcast-allow" type="xs:boolean" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="This option, if set to true, sets the VF in promiscuous mode and allows all broadcast traffic to reach the VM")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vf-unknown-multicast-allow" type="xs:boolean" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="This option, if set to true, sets the VF in promiscuous mode and allows unknown multicast traffic to reach the VM")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vf-unknown-unicast-allow" type="xs:boolean" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="This option, if set to true, sets the VF in promiscuous mode and allows unknown unicast traffic to reach the VM")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vf-insert-stag" type="xs:boolean" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="This option, if set to true, instructs to insert outer tag after traffic comes out of VM.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vf-link-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="This option is used to set the link status. Valid values as of 1607 are on, off, and auto.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="neutron-network-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Neutron network id of the interface")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="sriov-vfs">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of SR-IOV Virtual Functions.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:sriov-vf" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="l-interface">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Logical interfaces, e.g., a vnic.",indexedProps="macaddr,interface-id,interface-name,network-name,interface-type,interface-function,interface-role,prov-status",dependentOn="generic-vnf,newvce,p-interface,vserver,lag-interface,l-interface,pnf,pserver",nameProps="interface-type",container="l-interfaces",uriTemplate="/l-interfaces/l-interface/{interface-name}",searchable="interface-name",requiredProps="interface-name,is-port-mirrored,in-maint,is-ip-unnumbered")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="interface-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Name given to the interface")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="interface-role" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="E.g., CUSTOMER, UPLINK, etc.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="v6-wan-link-ip" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Questionably placed - v6 ip addr of this interface (is in vr-lan-interface from Mary B.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="selflink" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="URL to endpoint where AAI can get more details")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="interface-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="ID of interface")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="macaddr" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="MAC address for the interface")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="network-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Name of the network")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="management-option" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Whether A&amp;AI should be managing this interface of not. Could have value like CUSTOMER")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="interface-description" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Human friendly text regarding this interface.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="interface-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="type to sub-classify the l-interface (ex, loopback)")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="is-port-mirrored" type="xs:boolean" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(defaultValue="false",description="boolean indicatating whether or not port is a mirrored.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="in-maint" type="xs:boolean" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(defaultValue="false",description="used to indicate whether or not this object is in maintenance mode (maintenance mode = true)")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="prov-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Prov Status of the logical interface. Valid values [PREPROV/NVTPROV/PROV].")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="is-ip-unnumbered" type="xs:boolean" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(defaultValue="false",description="Flag indicating the interface uses the IP Unnumbered configuration.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="allowed-address-pairs" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Freeform field for storing an ip address, list of ip addresses or a subnet block.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="priority" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Priority used for fail-over. Valid values 1-1024, with 1 being the highest priority.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ops-note" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Notes to aid OPs in troubleshooting, such as attribute aliases or additional descriptions/instructions about an object.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="interface-function" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="The function performed by this Linterface")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="l2-multicasting" type="xs:boolean" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(defaultValue="false",description="Identifies l2-multicasting support on an l-interface. true indicates that l2-multicasting is supported; defaulted to false .")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:vlans" minOccurs="0"/>
+ <xs:element ref="tns:sriov-vfs" minOccurs="0"/>
+ <xs:element ref="tns:l-interfaces" minOccurs="0"/>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ <xs:element ref="tns:l3-interface-ipv4-address-list" minOccurs="0" maxOccurs="5000"/>
+ <xs:element ref="tns:l3-interface-ipv6-address-list" minOccurs="0" maxOccurs="5000"/>
+ <xs:element name="admin-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Administrative status of the interface. Valid values are 'up', 'down', or 'testing'.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="l-interfaces">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of logical interfaces.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:l-interface" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vserver">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Virtual Servers, aka virtual machine or VM.",nameProps="vserver-name",indexedProps="is-closed-loop-disabled,prov-status,vserver-name,vserver-id,vserver-name2",searchable="vserver-id,vserver-name,vserver-name2,operational-status",dependentOn="tenant",container="vservers",uriTemplate="/vservers/vserver/{vserver-id}",requiredProps="vserver-id,vserver-name,vserver-selflink,in-maint,is-closed-loop-disabled")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="vserver-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Unique identifier for this vserver relative to its tenant")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vserver-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Name of vserver")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vserver-name2" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Alternative name of vserver")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="prov-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Trigger for operational monitoring of this resource by Service Assurance systems.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vserver-selflink" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="URL to endpoint where AAI can get more details")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="in-maint" type="xs:boolean" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(defaultValue="false",description="Used to indicate whether or not this object is in maintenance mode (maintenance mode = true). This field (in conjunction with prov-status) is used to suppress alarms and vSCL on VNFs/VMs.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="is-closed-loop-disabled" type="xs:boolean" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(defaultValue="false",description="Used to indicate whether closed loop function is enabled on this node")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="numa" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Non-uniform memory access optimization, helps prevent memory-bandwidth bottlenecks. Expected values - 1 or 2 identifying memory access")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:volumes" minOccurs="0"/>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ <xs:element ref="tns:l-interfaces" minOccurs="0"/>
+ <xs:element name="operational-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Indicator for whether the resource is considered operational. Valid values are in-service-path and out-of-service-path.",suggestibleOnSearch="true")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vservers">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of virtual Servers, aka virtual machines or VMs.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:vserver" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="nos-server">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="nos-server is the execution environment that will have images, certain versions of VNOS, running on it.",indexedProps="nos-server-id,prov-status",dependentOn="tenant",nameProps="nos-server-name",container="nos-servers",uriTemplate="/nos-servers/nos-server/{nos-server-id}",requiredProps="nos-server-id,nos-server-name,vendor,nos-server-selflink,in-maint")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="nos-server-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Unique identifier for this nos relative to its tenant")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="nos-server-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Name of nos")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vendor" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="uCPE vendor")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="prov-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Trigger for operational monitoring of this resource by Service Assurance systems.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="nos-server-selflink" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="URL to endpoint where AAI can get more details")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="in-maint" type="xs:boolean" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(defaultValue="false",description="Used to indicate whether or not this object is in maintenance mode (maintenance mode = true). This field (in conjunction with prov-status) is used to suppress alarms and vSCL on VNFs/VMs.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="nos-servers">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="nos-server is the execution environment that will have images, certain versions of VNOS, running on it.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:nos-server" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="tenant">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Openstack tenant",nameProps="tenant-name",indexedProps="tenant-name,tenant-id,tenant-context",searchable="tenant-id,tenant-name",dependentOn="cloud-region",container="tenants",uriTemplate="/tenants/tenant/{tenant-id}",requiredProps="tenant-id,tenant-name")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="tenant-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Unique id relative to the cloud-region.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="tenant-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Readable name of tenant")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="tenant-context" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="This field will store the tenant context.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="parent-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="tenant parent-id")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:vservers" minOccurs="0"/>
+ <xs:element ref="tns:nos-servers" minOccurs="0"/>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="tenants">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of openstack tenants.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:tenant" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="hpa-feature-attributes">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="HPA Capability Feature attributes",indexedProps="hpa-attribute-key",dependentOn="hpa-capability",requiredProps="hpa-attribute-key")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="hpa-attribute-key" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="name of the specific HPA attribute")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="hpa-attribute-value" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="JSON string specifying the value, unit and type of the specific HPA attribute")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="hpa-capability">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Represents a HPA capability",indexedProps="hpa-feature,architecture,hpa-capability-id",dependentOn="flavor,cloud-region",container="hpa-capabilities",requiredProps="hpa-capability-id,hpa-feature",uriTemplate="/hpa-capabilities/hpa-capability/{hpa-capability-id}")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="hpa-capability-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="UUID to uniquely identify a HPA capability")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="hpa-feature" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Name of the HPACapability")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="hpa-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="HPA schema version")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="architecture" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Hardware architecture")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ <xs:element ref="tns:hpa-feature-attributes" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="hpa-capabilities">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of HPA Capabilities")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:hpa-capability" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="flavor">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Openstack flavor.",nameProps="flavor-name",indexedProps="flavor-name,flavor-id",dependentOn="cloud-region",container="flavors",uriTemplate="/flavors/flavor/{flavor-id}",requiredProps="flavor-id,flavor-name,flavor-selflink")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="flavor-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Flavor id, expected to be unique across cloud-region.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="flavor-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Flavor name")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="flavor-vcpus" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Number of CPUs")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="flavor-ram" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Amount of memory")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="flavor-disk" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Disk space")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="flavor-ephemeral" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Amount of ephemeral disk space")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="flavor-swap" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="amount of swap space allocation")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="flavor-is-public" type="xs:boolean" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="whether flavor is available to all users or private to the tenant it was created in.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="flavor-selflink" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="URL to endpoint where AAI can get more details")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="flavor-disabled" type="xs:boolean" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Boolean as to whether this flavor is no longer enabled")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:hpa-capabilities" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="List of flavor specific HPA Capabilities")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="flavors">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of openstack flavors.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:flavor" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="group-assignment">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Openstack group-assignment used to store exclusivity groups (EG).",nameProps="group-name",indexedProps="group-id,group-type,group-name",searchable="group-id,group-name",dependentOn="cloud-region",container="group-assignments",uriTemplate="/group-assignments/group-assignment/{group-id}",requiredProps="group-id,group-type,group-name")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="group-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Group id, expected to be unique across cloud-region.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="group-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Group type - the type of group this instance refers to")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="group-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Group name - name assigned to the group")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="group-description" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Group description - description of the group")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="group-assignments">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of openstack group assignments")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:group-assignment" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="snapshot">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Openstack snapshot",nameProps="snapshot-name",uniqueProps="snapshot-id",indexedProps="application,snapshot-name,application-vendor,snapshot-id,application-version,prev-snapshot-id",dependentOn="cloud-region",container="snapshots",uriTemplate="/snapshots/snapshot/{snapshot-id}",requiredProps="snapshot-id")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="snapshot-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Snapshot id, this is the key UUID assoc associated in glance with the snapshots.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="snapshot-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Snapshot name")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="snapshot-architecture" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Operating system architecture")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="snapshot-os-distro" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="The common name of the operating system distribution in lowercase")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="snapshot-os-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="The operating system version as specified by the distributor.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="application" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="The application that the image instantiates.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="application-vendor" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="The vendor of the application.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="application-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="The version of the application.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="snapshot-selflink" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="URL to endpoint where AAI can get more details")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="prev-snapshot-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="This field contains the UUID of the previous snapshot (if any).")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="snapshots">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of openstack snapshots")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:snapshot" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="metadatum">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Key/value pairs",indexedProps="metaname",dependentOn="image,service-instance,connector,configuration,model-ver,profile",container="metadata",uriTemplate="/metadata/metadatum/{metaname}",requiredProps="metaname,metaval")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="metaname" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true)</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="metaval" type="xs:string" minOccurs="0"/>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="metadata">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of metadatum (key/value pairs)")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:metadatum" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="image">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Openstack image.",nameProps="image-name",indexedProps="application,image-name,application-vendor,image-id,application-version",dependentOn="cloud-region",container="images",uriTemplate="/images/image/{image-id}",requiredProps="image-id,image-name,image-os-distro,image-os-version,image-selflink")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="image-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Image id, expected to be unique across cloud region")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="image-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Image name")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="image-architecture" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Operating system architecture.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="image-os-distro" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="The common name of the operating system distribution in lowercase")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="image-os-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="The operating system version as specified by the distributor.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="application" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="The application that the image instantiates.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="application-vendor" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="The vendor of the application.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="application-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="The version of the application.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="image-selflink" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="URL to endpoint where AAI can get more details")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ <xs:element ref="tns:metadata" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="images">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collectio of Openstack images.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:image" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="availability-zones">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of availability zones")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:availability-zone" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vip-ipv4-address-list">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="IPv4 Address Range",indexedProps="vip-ipv4-address,vlan-id-inner,neutron-network-id,neutron-subnet-id",dependentOn="cloud-region",uriTemplate="/vip-ipv4-address-list/{vip-ipv4-address}",requiredProps="vip-ipv4-address")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="vip-ipv4-address" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="IP address")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vip-ipv4-prefix-length" type="xs:unsignedInt" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Prefix length, 32 for single address")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vlan-id-inner" type="xs:unsignedInt" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Inner VLAN tag")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vlan-id-outer" type="xs:unsignedInt" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Outer VLAN tag")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="is-floating" type="xs:boolean" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Indicator of fixed or floating address")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="neutron-network-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Neutron network id of the interface that address belongs to")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="neutron-subnet-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Neutron id of subnet that address belongs to")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ops-note" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Notes to aid OPs in troubleshooting, such as attribute aliases or additional descriptions/instructions about an object.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vip-ipv6-address-list">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="IPv6 Address Range",indexedProps="vip-ipv6-address,vlan-id-inner,neutron-network-id,neutron-subnet-id",dependentOn="cloud-region",uriTemplate="/vip-ipv6-address-list/{vip-ipv6-address}",requiredProps="vip-ipv6-address")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="vip-ipv6-address" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="IP address")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vip-ipv6-prefix-length" type="xs:unsignedInt" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Prefix length, 128 for single address")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vlan-id-inner" type="xs:unsignedInt" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Inner VLAN tag")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vlan-id-outer" type="xs:unsignedInt" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Outer VLAN tag")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="is-floating" type="xs:boolean" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Indicator of fixed or floating address")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="neutron-network-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Neutron network id of the interface that address belongs to")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="neutron-subnet-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Neutron id of subnet that address belongs to")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ops-note" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Notes to aid OPs in troubleshooting, such as attribute aliases or additional descriptions/instructions about an object.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vlan-tag">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="vlan tag information",container="vlan-tags",dependentOn="vlan-range",uriTemplate="/vlan-tags/vlan-tag/{vlan-tag-id}",requiredProps="vlan-tag-id,vlan-tag-role,is-private")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="vlan-tag-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Vlan Tag Id")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vlan-tag-role" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Role assigned to this vlan-tag")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vlan-id-inner" type="xs:unsignedInt" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Inner VLAN tag")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vlan-id-outer" type="xs:unsignedInt" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Outer VLAN tag")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="is-private" type="xs:boolean" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="is private flag.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vlan-tag-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="VLAN tag Type")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vlan-tag-function" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="VLAN Tag Function")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="config-phase" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="The config-phase associated with this vlan-tag")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vlan-tags">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Vlan Tags Assigned out of a Vlan Range")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:vlan-tag" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vlan-range">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Definition of vlan range",indexedProps="vlan-range-id,vlan-type",dependentOn="cloud-region",container="vlan-ranges",uriTemplate="/vlan-ranges/vlan-range/{vlan-range-id}",searchable="vlan-range-id",requiredProps="vlan-range-id,vlan-id-lower,vlan-id-upper,vlan-type")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="vlan-range-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="vlan id in range UUID.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vlan-id-lower" type="xs:unsignedInt" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="vlan id in range lower")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vlan-id-upper" type="xs:unsignedInt" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="vlan id in range upper")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vlan-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="vlan type")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:vlan-tags" minOccurs="0"/>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vlan-ranges">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="tns:vlan-range" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="host-aggregate">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="describes an hostAggregates",dependentOn="cloud-region",container="host-aggregates",uriTemplate="/host-aggregates/host-aggregate/{host-aggregate-id}",requiredProps="host-aggregate-id,host-aggregate-name")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="host-aggregate-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Unique identifier for the host-aggregate.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="host-aggregate-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Name of the host-aggregate.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="host-aggregates">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of HostAggregates.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:host-aggregate" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="activity-state">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="describes an activities",uniqueProps="state-order",dependentOn="activity",container="activity-states",uriTemplate="/activity-states/activity-state/{state-order}",requiredProps="state-order,state-name")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="state-order" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Order for the activity state.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="state-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Name of the activity state (ex, NVT-PROV).")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="state-view" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="View of the activity state.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="activity-states">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of activity-states")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:activity-state" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="activity">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="describes an activities",uniqueProps="activity-id",dependentOn="pserver,pnf,cloud-region,p-interface,network-range",container="activities",uriTemplate="/activities/activity/{activity-id}",requiredProps="activity-id,activity-type")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="activity-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Unique id for the activity. (UUID)")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="activity-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Type of activity (ex, provisioning).")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="activity-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Name of the activity.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="activity-creator" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Application that created the activity.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="activity-description" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Description of activity.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="timestamp" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Date and Time activity is created.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="current-state" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Current state of the activity.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="reflected-state" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="State reflected by the database.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="activity-role" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Role")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="activity-function" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Function")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="timestamp-last-updated" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Date/time last updated")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="timestamp-expiration" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Date/time expires")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:activity-states" minOccurs="0"/>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="activities">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of activities.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:activity" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="validation-audit">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="validation audit, value of validation status",indexedProps="validation-id",uniqueProps="validation-id",dependentOn="cloud-region",container="validation-audits",uriTemplate="/validation-audits/validation-audit/{validation-id}",requiredProps="validation-id")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="validation-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Validation-Audit UUID")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="validation-request-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Request-id to retrieve data from client related to the specified audit")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="validation-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Status of the audit")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="validation-phase" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Phase in the lifecycle of the configuration")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="validation-audits">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of validation-audit")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:validation-audit" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="esr-system-info">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Persist common address information of external systems.",indexedProps="esr-system-info-id,system-name,system-type",searchable="esr-system-info-id,system-name,system-type",container="esr-system-info-list",dependentOn="cloud-region,esr-ems,esr-vnfm,esr-thirdparty-sdnc,ext-aai-network,esr-nfvo",requiredProps="esr-system-info-id,user-name,password,system-type",uriTemplate="/esr-system-info-list/esr-system-info/{esr-system-info-id}")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="esr-system-info-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Unique ID of esr system info.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="system-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="name of external system.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="type of external systems.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vendor" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="vendor of external systems.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="version of external systems.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="service-url" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="url used to access external systems.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="user-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="username used to access external systems.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="password" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="password used to access external systems.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="system-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="it could be vim/vnfm/thirdparty-sdnc/ems-resource/ems-performance/ems-alarm.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="protocol" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="protocol of third party SDNC, for example netconf/snmp.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ssl-cacert" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="ca file content if enabled ssl on auth-url.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ssl-insecure" type="xs:boolean" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Whether to verify VIM's certificate.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ip-address" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="service IP of ftp server.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="port" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="service port of ftp server.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="cloud-domain" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="domain info for authentication.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="default-tenant" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="default tenant of VIM.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="passive" type="xs:boolean" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="ftp passive mode or not.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="remote-path" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="resource or performance data file path.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="system-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="the status of external system.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="openstack-region-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="OpenStack region ID used by MultiCloud plugin to interact with an OpenStack instance.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="esr-system-info-list">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of persistent block-level external system auth info.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:esr-system-info" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="cloud-region">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="cloud-region designates an installation of a cloud cluster or region or instantiation. In AT&amp;Ts AIC cloud, this could be an LCP or DCP. Cloud regions are uniquely identified by a composite key, cloud-owner + cloud-region-id. The format of the cloud-owner is vendor-cloudname and we will use att-aic for AT&amp;T's AIC.",indexedProps="cloud-owner,cloud-region-id,cloud-type,owner-defined-type",nameProps="owner-defined-type",container="cloud-regions",namespace="cloud-infrastructure",uriTemplate="/cloud-infrastructure/cloud-regions/cloud-region/{cloud-owner}/{cloud-region-id}",requiredProps="cloud-owner,cloud-region-id,orchestration-disabled,in-maint")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="cloud-owner" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Identifies the vendor and cloud name. First part of composite key should be formatted as vendor-cloudname")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="cloud-region-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Identifier used by the vendor for the region. Second part of composite key")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="cloud-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Type of the cloud (e.g., openstack)")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="owner-defined-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Cloud-owner defined type indicator (e.g., dcp, lcp)")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="cloud-region-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Software version employed at the site. NOTE - THIS FIELD IS NOT KEPT UP TO DATE.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="identity-url" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="URL of the keystone identity service")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="cloud-zone" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Zone where the cloud is homed. NOTE - THIS FIELD IS NOT CORRECTLY POPULATED.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="complex-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="complex name for cloud-region instance. NOTE - THIS FIELD IS NOT CORRECTLY POPULATED.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="sriov-automation" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Whether the cloud region supports (true) or does not support (false) SR-IOV automation.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="cloud-extra-info" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="ESR inputs extra information about the VIM or Cloud which will be decoded by MultiVIM.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="cloud-region-number" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Number that maps to the letter at the end of the cloud-region-id.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="cloud-function" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Function of cloud-region.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="cloud-role" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Role of cloud-region.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ops-note" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Notes to aid OPs in troubleshooting, such as attribute aliases or additional descriptions/instructions about an object.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="cloud-region-number-definition" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="The alias used for this cloud.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Status of cloud-region.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="upgrade-cycle" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Upgrade cycle for the cloud region. For AIC regions upgrade cycle is designated by A,B,C etc.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="orchestration-disabled" type="xs:boolean" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(defaultValue="false",description="Used to indicate whether orchestration is enabled for this cloud-region.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="in-maint" type="xs:boolean" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(defaultValue="false",description="Used to indicate whether or not cloud-region object is in maintenance mode.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:volume-groups" minOccurs="0"/>
+ <xs:element ref="tns:tenants" minOccurs="0"/>
+ <xs:element ref="tns:flavors" minOccurs="0"/>
+ <xs:element ref="tns:group-assignments" minOccurs="0"/>
+ <xs:element ref="tns:snapshots" minOccurs="0"/>
+ <xs:element ref="tns:images" minOccurs="0"/>
+ <xs:element ref="tns:dvs-switches" minOccurs="0"/>
+ <xs:element ref="tns:oam-networks" minOccurs="0"/>
+ <xs:element ref="tns:availability-zones" minOccurs="0"/>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ <xs:element ref="tns:vip-ipv4-address-list" minOccurs="0" maxOccurs="5000"/>
+ <xs:element ref="tns:vip-ipv6-address-list" minOccurs="0" maxOccurs="5000"/>
+ <xs:element ref="tns:vlan-ranges" minOccurs="0"/>
+ <xs:element ref="tns:host-aggregates" minOccurs="0"/>
+ <xs:element ref="tns:activities" minOccurs="0"/>
+ <xs:element ref="tns:validation-audits" minOccurs="0"/>
+ <xs:element ref="tns:hpa-capabilities" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="List of cloud-region specific HPA Capabilities")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:esr-system-info-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="cloud-regions">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(maximumDepth="0")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:cloud-region" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="network-profile">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Network profile populated by SDN-GP for SNMP",indexedProps="nm-profile-name",container="network-profiles",namespace="cloud-infrastructure",uriTemplate="/cloud-infrastructure/network-profiles/network-profile/{nm-profile-name}",requiredProps="nm-profile-name")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="nm-profile-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Unique name of network profile.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="community-string" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Encrypted SNMP community string")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="network-profiles">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of network profiles")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:network-profile" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="available-bandwidth">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Instance of an available-bandwidth-map",indexedProps="ab-id",searchable="ab-id",uniqueProps="ab-id",container="available-bandwidth-map",dependentOn="bandwidth-attribute",requiredProps="ab-id")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="ab-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Id that identifies the attribute")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="odu-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="ODU Type that identifies the ODU Eg. ODU0, ODU1, ODU2, ODU3, ODU4")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="number" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="The value of available bandwidth. Applicable only for ENNI.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="selflink" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the link to get more information for this object.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="available-bandwidth-map">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of Available Bandwidth. Added for ENNI in MDONS use case.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:available-bandwidth" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="otn-label-restriction">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Instance of a otn-label-restriction attribute",indexedProps="lr-id",searchable="lr-id",uniqueProps="lr-id",container="otn-label-restrictions",dependentOn="bandwidth-attribute",requiredProps="lr-id")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="lr-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Id that identifies the label restriction")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="range-bitmap" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Bitmap of available labels starting from label-start to label-end.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="label-step" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Step of labels in label range.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="selflink" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the link to get more information for this object.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="otn-label-restrictions">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of Label Restriction. Added for ENNI in MDONS use case.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:otn-label-restriction" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="bandwidth-attribute">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Instance of a bandwidth-attribute",indexedProps="bwa-id",searchable="bwa-id",uniqueProps="bwa-id",container="bandwidth-attributes",dependentOn="pnf,p-interface",requiredProps="bwa-id",uriTemplate="/bandwidth-attributes/bandwidth-attribute/{bwa-id}")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="bwa-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Id that identifies the bandwidth attribute")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="selflink" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the link to get more information for this object.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ <xs:element ref="tns:available-bandwidth-map" minOccurs="0"/>
+ <xs:element ref="tns:otn-label-restrictions" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="bandwidth-attributes">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of bandwidth attribute. Added for ENNI in MDONS use case.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:bandwidth-attribute" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="sriov-pf">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="SR-IOV Physical Function",indexedProps="pf-pci-id",dependentOn="p-interface",container="sriov-pfs",uriTemplate="/sriov-pfs/sriov-pf/{pf-pci-id}",requiredProps="pf-pci-id")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="pf-pci-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Identifier for the sriov-pf")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="sriov-pfs">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of SR-IOV Physical Functions.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:sriov-pf" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="p-interface">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Physical interface (e.g., nic)",indexedProps="interface-name,prov-status,network-ref,operational-status,interface-role,interface-name2",nameProps="prov-status",dependentOn="vpls-pe,pserver,pnf",container="p-interfaces",uriTemplate="/p-interfaces/p-interface/{interface-name}",searchable="interface-name",requiredProps="interface-name,in-maint")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="interface-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Name that identifies the physical interface")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="interface-name2" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Alternate name that identifies the physical interface")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="selflink" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="URL to endpoint where AAI can get more details.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="speed-value" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Captures the numeric part of the speed")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="speed-units" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Captures the units corresponding to the speed")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="port-description" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Nature of the services and connectivity on this port.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="domain-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Domain type of the SDNC controllerr.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="equipment-identifier" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="CLEI or other specification for p-interface hardware.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="interface-role" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Role specification for p-interface hardware.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="interface-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Indicates the physical properties of the interface.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="network-interface-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Indicates the physical properties of the interface.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:bandwidth-attributes" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="The data structure to indicate value of available bandwidth. Applicable only for ENNI.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="prov-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Trigger for operational monitoring of this resource by Service Assurance systems.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="mac-addresss" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="MAC Address of the p-interface.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="in-maint" type="xs:boolean" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(defaultValue="false",description="used to indicate whether or not this object is in maintenance mode (maintenance mode = true)")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="inv-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="inventory status")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ops-note" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Notes to aid OPs in troubleshooting, such as attribute aliases or additional descriptions/instructions about an object.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="interface-function" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="The function performed by this pInterface")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="macaddr" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="MAC address for the interface")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="network-ref" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the network-ref of this p-interface. Derived from ietf-restconf-notification that identifies a termination-point.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="transparent" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the transparent value of this p-interface.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="operational-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="oper Status of this p-interface.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="inter-domain-plug-id" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="connect interdomain link")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ <xs:element ref="tns:sriov-pfs" minOccurs="0"/>
+ <xs:element ref="tns:l-interfaces" minOccurs="0"/>
+ <xs:element ref="tns:activities" minOccurs="0"/>
+ <xs:element ref="tns:l3-interface-ipv4-address-list" minOccurs="0" maxOccurs="5000"/>
+ <xs:element ref="tns:l3-interface-ipv6-address-list" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="p-interfaces">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of physical interfaces.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:p-interface" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="lag-interface">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Link aggregate interface",indexedProps="interface-name,interface-id,interface-role,interface-function,prov-status",dependentOn="generic-vnf,pserver,vpls-pe,pnf",container="lag-interfaces",uriTemplate="/lag-interfaces/lag-interface/{interface-name}",requiredProps="interface-name,in-maint")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="interface-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Name that identifies the link aggregate interface")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="interface-description" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Human friendly text regarding this interface.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="speed-value" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Captures the numeric part of the speed")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="speed-units" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Captures the units corresponding to the speed")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="interface-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="ID of interface")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="interface-role" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Role assigned to this Interface, should use values as defined in ONAP Yang models.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="prov-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Trigger for operational monitoring of this resource by Service Assurance systems.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="in-maint" type="xs:boolean" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(defaultValue="false",description="used to indicate whether or not this object is in maintenance mode (maintenance mode = true)")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="lacp-system-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="The system id used by the LACP protocol.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ops-note" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Notes to aid OPs in troubleshooting, such as attribute aliases or additional descriptions/instructions about an object.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="interface-function" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="The function performed by this Lag interface")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="min-links" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Minimum links in service before a LAG should be taken out of service")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ <xs:element ref="tns:l-interfaces" minOccurs="0"/>
+ <xs:element ref="tns:l3-interface-ipv4-address-list" minOccurs="0" maxOccurs="5000"/>
+ <xs:element ref="tns:l3-interface-ipv6-address-list" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="lag-interfaces">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of link aggregate interfaces.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:lag-interface" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="hpa-capacity">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="HPA Capacity information for compute node",indexedProps="hpa-capacity-key",dependentOn="pserver",requiredProps="hpa-capacity-key")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="hpa-capacity-key" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Composite key formed with hpaFeature and append list of hpaFeatureAttributes needed for capacity check")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="hpa-capacity-value" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="JSON string specifying the capacity (total,free), unit and metadata of the specific HPA attribute")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="pserver">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Compute host whose hostname must be unique and must exactly match what is sent as a relationship to a vserver.",nameProps="pserver-name2,fqdn",indexedProps="hostname,pserver-id,pserver-name2,inv-status,fqdn,prov-status,ptnii-equip-name",searchable="hostname,pserver-name2,pserver-id,ipv4-oam-address,operational-status",uniqueProps="hostname",container="pservers",namespace="cloud-infrastructure",uriTemplate="/cloud-infrastructure/pservers/pserver/{hostname}",requiredProps="hostname,in-maint")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="hostname" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Value from executing hostname on the compute node.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ptnii-equip-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="PTNII name")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="number-of-cpus" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Number of cpus")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="disk-in-gigabytes" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Disk size, in GBs")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ram-in-megabytes" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="RAM size, in MBs")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="equip-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Equipment type. Source of truth should define valid values.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="equip-vendor" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Equipment vendor. Source of truth should define valid values.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="equip-model" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Equipment model. Source of truth should define valid values.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="fqdn" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Fully-qualified domain name")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="pserver-selflink" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="URL to endpoint where AAI can get more details")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ipv4-oam-address" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used to configure device, also used for troubleshooting and is IP used for traps generated by device.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="serial-number" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Serial number, may be queried")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ipaddress-v4-loopback-0" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="IPV4 Loopback 0 address")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ipaddress-v6-loopback-0" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="IPV6 Loopback 0 address")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ipaddress-v4-aim" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="IPV4 AIM address")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ipaddress-v6-aim" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="IPV6 AIM address")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ipaddress-v6-oam" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="IPV6 OAM address")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="inv-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="CANOPI's inventory status. Only set with values exactly as defined by CANOPI.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="pserver-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="ID of Pserver")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="internet-topology" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="internet topology of Pserver")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="in-maint" type="xs:boolean" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(defaultValue="false",description="used to indicate whether or not this object is in maintenance mode (maintenance mode = true). This field (in conjunction with prov-status) is used to suppress alarms and vSCL on VNFs/VMs.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="pserver-name2" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="alternative pserver name")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="purpose" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="purpose of pserver")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="prov-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Prov Status of this device (not under canopi control) Valid values [PREPROV/NVTPROV/PROV]")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="management-option" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Indicates who owns and or manages the device.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="host-profile" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="The host profile that defines the configuration of the pserver.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="role" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="The role performed by the pserver.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="function" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="The function performed by the pserver.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ops-note" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Notes to aid OPs in troubleshooting, such as attribute aliases or additional descriptions/instructions about an object.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="operational-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Indicator for whether the resource is considered operational. Valid values are in-service-path and out-of-service-path.",suggestibleOnSearch="true")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ <xs:element ref="tns:p-interfaces" minOccurs="0"/>
+ <xs:element ref="tns:l-interfaces" minOccurs="0"/>
+ <xs:element ref="tns:lag-interfaces" minOccurs="0"/>
+ <xs:element ref="tns:activities" minOccurs="0"/>
+ <xs:element ref="tns:hpa-capacity" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="pservers">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of compute hosts.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:pserver" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="virtual-data-center">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Virtual organization of cloud infrastructure elements in a data center context",nameProps="vdc-name",indexedProps="vdc-name,vdc-id",container="virtual-data-centers",namespace="cloud-infrastructure",uriTemplate="/cloud-infrastructure/virtual-data-centers/virtual-data-center/{vdc-id}",requiredProps="vdc-id,vdc-name")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="vdc-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Unique ID of the vdc")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vdc-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Name of the virtual data center")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="virtual-data-centers">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Virtual organization of cloud infrastructure elements in a data center context")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:virtual-data-center" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="operational-environment">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="It is a logical partition of the cloud which allows to have multiple environments in the production AIC.",indexedProps="operational-environment-id",nameProps="operational-environment-name",uniqueProps="operational-environment-id",container="operational-environments",namespace="cloud-infrastructure",uriTemplate="/cloud-infrastructure/operational-environments/operational-environment/{operational-environment-id}",requiredProps="operational-environment-id,operational-environment-name,operational-environment-type,operational-environment-status,tenant-context,workload-context")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="operational-environment-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="UUID of an operational environment")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="operational-environment-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Operational Environment name")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="operational-environment-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Operational Environment Type.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="operational-environment-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Status")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="tenant-context" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Tenant Context.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="workload-context" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Workload Context.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="operational-environments">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="a logical partition of the cloud which allows to have multiple environments in the production AIC.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:operational-environment" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="geo-region">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Top level node for a cg-nat geographical region.",indexedProps="geo-region-id",uniqueProps="geo-region-id",container="geo-regions",namespace="cloud-infrastructure",uriTemplate="/cloud-infrastructure/geo-regions/geo-region/{geo-region-id}",requiredProps="geo-region-id")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="geo-region-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="UUID, key for geo-region object.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="geo-region-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Name of geo-region")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="geo-region-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Type of geo-region")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="geo-region-role" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Role of geo-region")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="geo-region-function" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Function of geo-region")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="geo-regions">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of geo-regions")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:geo-region" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="network-technology">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="The network-technology object is used to capture the supported network technologies of a cloud-region.",nameProps="network-technology-id,network-technology-name",uniqueProps="network-technology-id",container="network-technologies",namespace="cloud-infrastructure",uriTemplate="/cloud-infrastructure/network-technologies/network-technology/{network-technology-id}",requiredProps="network-technology-id,network-technology-name")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="network-technology-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Unique identifier of the network-technology object (UUID)")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="network-technology-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="The network-technology that a cloud-region can support. Current valid values- CONTRAIL AIC_SR_IOV OVS STANDARD-SR-IOV")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="network-technologies">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description=" The network-technology object is used to capture the supported network technologies of a cloud-region.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:network-technology" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="cloud-infrastructure">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Namespace for cloud infrastructure.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:complexes" minOccurs="0"/>
+ <xs:element ref="tns:cloud-regions" minOccurs="0"/>
+ <xs:element ref="tns:network-profiles" minOccurs="0"/>
+ <xs:element ref="tns:pservers" minOccurs="0"/>
+ <xs:element ref="tns:virtual-data-centers" minOccurs="0"/>
+ <xs:element ref="tns:operational-environments" minOccurs="0"/>
+ <xs:element ref="tns:geo-regions" minOccurs="0"/>
+ <xs:element ref="tns:network-technologies" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="esr-ems">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Persist EMS address information used by EMS driver.",indexedProps="ems-id",searchable="ems-id",container="esr-ems-list",namespace="external-system",requiredProps="ems-id",uriTemplate="/external-system/esr-ems-list/esr-ems/{ems-id}")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="ems-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Unique ID of EMS.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:esr-system-info-list" minOccurs="0"/>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="esr-ems-list">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(maximumDepth="0")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:esr-ems" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="esr-vnfm">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Persist VNFM address information used by VF-C.",indexedProps="vnfm-id",searchable="vnfm-id",container="esr-vnfm-list",namespace="external-system",requiredProps="vnfm-id",uriTemplate="/external-system/esr-vnfm-list/esr-vnfm/{vnfm-id}")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="vnfm-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Unique ID of VNFM.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vim-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="indecate the VIM to deploy VNF.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="certificate-url" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="certificate url of VNFM.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:esr-system-info-list" minOccurs="0"/>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="esr-vnfm-list">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(maximumDepth="0")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:esr-vnfm" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="esr-nfvo">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Persist NFVO address information used by VF-C.",indexedProps="nfvo-id",searchable="nfvo-id",container="esr-nfvo-list",namespace="external-system",requiredProps="nfvo-id",uriTemplate="/external-system/esr-nfvo-list/esr-nfvo/{nfvo-id}")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="nfvo-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Unique ID of nfvo.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="api-root" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="indecate the api-root.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:esr-system-info-list" minOccurs="0"/>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="esr-nfvo-list">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(maximumDepth="0")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:esr-nfvo" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="esr-thirdparty-sdnc">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Persist SDNC address information used by ONAP SDNC.",container="esr-thirdparty-sdnc-list",namespace="external-system",requiredProps="thirdparty-sdnc-id",uriTemplate="/external-system/esr-thirdparty-sdnc-list/esr-thirdparty-sdnc/{thirdparty-sdnc-id}")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="thirdparty-sdnc-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Unique ID of SDNC.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="location" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="used for DC type to indicate the location of SDNC, such as Core or Edge.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="product-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="password used to access SDNC server.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="domain-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Domain type of the SDNC controllerr.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:esr-system-info-list" minOccurs="0"/>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="esr-thirdparty-sdnc-list">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(maximumDepth="0")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:esr-thirdparty-sdnc" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="external-system">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Namespace for external system.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:esr-ems-list" minOccurs="0"/>
+ <xs:element ref="tns:esr-vnfm-list" minOccurs="0"/>
+ <xs:element ref="tns:esr-nfvo-list" minOccurs="0"/>
+ <xs:element ref="tns:esr-thirdparty-sdnc-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="connector">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of resource instances used to connect a variety of disparate inventory widgets",indexedProps="resource-instance-id,model-invariant-id,model-version-id,widget-model-id,widget-model-version",container="connectors",namespace="business",uriTemplate="/business/connectors/connector/{resource-instance-id}",requiredProps="resource-instance-id")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="resource-instance-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Unique id of resource instance.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-invariant-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="the ASDC model id for this resource or service model.",visibility="deployment",requires="model-version-id",dbAlias="model-invariant-id-local")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-version-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="the ASDC model version for this resource or service model.",visibility="deployment",requires="model-invariant-id",dbAlias="model-version-id-local",privateEdge="service-design-and-creation/models/model/{model-invariant-id}/model-vers/model-ver/{model-version-id}")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="widget-model-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="the ASDC data dictionary widget model. This maps directly to the A&amp;AI widget.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="widget-model-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="the ASDC data dictionary version of the widget model.This maps directly to the A&amp;AI version of the widget.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ <xs:element ref="tns:metadata" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="connectors">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of resource instances used to connect a variety of disparate inventory widgets")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:connector" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="tunnel-xconnect">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Represents the specifics of a tunnel cross connect piece of a resource that gets separately allotted",uniqueProps="id",indexedProps="id",dependentOn="allotted-resource",container="tunnel-xconnects",uriTemplate="/tunnel-xconnects/tunnel-xconnect/{id}",requiredProps="id")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Allotted Resource id UUID assigned to this instance.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Concurrency value")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="tunnel-xconnects">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="This object is used to store the specific tunnel cross connect aspects of an allotted resource")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:tunnel-xconnect" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="allotted-resource">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Represents a slice or partial piece of a resource that gets separately allotted",nameProps="description,allotted-resource-name",uniqueProps="id",indexedProps="id,model-invariant-id,model-version-id,type,role,allotted-resource-name,access-provider-id,access-client-id,access-topology-id,access-node-id,access-ltp-id,vpn-name,orchestration-status",dependentOn="service-instance",container="allotted-resources",uriTemplate="/allotted-resources/allotted-resource/{id}",requiredProps="id")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Allotted Resource id UUID assigned to this instance.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="description" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="The descriptive information assigned to this allotted resource instance")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="selflink" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Link back to more information in the controller")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-invariant-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="the ASDC model id for this resource or service model.",visibility="deployment",requires="model-version-id",dbAlias="model-invariant-id-local")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-version-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="the ASDC model version for this resource or service model.",visibility="deployment",requires="model-invariant-id",dbAlias="model-version-id-local",privateEdge="service-design-and-creation/models/model/{model-invariant-id}/model-vers/model-ver/{model-version-id}")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Concurrency value")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="orchestration-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Orchestration status")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="operational-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Indicator for whether the resource is considered operational")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Generic description of the type of allotted resource.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="role" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="role in the network that this resource will be providing.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="allotted-resource-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the name of this allotted-resource.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="access-provider-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the id of the access provider of this allotted-resource.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="access-client-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the id of the access client of this allotted-resource.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="access-topology-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the id of the access topology of this allotted-resource.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="access-node-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the id of the access node of this allotted-resource.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="access-ltp-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the id of the access ltp of this allotted-resource.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="cvlan" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the cvlan of this allotted-resource.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vpn-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the vpn-name of this allotted-resource.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:tunnel-xconnects" minOccurs="0"/>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="allotted-resources">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="This object is used to store slices of services being offered")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:allotted-resource" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="communication-service-profile">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Requirement of comunication service.",uniqueProps="profile-id",indexedProps="profile-id",container="communication-service-profiles",dependentOn="service-instance",uriTemplate="/service-instances/service-instance/{service-instance-id}/communication-service-profiles/communication-service-profile/{profile-id}",searcheable="profile-id")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="profile-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="ID of the profile.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="max-number-of-UEs" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="The maximum number of UEs may simultaneously access the communication service")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="coverage-area-list" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="A list of TrackingAreas where the NSI can be selected.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="latency" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="The packet transmission latency (millisecond) through the RAN, CN, and TN part of 5G network and is used to evaluate utilization performance of the end-to-end network slice instance.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="exp-data-rate-UL" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="User experience data rate of upload.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="exp-data-rate-DL" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="User experience data rate of download.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ue-mobility-level" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="User mobility level, value can be stationary, nomadic, restricted mobility, fully mobility.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-sharing-level" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Whether the resources to be allocated to the network slice instance may be shared with another network slice instance(s).")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="communication-service-profiles">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of communication service profile.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:communication-service-profile" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="service-profile">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Requirement of E2E Slice service.",uniqueProps="profile-id",indexedProps="profile-id",container="service-profiles",dependentOn="service-instance",uriTemplate="/service-instances/service-instance/{service-instance-id}/service-profiles/service-profile/{profile-id}",searcheable="profile-id")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="profile-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="ID of the profile.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="latency" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="The packet transmission latency (millisecond) through the RAN, CN, and TN part of 5G network and is used to evaluate utilization performance of the end-to-end network slice instance.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="max-number-of-UEs" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="The maximum number of UEs may simultaneously access the E2E slice service")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="coverage-area-TA-list" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="A list of TrackingAreas where the NSI can be selected.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ue-mobility-level" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="User mobility level, value can be stationary, nomadic, restricted mobility, fully mobility.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-sharing-level" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Whether the resources to be allocated to the network slice instance may be shared with another network slice instance(s).")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="activity-factor" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Percentage value of the amount of simultaneous active UEs to the total number of UEs where active means the UEs are exchanging data with the network.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="jitter" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="The jitter requirements of network slice.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="survival-time" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="An attribute specifies the time that an application consuming a communication service may continue without an anticipated message.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="availability" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="This parameter specifies the availability requirement, expressed as a percentage.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="reliability" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="An attribute specifies in the context of network layer packet transmissions, percentage value of the amount of sent network layer packets successfully delivered to a given system entity within the time constraint required by the targeted service, divided by the total number of sent network layer packets.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="dl-thpt-per-slice" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="This attribute defines achievable data rate of the network slice in downlink that is available ubiquitously across the coverage area of the slice.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="dl-thpt-per-UE" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="This attribute defines downlink data rate supported by the network slice per UE.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ul-thpt-per-slice" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="This attribute defines achievable data rate of the network slice in uplink that is available ubiquitously across the coverage area of the slice.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ul-thpt-per-UE" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="This attribute defines uplink data rate supported by the network slice per UE.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="max-pkt-size" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="This parameter specifies the maximum packet size supported by the network slice.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="max-number-of-conns" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="This parameter defines the maximum number of concurrent sessions supported by the network slice.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="term-density" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="An attribute specifies the overall user density over the coverage area of the network slice.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="service-profiles">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of E2E slice service profile.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:service-profile" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="slice-profile">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Requirement of network slice subnet service.",uniqueProps="profile-id",indexedProps="profile-id",container="slice-profiles",dependentOn="service-instance",uriTemplate="/service-instances/service-instance/{service-instance-id}/slice-profiles/slice-profile/{profile-id}",searcheable="profile-id")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="profile-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="ID of the profile.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="latency" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="The packet transmission latency (millisecond) through the RAN or CN or TN and is used to evaluate utilization performance of the end-to-end network slice instance.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="max-number-of-UEs" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="The maximum number of UEs may simultaneously access the slice subnet service")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="coverage-area-TA-list" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="A list of TrackingAreas where the NSSI can be selected.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ue-mobility-level" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="User mobility level, value can be stationary, nomadic, restricted mobility, fully mobility.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-sharing-level" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Whether the resources to be allocated to the slice subnet instance may be shared with another network slice instance(s).")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="exp-data-rate-UL" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="User experience data rate of upload.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="exp-data-rate-DL" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="User experience data rate of download.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="area-traffic-cap-UL" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="The area traffic capbility of upload.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="area-traffic-cap-DL" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="The area traffic capbility of download.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="activity-factor" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="An attribute specfies the percentage value of the amount of simultaneous active UEs to the total number of UEs where active means the UEs are exchanging data with the network.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="jitter" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="The jitter requirements of network slice subnet.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="survival-time" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Survival time for network slice subnet.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="cs-availability-target" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Communication service availability target value.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="max-bandwidth" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Maxmun bandwidth value of TN network.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="exp-data-rate" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Expected date rate for uRLLC.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="max-number-of-PDU-session" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="maxNumberofPDUSession Integer 1 The maximum number of PDU sessions that can simultaneously/concurrently access to the network slice.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="overall-user-density" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Overall User Density.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="cs-reliability-mean-time" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Communication service reliability mean time between failures.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="msg-size-byte" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Message size(byte) .")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="transfer-interval-target" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="transferIntervalTarget String 1 Target value of transfer interval.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="slice-profiles">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of slice subnet service profile.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:slice-profile" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="service-instance">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Instance of a service",indexedProps="service-instance-id,model-invariant-id,model-version-id,widget-model-id,widget-model-version,service-instance-name,service-instance-location-id,orchestration-status,environment-context,workload-context",nameProps="service-instance-name",searchable="service-instance-id,service-instance-name,operational-status",uniqueProps="service-instance-id",dependentOn="service-subscription",container="service-instances",uriTemplate="/service-instances/service-instance/{service-instance-id}",requiredProps="service-instance-id")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="service-instance-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Uniquely identifies this instance of a service")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="service-instance-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="This field will store a name assigned to the service-instance.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="service-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="String capturing type of service.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="service-role" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="String capturing the service role.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="service-rate" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Rate of the service instance.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="service-layer" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Definition of the service layer.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="due-date" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Due date of the service creation.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="end-date" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="End date of the service creation.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="environment-context" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="This field will store the environment context assigned to the service-instance.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="workload-context" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="This field will store the workload context assigned to the service-instance.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="created-at" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="create time of Network Service.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="updated-at" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="last update of Network Service.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="description" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="short description for service-instance.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-invariant-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="the ASDC model id for this resource or service model.",visibility="deployment",requires="model-version-id",dbAlias="model-invariant-id-local")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-version-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="the ASDC model version for this resource or service model.",visibility="deployment",requires="model-invariant-id",dbAlias="model-version-id-local",privateEdge="service-design-and-creation/models/model/{model-invariant-id}/model-vers/model-ver/{model-version-id}")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="persona-model-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="the ASDC model version for this resource or service model.",visibility="internal",dataCopy="service-design-and-creation/models/model/{model-invariant-id}/model-vers/model-ver/{model-version-id}#model-version")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="widget-model-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="the ASDC data dictionary widget model. This maps directly to the A&amp;AI widget.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="widget-model-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="the ASDC data dictionary version of the widget model.This maps directly to the A&amp;AI version of the widget.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="bandwidth-total" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Indicates the total bandwidth to be used for this service.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="bandwidth-up-wan1" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="indicates the upstream bandwidth this service will use on the WAN1 port of the physical device.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="bandwidth-down-wan1" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="indicates the downstream bandwidth this service will use on the WAN1 port of the physical device.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="bandwidth-up-wan2" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="indicates the upstream bandwidth this service will use on the WAN2 port of the physical device.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="bandwidth-down-wan2" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="indicates the downstream bandwidth this service will use on the WAN2 port of the physical device.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vhn-portal-url" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="URL customers will use to access the vHN Portal.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="service-instance-location-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="An identifier that customers assign to the location where this service is being used.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="selflink" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Path to the controller object.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="orchestration-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Orchestration status of this service.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="input-parameters" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="String capturing request parameters from SO to pass to Closed Loop.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="service-function" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="String capturing function of the service.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ <xs:element ref="tns:metadata" minOccurs="0"/>
+ <xs:element ref="tns:allotted-resources" minOccurs="0"/>
+ <xs:element ref="tns:communication-service-profiles" minOccurs="0"/>
+ <xs:element ref="tns:service-profiles" minOccurs="0"/>
+ <xs:element ref="tns:slice-profiles" minOccurs="0"/>
+ <xs:element name="operational-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Indicator for whether the resource is considered operational. Valid values are in-service-path and out-of-service-path.",suggestibleOnSearch="true")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="service-instances">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of service instances")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:service-instance" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="service-subscription">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Object that group service instances.",indexedProps="service-type",dependentOn="customer",container="service-subscriptions",crossEntityReference="service-instance,service-type",uriTemplate="/service-subscriptions/service-subscription/{service-type}",requiredProps="service-type")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="service-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Value defined by orchestration to identify this service across ONAP.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="temp-ub-sub-account-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="This property will be deleted from A&amp;AI in the near future. Only stop gap solution.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:service-instances" minOccurs="0"/>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="service-subscriptions">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of objects that group service instances.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:service-subscription" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="customer">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="customer identifiers to provide linkage back to BSS information.",nameProps="subscriber-name",indexedProps="subscriber-name,global-customer-id,subscriber-type",searchable="global-customer-id,subscriber-name",uniqueProps="global-customer-id",container="customers",namespace="business",uriTemplate="/business/customers/customer/{global-customer-id}",requiredProps="global-customer-id,subscriber-name,subscriber-type")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="global-customer-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Global customer id used across ONAP to uniquely identify customer.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="subscriber-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Subscriber name, an alternate way to retrieve a customer.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="subscriber-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Subscriber type, a way to provide VID with only the INFRA customers.",defaultValue="CUST")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:service-subscriptions" minOccurs="0"/>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="customers">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of customer identifiers to provide linkage back to BSS information.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:customer" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="line-of-business">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="describes a line-of-business",indexedProps="line-of-business-name",uniqueProps="line-of-business-name",container="lines-of-business",namespace="business",uriTemplate="/business/lines-of-business/line-of-business/{line-of-business-name}",requiredProps="line-of-business-name")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="line-of-business-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Name of the line-of-business (product)")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="lines-of-business">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of lines-of-business")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:line-of-business" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="owning-entity">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="describes an owning-entity",indexedProps="owning-entity-id,owning-entity-name",searchable="owning-entity-id",uniqueProps="owning-entity-id,owning-entity-name",container="owning-entities",namespace="business",uriTemplate="/business/owning-entities/owning-entity/{owning-entity-id}",requiredProps="owning-entity-id,owning-entity-name")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="owning-entity-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="UUID of an owning entity")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="owning-entity-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Owning entity name")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="owning-entities">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of owning-entities")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:owning-entity" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="platform">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="describes a platform",indexedProps="platform-name",uniqueProps="platform-name",container="platforms",namespace="business",uriTemplate="/business/platforms/platform/{platform-name}",requiredProps="platform-name")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="platform-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Name of the platform")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="platforms">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of platforms")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:platform" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="project">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="describes the project",indexedProps="project-name",uniqueProps="project-name",container="projects",namespace="business",uriTemplate="/business/projects/project/{project-name}",requiredProps="project-name")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="project-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Name of the project deploying a service")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="project-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Type of project (ex, VPMO)")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="project-state" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Current state of the project.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="description" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Description of the project.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="projects">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of projects")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:project" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="sp-partner">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Instance of an sp-partner",indexedProps="sp-partner-id,url,callsource,model-invariant-id,model-version-id",nameProps="sp-partner-id",searchable="sp-partner-id",uniqueProps="sp-partner-id",container="sp-partners",namespace="business",uriTemplate="/business/sp-partners/sp-partner/{sp-partner-id}",requiredProps="sp-partner-id")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="sp-partner-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Uniquely identifies this sp-partner by id")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="url" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the URL of this sp-partner.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="callsource" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the callsource of this sp-partner.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="operational-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the operational-status for this sp-partner.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-customization-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the model-customization-id for this sp-partner.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-invariant-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="the ASDC model id for this sp-partner model.",visibility="deployment",requires="model-version-id",dbAlias="model-invariant-id-local")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-version-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="the ASDC model version for this sp-partner model.",visibility="deployment",requires="model-invariant-id",dbAlias="model-version-id-local",privateEdge="service-design-and-creation/models/model/{model-invariant-id}/model-vers/model-ver/{model-version-id}")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="sp-partners">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of sp-partners")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:sp-partner" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="business">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Namespace for business related constructs")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:connectors" minOccurs="0"/>
+ <xs:element ref="tns:customers" minOccurs="0"/>
+ <xs:element ref="tns:lines-of-business" minOccurs="0"/>
+ <xs:element ref="tns:owning-entities" minOccurs="0"/>
+ <xs:element ref="tns:platforms" minOccurs="0"/>
+ <xs:element ref="tns:projects" minOccurs="0"/>
+ <xs:element ref="tns:sp-partners" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vnf-image">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Image object that pertain to a VNF that doesn't have associated vservers. This is a kludge.",indexedProps="application,vnf-image-uuid,application-vendor,application-version",uniqueProps="vnf-image-uuid",container="vnf-images",namespace="service-design-and-creation",uriTemplate="/service-design-and-creation/vnf-images/vnf-image/{vnf-image-uuid}",requiredProps="vnf-image-uuid,application,application-vendor")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="vnf-image-uuid" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Unique ID of this asset")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="application" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="The application that the image instantiates.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="application-vendor" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="The vendor of the application.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="application-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="The version of the application.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="selflink" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="URL to endpoint where AAI can get more details")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vnf-images">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of image objects that pertain to a VNF that doesn't have associated vservers. This is a kludge.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:vnf-image" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="service">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Stand-in for service model definitions. Likely to be deprecated in favor of models from ASDC. Does not strictly map to ASDC services.",indexedProps="service-description,service-id",container="services",namespace="service-design-and-creation",uriTemplate="/service-design-and-creation/services/service/{service-id}",requiredProps="service-id,service-description")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="service-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="This gets defined by others to provide a unique ID for the service, we accept what is sent.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="service-description" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Description of the service")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="service-selflink" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="URL to endpoint where AAI can get more details")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="service-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="service version")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="services">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of service model definitions. Likely to be deprecated in favor of models from ASDC.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:service" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="service-capability">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Early definition of server/resource pairings, likely to be replaced by models. No new use should be made of this.",indexedProps="service-type,vnf-type",container="service-capabilities",namespace="service-design-and-creation",uriTemplate="/service-design-and-creation/service-capabilities/service-capability/{service-type}/{vnf-type}",requiredProps="service-type,vnf-type")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="service-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="This gets defined by others to provide a unique ID for the service, we accept what is sent.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vnf-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="String capturing type of vnf, that was intended to identify the SDC resource. This field has been overloaded in service-specific ways and clients should expect changes to occur in the future to this field as ONAP matures.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="service-capabilities">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of service capabilities.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:service-capability" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="element-choice-set">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="This is how we would capture constraints defining allowed sets of elements.",uniqueProps="element-choice-set-uuid",indexedProps="element-choice-set-uuid",allowDirectRead="true",allowDirectWrite="false",dependentOn="constrained-element-set",container="element-choice-sets",uriTemplate="/element-choice-sets/element-choice-set/{element-choice-set-uuid}",requiredProps="element-choice-set-uuid,element-choice-set-name")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="element-choice-set-uuid" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,autoGenerateUuid="true")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="element-choice-set-name" type="xs:string" minOccurs="0"/>
+ <xs:element name="cardinality" type="xs:string" minOccurs="0"/>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0"/>
+ <xs:element ref="tns:model-elements" minOccurs="0"/>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="element-choice-sets">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="tns:element-choice-set" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="constrained-element-set">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="This is how we would capture constraints defining allowed sets of elements.",uniqueProps="constrained-element-set-uuid",indexedProps="constrained-element-set-uuid",allowDirectRead="true",allowDirectWrite="false",dependentOn="model-constraint,model-element",container="constrained-element-sets",uriTemplate="/constrained-element-sets/constrained-element-set/{constrained-element-set-uuid}",requiredProps="constrained-element-set-uuid,constraint-type,check-type")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="constrained-element-set-uuid" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,autoGenerateUuid="true")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="constraint-type" type="xs:string" minOccurs="0"/>
+ <xs:element name="check-type" type="xs:string" minOccurs="0"/>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0"/>
+ <xs:element ref="tns:element-choice-sets" minOccurs="0"/>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="constrained-element-sets">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="tns:constrained-element-set" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="model-constraint">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="This is how we would capture constraints defining allowed sets of elements.",uniqueProps="model-constraint-uuid",indexedProps="model-constraint-uuid",allowDirectRead="true",allowDirectWrite="false",dependentOn="model-element",container="model-constraints",uriTemplate="/model-constraints/model-constraint/{model-constraint-uuid}",requiredProps="model-constraint-uuid,constrained-element-set-uuid-to-replace")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="model-constraint-uuid" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,autoGenerateUuid="true")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="constrained-element-set-uuid-to-replace" type="xs:string" minOccurs="0"/>
+ <xs:element ref="tns:constrained-element-sets" minOccurs="0"/>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="model-constraints">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="tns:model-constraint" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="model-element">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Defines how other models combine to make up a higher-level model.",uniqueProps="model-element-uuid",indexedProps="model-element-uuid",allowDirectRead="true",dependentOn="element-choice-set,model-element,model-ver",allowDirectWrite="false",container="model-elements",uriTemplate="/model-elements/model-element/{model-element-uuid}",requiredProps="model-element-uuid,new-data-del-flag,cardinality")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="model-element-uuid" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,autoGenerateUuid="true")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="new-data-del-flag" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Indicates whether this element was created as part of instantiation from this model")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="cardinality" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="How many of this type of element are required/allowed")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="linkage-points" type="xs:string" minOccurs="0" maxOccurs="5000"/>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:model-elements" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Defines how other models combine to make up a higher-level model")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:model-constraints" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Describes new constraints on this model element that are not part of that model's definition")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="model-elements">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="tns:model-element" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="model-ver">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Subgraph definition provided by ASDC to describe a specific version of an inventory asset and its connections related to ASDC models",nameProps="model-name",indexedProps="model-version-id,model-name,model-version,distribution-status",uniqueProps="model-version-id",dependentOn="model",container="model-vers",uriTemplate="/model-vers/model-ver/{model-version-id}",requiredProps="model-version-id,model-name,model-version")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="model-version-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Unique identifier corresponding to one version of a model in ASDC")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Name of the model, which can change from version to version.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Version")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="distribution-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Distribution Status")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-description" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Description")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="sdnc-model-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="The CDS blue print name associated with the resource.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="sdnc-model-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="The version of the CDS blue print.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:model-elements" minOccurs="0"/>
+ <xs:element ref="tns:metadata" minOccurs="0"/>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="model-vers">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="tns:model-ver" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="model">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Subgraph definition provided by ASDC to describe an inventory asset and its connections related to ASDC models, independent of version",nameProps="model-type",indexedProps="model-invariant-id,model-type",uniqueProps="model-invariant-id",container="models",namespace="service-design-and-creation",uriTemplate="/service-design-and-creation/models/model/{model-invariant-id}",requiredProps="model-invariant-id,model-type")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="model-invariant-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Unique identifier corresponding to the main definition of a model in ASDC")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Type of the model, e.g., service, resource, widget, etc.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-role" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Role of the model,e.g.,NST,NSST,CST,etc")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:model-vers" minOccurs="0"/>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="models">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of subgraph definitions provided by ASDC to describe the inventory assets and their connections related to ASDC models")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:model" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="related-lookup">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="TBD",uniqueProps="related-lookup-uuid",indexedProps="related-lookup-uuid",allowDirectRead="true",allowDirectWrite="false",dependentOn="named-query-element",container="related-lookups",requiredProps="related-lookup-uuid,source-node-type,source-node-property,target-node-type,target-node-property",uriTemplate="/related-lookups/related-lookup/{related-lookup-uuid}")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="related-lookup-uuid" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,autoGenerateUuid="true")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="source-node-type" type="xs:string" minOccurs="0"/>
+ <xs:element name="source-node-property" type="xs:string" minOccurs="0"/>
+ <xs:element name="target-node-type" type="xs:string" minOccurs="0"/>
+ <xs:element name="target-node-property" type="xs:string" minOccurs="0"/>
+ <xs:element name="property-collect-list" type="xs:string" minOccurs="0" maxOccurs="5000"/>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0"/>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="related-lookups">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="tns:related-lookup" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="property-constraint">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="TBD",uniqueProps="property-constraint-uuid",indexedProps="property-constraint-uuid",allowDirectRead="true",allowDirectWrite="false",dependentOn="named-query-element",container="property-constraints",requiredProps="property-constraint-uuid,constraint-type,property-name,property-value",uriTemplate="/property-constraints/property-constraint/{property-constraint-uuid}")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="property-constraint-uuid" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,autoGenerateUuid="true")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="constraint-type" type="xs:string" minOccurs="0"/>
+ <xs:element name="property-name" type="xs:string" minOccurs="0"/>
+ <xs:element name="property-value" type="xs:string" minOccurs="0"/>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="property-constraints">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="tns:property-constraint" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="named-query-element">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="TBD",uniqueProps="named-query-element-uuid",indexedProps="named-query-element-uuid",allowDirectRead="true",allowDirectWrite="false",dependentOn="named-query,named-query-element",container="named-query-elements",requiredProps="named-query-element-uuid",uriTemplate="/named-query-elements/named-query-element/{named-query-element-uuid}")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="named-query-element-uuid" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,autoGenerateUuid="true")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="property-collect-list" type="xs:string" minOccurs="0" maxOccurs="5000"/>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0"/>
+ <xs:element name="property-limit-desc" type="xs:string" minOccurs="0"/>
+ <xs:element name="do-not-output" type="xs:string" minOccurs="0"/>
+ <xs:element ref="tns:named-query-elements" minOccurs="0"/>
+ <xs:element ref="tns:related-lookups" minOccurs="0"/>
+ <xs:element ref="tns:property-constraints" minOccurs="0"/>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="named-query-elements">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="tns:named-query-element" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="named-query">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="TBD",nameProps="named-query-name",uniqueProps="named-query-uuid",indexedProps="named-query-uuid,named-query-name",container="named-queries",namespace="service-design-and-creation",requiredProps="named-query-uuid,named-query-name,named-query-version",uriTemplate="/service-design-and-creation/named-queries/named-query/{named-query-uuid}")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="named-query-uuid" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true)</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="named-query-name" type="xs:string" minOccurs="0"/>
+ <xs:element name="named-query-version" type="xs:string" minOccurs="0"/>
+ <xs:element name="required-input-params" minOccurs="0">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="required-input-param" type="xs:string" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="description" type="xs:string" minOccurs="0"/>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0"/>
+ <xs:element ref="tns:named-query-elements" minOccurs="0"/>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="named-queries">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="tns:named-query" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="service-design-and-creation">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Namespace for objects managed by ASDC")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:vnf-images" minOccurs="0"/>
+ <xs:element ref="tns:services" minOccurs="0"/>
+ <xs:element ref="tns:service-capabilities" minOccurs="0"/>
+ <xs:element ref="tns:models" minOccurs="0"/>
+ <xs:element ref="tns:named-queries" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="logical-link">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Logical links generally connect l-interfaces but are used to express logical connectivity between two points",indexedProps="link-name,model-invariant-id,model-version-id,widget-model-id,widget-model-version,link-id,prov-status,circuit-id,link-function,link-type,purpose,operational-status",uniqueProps="link-id",container="logical-links",namespace="network",searchable="link-name",uriTemplate="/network/logical-links/logical-link/{link-name}",requiredProps="link-name,in-maint,link-type")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="link-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="e.g., evc-name, or vnf-nameA_interface-nameA_vnf-nameZ_interface-nameZ")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="in-maint" type="xs:boolean" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(defaultValue="false",description="used to indicate whether or not this object is in maintenance mode (maintenance mode = true). This field (in conjunction with prov-status) is used to suppress alarms and vSCL on VNFs/VMs.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="link-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Type of logical link, e.g., evc")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="speed-value" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Captures the numeric part of the speed")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="speed-units" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Captures the units corresponding to the speed")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="available-capacity" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Captures the units corresponding to the speed")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="admin-state" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Captures the administrative state of the link")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ip-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="v4, v6, or ds for dual stack")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="routing-protocol" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="For example, static or BGP")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-invariant-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="the ASDC model id for this resource or service model.",visibility="deployment",requires="model-version-id",dbAlias="model-invariant-id-local")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-version-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="the ASDC model version for this resource or service model.",visibility="deployment",requires="model-invariant-id",dbAlias="model-version-id-local",privateEdge="service-design-and-creation/models/model/{model-invariant-id}/model-vers/model-ver/{model-version-id}")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="widget-model-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="the ASDC data dictionary widget model. This maps directly to the A&amp;AI widget.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="widget-model-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="the ASDC data dictionary version of the widget model.This maps directly to the A&amp;AI version of the widget.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="operational-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Indication of operational status of the logical link.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="prov-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Trigger for operational monitoring of this VNF by BAU Service Assurance systems.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="link-role" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Indication of the network use of the logical link.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="link-name2" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Alias or alternate name (CLCI or D1 name).")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="link-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="UUID of the logical-link, SDNC generates this.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="circuit-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Circuit id")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="purpose" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Reason for this entity, role it is playing")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="link-description" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="A description for the logical-link.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="segment-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="A segment-id assigned to the logical-link (ex, esi for ethernet segments).")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="link-function" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="The function performed by this logical link")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="logical-links">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of logical connections")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:logical-link" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="class-of-service">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(indexedProps="cos",dependentOn="site-pair",container="classes-of-service",uriTemplate="/classes-of-service/class-of-service/{cos}")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="cos" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="unique identifier of probe")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="probe-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="identifier of probe")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="probe-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="type of probe")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="classes-of-service">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="class-of-service of probe")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:class-of-service" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="site-pair">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(indexedProps="site-pair-id",uniqueProps="site-pair-id",dependentOn="routing-instance",container="site-pairs",uriTemplate="/site-pairs/site-pair/{site-pair-id}")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="site-pair-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="unique identifier of probe")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="source-ip" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Prefix address")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="destination-ip" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Prefix address")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ip-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="ip version, v4, v6")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="destination-hostname" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Hostname of the destination equipment to which SLAs are measured against.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="destination-equip-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="The type of destinatination equipment. Could be Router, UCPE, etc.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:classes-of-service" minOccurs="0"/>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="site-pairs">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="probe within a set")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:site-pair" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="routing-instance">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(indexedProps="routing-instance-id",dependentOn="site-pair-set",container="routing-instances",uriTemplate="/routing-instances/routing-instance/{routing-instance-id}")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="routing-instance-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Unique id of routing instance")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="rpm-owner" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="rpm owner")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:site-pairs" minOccurs="0"/>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="routing-instances">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="set of probes related to generic-vnf routing instance")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:routing-instance" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="site-pair-set">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Set of instances for probes used to measure service level agreements",indexedProps="site-pair-set-id",uniqueProps="site-pair-set-id",container="site-pair-sets",namespace="network",uriTemplate="/network/site-pair-sets/site-pair-set/{site-pair-set-id}",requiredProps="site-pair-set-id")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="site-pair-set-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Unique id of site pair set.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:routing-instances" minOccurs="0"/>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="site-pair-sets">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of sets of instances for probes related to generic-vnf")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:site-pair-set" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="route-target">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Route target information",container="route-targets",dependentOn="vpn-binding,vrf",canBeLinked="true",uriTemplate="/route-targets/route-target/{global-route-target}/{route-target-role}",requiredProps="global-route-target,route-target-role")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="global-route-target" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Number used to identify an RT, globally unique in the network")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="route-target-role" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Role assigned to this route target")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="route-targets">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of route target information")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:route-target" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vpn-binding">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="VPN binding",nameProps="vpn-name,vpn-type",indexedProps="vpn-name,vpn-id,vpn-type,access-provider-id,access-client-id,access-topology-id,src-access-node-id,src-access-ltp-id,dst-access-node-id,dst-access-ltp-id,operational-status,model-invariant-id,model-version-id",searchable="vpn-id,vpn-name",uniqueProps="vpn-id",container="vpn-bindings",namespace="network",uriTemplate="/network/vpn-bindings/vpn-binding/{vpn-id}",requiredProps="vpn-id,vpn-name")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="vpn-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="VPN ID, globally unique within A&amp;AI")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vpn-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="VPN Name")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vpn-platform" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="the platform associated with the VPN example AVPN, Mobility")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vpn-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Type of the vpn, should be taken from enumerated/valid values")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vpn-region" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="region of customer vpn")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="customer-vpn-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="id for this customer vpn")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="route-distinguisher" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used to distinguish the distinct VPN routes of separate customers who connect to the provider in an MPLS network.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="access-provider-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the id of the access provider of this vpn.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="access-client-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the id of the access client of this vpn.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="access-topology-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the id of the access topology of this vpn.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="src-access-node-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the id of the src-access-node of this vpn.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="src-access-ltp-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the id of the src-access-ltp of this vpn.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="dst-access-node-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the id of the dst-access-node of this vpn.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="dst-access-ltp-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the id of the dst-access-ltp of this vpn.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="operational-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the operational-status for this object.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-customization-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the model-customization-id for this object.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-invariant-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="the ASDC model id for this resource or service model.",visibility="deployment",requires="model-version-id",dbAlias="model-invariant-id-local")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-version-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="the ASDC model version for this resource or service model.",visibility="deployment",requires="model-invariant-id",dbAlias="model-version-id-local",privateEdge="service-design-and-creation/models/model/{model-invariant-id}/model-vers/model-ver/{model-version-id}")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="max-prefix-v4" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Max prefix for IPv4.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="max-prefix-v6" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Max prefix for IPv6.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="max-prefix-threshold" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Max prefix threshold.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="label-mode-v4" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Label mode for IPv4.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="label-mode-v6" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Label mode for IPv6.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vpn-description" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="The description of the vpn.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vxlan-network-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="A VNI associated with the VPN.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ops-note" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Notes to aid OPs in troubleshooting, such as attribute aliases or additional descriptions/instructions about an object.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="max-path" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="A variable BGP max AS path length.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:route-targets" minOccurs="0"/>
+ <xs:element ref="tns:relationship-list" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="l3-networks relate to vpn-bindings")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vpn-bindings">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="tns:vpn-binding" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vpls-pe">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="VPLS Provider Edge routers.",indexedProps="prov-status,equipment-name",container="vpls-pes",namespace="network",uriTemplate="/network/vpls-pes/vpls-pe/{equipment-name}",requiredProps="equipment-name")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="equipment-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true)</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="prov-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Trigger for operational monitoring of this VNF by BAU Service Assurance systems.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ipv4-oam-address" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Address tail-f uses to configure generic-vnf, also used for troubleshooting and is IP used for traps generated by GenericVnf (v4-loopback0-ip-address).")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="equipment-role" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Client should send valid enumerated value, e.g., VPLS-PE.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vlan-id-outer" type="xs:unsignedInt" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Temporary location for stag to get to VCE")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ <xs:element ref="tns:p-interfaces" minOccurs="0"/>
+ <xs:element ref="tns:lag-interfaces" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vpls-pes">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of VPLS Provider Edge routers")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:vpls-pe" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="multicast-configuration">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(indexedProps="multicast-configuration-id",uniqueProps="multicast-configuration-id",container="multicast-configurations",namespace="network",uriTemplate="/network/multicast-configurations/multicast-configuration/{multicast-configuration-id}")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="multicast-configuration-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Unique id of multicast configuration.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="multicast-protocol" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="protocol of multicast configuration")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="rp-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="rp type of multicast configuration")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="multicast-configurations">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="multicast configuration of generic-vnf ip-address")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:multicast-configuration" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="cvlan-tag-entry">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(dependentOn="port-group",indexedProps="cvlan-tag",container="cvlan-tags",uriTemplate="/cvlan-tags/cvlan-tag/{cvlan-tag}")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="cvlan-tag" type="xs:unsignedInt" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="See mis-na-virtualization-platform.yang")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="cvlan-tags">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="tns:cvlan-tag-entry" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="port-group">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Used to capture the network interfaces of this VCE",nameProps="port-group-name",indexedProps="port-group-id,heat-stack-id,interface-id,switch-name,interface-role,orchestration-status",dependentOn="vce",container="port-groups",uriTemplate="/port-groups/port-group/{interface-id}",requiredProps="interface-id,orchestration-status")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="interface-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Unique ID of the interface")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="neutron-network-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Neutron network id of this Interface")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="neutron-network-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Neutron network name of this Interface")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="interface-role" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Role assigned to this Interface, should use values as defined in ECOMP Yang models.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="port-group-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Unique ID for port group in vmware")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="port-group-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Likely to duplicate value of neutron network name")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="switch-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="DVS or standard switch name (should be non-null for port groups associated with DVS)")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="orchestration-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Orchestration status of this VNF, mastered by MSO")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="heat-stack-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Heat stack id corresponding to this instance, managed by MSO")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="mso-catalog-key" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Corresponds to the SDN-C catalog id used to configure this VCE")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:cvlan-tags" minOccurs="0"/>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="port-groups">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="tns:port-group" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="license">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Metadata for license group.",indexedProps="group-uuid,resource-uuid,project-number,order-number,receipt-date",dependentOn="chassis,generic-vnf,vce",container="licenses",uriTemplate="/licenses/license/{group-uuid}/{resource-uuid}",requiredProps="group-uuid,resource-uuid")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="group-uuid" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Unique ID for the license group the resource belongs to, should be uuid.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-uuid" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Unique ID of a license resource. ")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="project-number" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used to store CFAS or other project numbers.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="order-number" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Order number.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="receipt-date" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Date of receipt.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Concurrency value")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="licenses">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Licenses to be allocated across resources, keyed by group-uuid and resource-uuid, related to license management")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:license" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="entitlement">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Metadata for entitlement group.",indexedProps="group-uuid,resource-uuid",dependentOn="generic-vnf,vce",container="entitlements",uriTemplate="/entitlements/entitlement/{group-uuid}/{resource-uuid}",requiredProps="group-uuid,resource-uuid")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="group-uuid" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Unique ID for the entitlement group the resource comes from, should be uuid.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-uuid" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Unique ID of an entitlement resource. ")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Concurrency value")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="entitlements">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Entitlements, keyed by group-uuid and resource-uuid, related to license management")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:entitlement" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vce">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Virtual Customer Edge Router, used specifically for Gamma. This object is deprecated.",nameProps="vnf-name",indexedProps="vnf-name,vnf-name2,vnf-type,heat-stack-id,vnf-id,regional-resource-zone,vpe-id,prov-status,service-id,orchestration-status",searchable="vnf-id,vnf-name,vnf-name2",uniqueProps="vnf-id",container="vces",namespace="network",extendsFrom="vnf",uriTemplate="/network/vces/vce/{vnf-id}",requiredProps="vnf-id,vnf-name,vnf-type")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="vnf-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Unique id of VNF. This is unique across the graph.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vnf-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Name of VNF.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vnf-name2" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Alternate name of VNF.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vnf-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="String capturing type of vnf, that was intended to identify the SDC resource. This field has been overloaded in service-specific ways and clients should expect changes to occur in the future to this field as ONAP matures.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="service-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Unique identifier of service, does not strictly map to ASDC services, SOON TO BE DEPRECATED.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="regional-resource-zone" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Regional way of organizing pservers, source of truth should define values")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="prov-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Trigger for operational monitoring of this resource by Service Assurance systems.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="operational-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Indicator for whether the resource is considered operational")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="license-key" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="OBSOLETE - do not use")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="equipment-role" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Network role being played by this VNF")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="orchestration-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Orchestration status of this VNF, mastered by MSO")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="heat-stack-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Heat stack id corresponding to this instance, managed by MSO")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="mso-catalog-key" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Corresponds to the SDN-C catalog id used to configure this VCE")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vpe-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Unique ID of VPE connected to this VCE.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="v6-vce-wan-address" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Valid v6 IP address for the WAN Link on this router. Implied length of /64.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ipv4-oam-address" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Address tail-f uses to configure vce, also used for troubleshooting and is IP used for traps generated by VCE.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ipv4-loopback0-address" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Loopback0 address")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="entitlement-resource-uuid" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="OBSOLETE - see child relationships")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:port-groups" minOccurs="0"/>
+ <xs:element ref="tns:licenses" minOccurs="0"/>
+ <xs:element ref="tns:entitlements" minOccurs="0"/>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vces">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of Virtual Customer Edge Routers, used specifically for Gamma. This object is deprecated.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:vce" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="cp">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="| SE group | This object captures the point of attachment from services or resources to a virtual link or network. | A&amp;AI clients for this object are typically: DCAE-DTI, (DMaaP-DCAE,...) |",uniqueProps="cp-instance-id",dependentOn="vnfc",container="cps",uriTemplate="/cps/cp/{cp-instance-id}",requiredProps="cp-instance-id")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="cp-instance-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Unique ID of the connection point.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="port-id" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="port index to represent multiple CPs on VNFC connected to same network.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ <xs:element ref="tns:l3-interface-ipv4-address-list" minOccurs="0" maxOccurs="5000"/>
+ <xs:element ref="tns:l3-interface-ipv6-address-list" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="cps">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of connection points.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:cp" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vnfc">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(indexedProps="vnfc-name,prov-status,nfc-function,nfc-naming-code,ipaddress-v4-oam-vip,is-closed-loop-disabled,group-notation,model-invariant-id,model-version-id,orchestration-status",searchable="vnfc-name",container="vnfcs",namespace="network",uriTemplate="/network/vnfcs/vnfc/{vnfc-name}")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="vnfc-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Unique ID of vnfc.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="nfc-naming-code" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Short code that is used in naming instances of the item being modeled")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="nfc-function" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="English description of function that the specific resource deployment is providing. Assigned as part of the customization of a resource in a service")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="prov-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="prov status of this vnfc")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="orchestration-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Orchestration status of this VNF, mastered by APP-C")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ipaddress-v4-oam-vip" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Oam V4 vip address of this vnfc")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="in-maint" type="xs:boolean" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(defaultValue="false",description="used to indicate whether or not this object is in maintenance mode (maintenance mode = true)")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="is-closed-loop-disabled" type="xs:boolean" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(defaultValue="false",description="used to indicate whether closed loop function is enabled on this node")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="group-notation" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Group notation of VNFC")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-invariant-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="the ASDC model id for this resource or service model.",visibility="deployment",requires="model-version-id",dbAlias="model-invariant-id-local")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-version-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="the ASDC model version for this resource or service model.",visibility="deployment",requires="model-invariant-id",dbAlias="model-version-id-local")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-customization-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="captures the id of all the configuration used to customize the resource for the service.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ <xs:element ref="tns:cps" minOccurs="0"/>
+ <xs:element ref="tns:l3-interface-ipv4-address-list" minOccurs="0" maxOccurs="5000"/>
+ <xs:element ref="tns:l3-interface-ipv6-address-list" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vnfcs">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="virtual network components associated with a vserver from application controller.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:vnfc" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="host-route">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(indexedProps="host-route-id",dependentOn="subnet",container="host-routes",uriTemplate="/host-routes/host-route/{host-route-id}")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="host-route-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="host-route id")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="route-prefix" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="subnet prefix")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="next-hop" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Could be ip-address, hostname, or service-instance")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="next-hop-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Should be ip-address, hostname, or service-instance to match next-hop")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="metric" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Value that is assigned to an IP route for a particular network interface that identifies the cost that is associated with using that route.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="host-routes">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="tns:host-route" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="address-family">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Definition of address family",indexedProps="address-family-id,af-type",nameProps="address-family-id,af-type",dependentOn="bgp-group,bgp-neighbor",container="address-families",uriTemplate="/address-families/address-family/{address-family-id}",requiredProps="address-family-id,af-type")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="address-family-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="address family UUID.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="af-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="address family type (aka afi)")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="af-subtype" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="address family subtype (aka safi)")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="af-role" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="role of address-family")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="af-function" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="function of address-family")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="address-families">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="tns:address-family" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="bgp-neighbor">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Definition of bgp-neighbor",indexedProps="bgp-neighbor-id",dependentOn="pnf,vrf,subnet,generic-vnf",nameProps="bgp-neighbor-id",container="bgp-neighbors",uriTemplate="/bgp-neighbors/bgp-neighbor/{bgp-neighbor-id}",requiredProps="bgp-neighbor-id,bgp-neighbor-type")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="bgp-neighbor-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="UUID.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="bgp-neighbor-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="name of bgp-group")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="bgp-neighbor-role" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="type of bgp-group")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="bgp-neighbor-function" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="role of bgp-group")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="local-as" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="local a-s number type of vrf (bridge-domain as an example)")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="local-address" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="local address")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="peer-as" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="peer a-s number")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="peer-address" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="peer address")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="description" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="description of bgp-group")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ops-note" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Notes to aid OPs in troubleshooting, such as attribute aliases or additional descriptions/instructions about an object.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="prov-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="provisioning status. Valid values can be found at (https://wiki.web.att.com/display/SPTIIRP/prov-status).")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="peer-hostname" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="hostname of the peer")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ <xs:element ref="tns:address-families" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="bgp-neighbors">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="tns:bgp-neighbor" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="subnet">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(indexedProps="subnet-id,subnet-name,subnet-type,subnet-function,orchestration-status",nameProps="subnet-name",uniqueProps="subnet-id",dependentOn="l3-network,zone",container="subnets",uriTemplate="/subnets/subnet/{subnet-id}",requiredProps="subnet-id")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="subnet-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Subnet ID, should be UUID.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="subnet-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Name associated with the subnet.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="neutron-subnet-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Neutron id of this subnet")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="gateway-address" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="gateway ip address")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="network-start-address" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="network start address")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="cidr-mask" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="cidr mask")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ip-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="ip version")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="orchestration-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Orchestration status of this VNF, mastered by MSO")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="description" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="text used for documentation")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="dhcp-enabled" type="xs:boolean" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(defaultValue="false",description="dhcp enabled")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="dhcp-start" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="the start address reserved for use by dhcp")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="dhcp-end" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="the last address reserved for use by dhcp")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="subnet-role" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="role of the subnet, referenced when assigning IPs")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="subnet-model" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="subnet model BGP, VRPP")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ops-note" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Notes to aid OPs in troubleshooting, such as attribute aliases or additional descriptions/instructions about an object.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="subnet-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Subtype used to categorize this physical link")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="subnet-function" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="The function performed by this Linterface")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ip-assignment-direction" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="ip address assignment direction of the subnet")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="subnet-sequence" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="sequence of the subnet")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:host-routes" minOccurs="0"/>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ <xs:element ref="tns:bgp-neighbors" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="subnets">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="tns:subnet" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="ctag-assignment">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(indexedProps="vlan-id-inner",dependentOn="l3-network",container="ctag-assignments",uriTemplate="/ctag-assignments/ctag-assignment/{vlan-id-inner}")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="vlan-id-inner" type="xs:unsignedInt" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="id.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="ctag-assignments">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="tns:ctag-assignment" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="segmentation-assignment">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Openstack segmentation assignment.",indexedProps="segmentation-id",dependentOn="l3-network",container="segmentation-assignments",uriTemplate="/segmentation-assignments/segmentation-assignment/{segmentation-id}",requiredProps="segmentation-id")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="segmentation-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Route Table Reference id, UUID assigned to this instance.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Concurrency value")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="segmentation-assignments">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of openstack segmentation assignments")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:segmentation-assignment" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="aggregate-route">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Aggregate route configs are used on the D2 IPE’s for the Voice services. In 1902, SDNC will create aggregate-route objects and write them to A&amp;AI. ",uniqueProps="agg-route-id",container="aggregate-routes",dependentOn="vrf,l3-network",uriTemplate="/aggregate-routes/aggregate-route/{agg-route-id}",requiredProps="agg-route-id")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="agg-route-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Route UUID.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="network-start-address" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Name of the forwarding-path")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="cidr-mask" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="CIDR-mask for aggregate route subnet")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ip-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Identifies is aggregate route is ipv4 or ipv6")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="aggregate-routes">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of aggregate routes.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:aggregate-route" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="l3-network">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Generic network definition",nameProps="network-name",indexedProps="heat-stack-id,service-id,network-id,network-name,model-invariant-id,model-version-id,widget-model-id,widget-model-version,contrail-network-fqdn,network-role,network-function,orchestration-status",searchable="network-id,network-name",uniqueProps="network-id",container="l3-networks",namespace="network",uriTemplate="/network/l3-networks/l3-network/{network-id}",requiredProps="network-id,is-bound-to-vpn,is-provider-network,is-shared-network,is-external-network")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="network-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Network ID, should be uuid. Unique across A&amp;AI.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="network-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Name of the network, governed by some naming convention..")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="network-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Type of the network - who defines these values?")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="network-role" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Role the network plans - who defines these values?")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="network-technology" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Network technology - who defines these values?")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="description" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="text used for documentation")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="neutron-network-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Neutron network id of this Interface")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="is-bound-to-vpn" type="xs:boolean" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(defaultValue="false",description="Set to true if bound to VPN")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="service-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Unique identifier of service from ASDC. Does not strictly map to ASDC services. SOON TO BE DEPRECATED")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="network-role-instance" type="xs:unsignedInt" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="network role instance")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="orchestration-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Orchestration status of this VNF, mastered by MSO")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="heat-stack-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Heat stack id corresponding to this instance, managed by MSO")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="mso-catalog-key" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Corresponds to the SDN-C catalog id used to configure this VCE")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="contrail-network-fqdn" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Contrail FQDN for the network")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-invariant-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="the ASDC model id for this resource or service model.",visibility="deployment",requires="model-version-id",dbAlias="model-invariant-id-local")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-version-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="the ASDC model version for this resource or service model.",visibility="deployment",requires="model-invariant-id",dbAlias="model-version-id-local",privateEdge="service-design-and-creation/models/model/{model-invariant-id}/model-vers/model-ver/{model-version-id}")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="persona-model-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="the ASDC model version for this resource or service model.",visibility="internal",dataCopy="service-design-and-creation/models/model/{model-invariant-id}/model-vers/model-ver/{model-version-id}#model-version")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-customization-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="captures the id of all the configuration used to customize the resource for the service.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="widget-model-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="the ASDC data dictionary widget model. This maps directly to the A&amp;AI widget.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="widget-model-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="the ASDC data dictionary version of the widget model.This maps directly to the A&amp;AI version of the widget.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="physical-network-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Name associated with the physical network.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="is-provider-network" type="xs:boolean" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(defaultValue="false",description="boolean indicatating whether or not network is a provider network.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="is-shared-network" type="xs:boolean" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(defaultValue="false",description="boolean indicatating whether or not network is a shared network.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="is-external-network" type="xs:boolean" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(defaultValue="false",description="boolean indicatating whether or not network is an external network.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="selflink" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Path to the controller object.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="operational-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Indicator for whether the resource is considered operational.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="is-trunked" type="xs:boolean" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(defaultValue="false",description="Trunked network indication.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ops-note" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Notes to aid OPs in troubleshooting, such as attribute aliases or additional descriptions/instructions about an object.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="network-function" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="The function performed by this l3 network")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:subnets" minOccurs="0"/>
+ <xs:element ref="tns:ctag-assignments" minOccurs="0"/>
+ <xs:element ref="tns:segmentation-assignments" minOccurs="0"/>
+ <xs:element ref="tns:aggregate-routes" minOccurs="0"/>
+ <xs:element ref="tns:relationship-list" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Relates to tenant (or is it a child of tenant), complex, service, vpn-binding")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="l3-networks">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="tns:l3-network" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="network-policy">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(nameProps="network-policy-fqdn",indexedProps="network-policy-id,network-policy-fqdn",searchable="network-policy-id,network-policy-fqdn",uniqueProps="network-policy-id",container="network-policies",namespace="network",uriTemplate="/network/network-policies/network-policy/{network-policy-id}")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="network-policy-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="UUID representing unique key to this instance")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="network-policy-fqdn" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Contrail FQDN for the policy")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="heat-stack-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="ID for the openStack Heat instance")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Name of the policy")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Type of the policy")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="latency" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="The packet transmission latency (millisecond) through the Transport slice connections and is used to evaluate utilization performance of the end-to-end network slice instance.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="jitter" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="jitter")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="max-bandwidth" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="The maximum bandwidth (mb) of the connection links in a transport slice instance.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="reliability" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="The reliability requirement for an network slice subnet instance, expressed as a percentage.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="network-policies">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="tns:network-policy" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vf-module">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="a deployment unit of VNFCs",indexedProps="vf-module-id,vf-module-name,heat-stack-id,model-invariant-id,model-version-id,widget-model-id,widget-model-version,contrail-service-instance-fqdn,orchestration-status",searchable="vf-module-id,vf-module-name,operational-status",dependentOn="generic-vnf",container="vf-modules",uriTemplate="/vf-modules/vf-module/{vf-module-id}",requiredProps="vf-module-id,is-base-vf-module,automated-assignment")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="vf-module-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Unique ID of vf-module.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vf-module-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Name of vf-module")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="heat-stack-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Heat stack id corresponding to this instance.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="orchestration-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="orchestration status of this vf-module, mastered by MSO")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="is-base-vf-module" type="xs:boolean" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(defaultValue="false",description="used to indicate whether or not this object is base vf module")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="automated-assignment" type="xs:boolean" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(defaultValue="false",description="Indicates whether vf-module assignment was done via automation or manually")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-invariant-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="the ASDC model id for this resource or service model.",visibility="deployment",requires="model-version-id",dbAlias="model-invariant-id-local")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-version-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="the ASDC model version for this resource or service model.",visibility="deployment",requires="model-invariant-id",dbAlias="model-version-id-local",privateEdge="service-design-and-creation/models/model/{model-invariant-id}/model-vers/model-ver/{model-version-id}")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="persona-model-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="the ASDC model version for this resource or service model.",visibility="internal",dataCopy="service-design-and-creation/models/model/{model-invariant-id}/model-vers/model-ver/{model-version-id}#model-version")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-customization-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="captures the id of all the configuration used to customize the resource for the service.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="widget-model-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="the ASDC data dictionary widget model. This maps directly to the A&amp;AI widget.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="widget-model-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="the ASDC data dictionary version of the widget model.This maps directly to the A&amp;AI version of the widget.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="contrail-service-instance-fqdn" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="the Contrail unique ID for a service-instance")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="module-index" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="the index will track the number of modules of a given type that have been deployed in a VNF, starting with 0, and always choosing the lowest available digit")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="selflink" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Path to the controller object.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ <xs:element name="operational-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Indicator for whether the resource is considered operational. Valid values are in-service-path and out-of-service-path.",suggestibleOnSearch="true")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vf-modules">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of vf-modules, a deployment unit of VNFCs")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:vf-module" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="bgp-group">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Definition of bgp-group",indexedProps="bgp-group-id",dependentOn="pnf,vrf,generic-vnf",nameProps="bgp-group-id,bgp-group-name",container="bgp-groups",uriTemplate="/bgp-groups/bgp-group/{bgp-group-id}",requiredProps="bgp-group-id,bgp-group-name")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="bgp-group-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="UUID.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="bgp-group-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="name of bgp-group")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="bgp-group-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="type of bgp-group")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="bgp-group-role" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="role of bgp-group")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="bgp-group-function" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="function of bgp-group")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="local-as" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="local a-s number type of vrf (bridge-domain as an example)")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="local-address" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="local address")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="peer-as" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="peer a-s number")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="peer-address" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="peer address")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="description" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="description of bgp-group")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ops-note" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Notes to aid OPs in troubleshooting, such as attribute aliases or additional descriptions/instructions about an object.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:address-families" minOccurs="0"/>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="bgp-groups">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="tns:bgp-group" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="generic-vnf">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="General purpose VNF",nameProps="vnf-name",indexedProps="is-closed-loop-disabled,vnf-name2,vnf-type,heat-stack-id,vnf-name,vnf-id,regional-resource-zone,prov-status,service-id,model-invariant-id,model-version-id,widget-model-id,widget-model-version,nf-type,nf-function,nf-naming-code,nf-role,nm-profile-name,orchestration-status",searchable="vnf-id,vnf-name,vnf-name2,operational-status",uniqueProps="vnf-id",container="generic-vnfs",namespace="network",extendsFrom="vnf",containsSuggestibleProps="true",suggestionAliases="VNFs",uriTemplate="/network/generic-vnfs/generic-vnf/{vnf-id}",requiredProps="vnf-id,vnf-type,in-maint,is-closed-loop-disabled")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="vnf-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Unique id of VNF. This is unique across the graph.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vnf-instance-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="vnf instance id.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vnf-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Name of VNF.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vnf-name2" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Alternate name of VNF.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vnf-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="String capturing type of vnf, that was intended to identify the ASDC resource. This field has been overloaded in service-specific ways and clients should expect changes to occur in the future to this field as ECOMP matures.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="service-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Unique identifier of service, does not necessarily map to ASDC service models. SOON TO BE DEPRECATED")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="regional-resource-zone" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Regional way of organizing pservers, source of truth should define values")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="prov-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Trigger for operational monitoring of this resource by Service Assurance systems.",suggestibleOnSearch="true")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="operational-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Indicator for whether the resource is considered operational. Valid values are in-service-path and out-of-service-path.",suggestibleOnSearch="true")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="license-key" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="OBSOLETE - do not use")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="equipment-role" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Client should send valid enumerated value")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="orchestration-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Orchestration status of this VNF, used by MSO.",suggestibleOnSearch="true")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vnf-package-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vnf-discriptor-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="vnf discriptor name")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="job-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="job id corresponding to vnf")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="heat-stack-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Heat stack id corresponding to this instance, managed by MSO")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="mso-catalog-key" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Corresponds to the SDN-C catalog id used to configure this VCE")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="management-option" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="identifier of managed customer")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ipv4-oam-address" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Address tail-f uses to configure generic-vnf, also used for troubleshooting and is IP used for traps generated by generic-vnf.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ipv4-loopback0-address" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="v4 Loopback0 address")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="nm-lan-v6-address" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="v6 Loopback address")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="management-v6-address" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="v6 management address")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vcpu" type="xs:unsignedInt" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="number of vcpus ordered for this instance of VNF, used for VNFs with no vservers/flavors, to be used only by uCPE")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vcpu-units" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="units associated with vcpu, used for VNFs with no vservers/flavors, to be used only by uCPE")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vmemory" type="xs:unsignedInt" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="number of GB of memory ordered for this instance of VNF, used for VNFs with no vservers/flavors, to be used only by uCPE")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vmemory-units" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="units associated with vmemory, used for VNFs with no vservers/flavors, to be used only by uCPE")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vdisk" type="xs:unsignedInt" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="number of vdisks ordered for this instance of VNF, used for VNFs with no vservers/flavors, to be used only uCPE")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vdisk-units" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="units associated with vdisk, used for VNFs with no vservers/flavors, to be used only by uCPE")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="nshd" type="xs:unsignedInt" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="number of associated SHD in vnf.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="nvm" type="xs:unsignedInt" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="number of vms in vnf.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="nnet" type="xs:unsignedInt" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="number of network in vnf.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="in-maint" type="xs:boolean" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(defaultValue="false",description="used to indicate whether or not this object is in maintenance mode (maintenance mode = true). This field (in conjunction with prov-status) is used to suppress alarms and vSCL on VNFs/VMs.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="is-closed-loop-disabled" type="xs:boolean" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(defaultValue="false",description="used to indicate whether closed loop function is enabled on this node")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="summary-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="details regarding the generic-vnf operation, PLEASE DISCONTINUE USE OF THIS FIELD.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="encrypted-access-flag" type="xs:boolean" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="indicates whether generic-vnf access uses SSH")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="entitlement-assignment-group-uuid" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="UUID of the Entitlement group used for licensing VNFs, OBSOLETE - See child relationships.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="entitlement-resource-uuid" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="UUID of the specific entitlement resource. OBSOLETE - See child relationships.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="license-assignment-group-uuid" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="UUID of the license assignment group. OBSOLETE - See child relationships.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="license-key-uuid" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="UUID of the actual license resource. OBSOLETE - See child relationships.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-invariant-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="the ASDC model id for this resource or service model.",visibility="deployment",requires="model-version-id",dbAlias="model-invariant-id-local")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-version-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="the ASDC model version for this resource or service model.",visibility="deployment",requires="model-invariant-id",dbAlias="model-version-id-local",privateEdge="service-design-and-creation/models/model/{model-invariant-id}/model-vers/model-ver/{model-version-id}")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="persona-model-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="the ASDC model version for this resource or service model.",visibility="internal",dataCopy="service-design-and-creation/models/model/{model-invariant-id}/model-vers/model-ver/{model-version-id}#model-version")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-customization-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="captures the id of all the configuration used to customize the resource for the service.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="widget-model-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="the ASDC data dictionary widget model. This maps directly to the A&amp;AI widget.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="widget-model-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="the ASDC data dictionary version of the widget model.This maps directly to the A&amp;AI version of the widget.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="as-number" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="as-number of the VNF")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="regional-resource-subzone" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="represents sub zone of the rr plane")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="nf-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Generic description of the type of NF",suggestibleOnSearch="true")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="nf-function" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="English description of Network function that the specific VNF deployment is providing")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="nf-role" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="role in the network that this model will be providing",suggestibleOnSearch="true")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="nf-naming-code" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="string assigned to this model used for naming purposes")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="selflink" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Path to the controller object.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ipv4-oam-gateway-address" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Gateway address")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ipv4-oam-gateway-address-prefix-length" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Prefix length for oam-address")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vlan-id-outer" type="xs:unsignedInt" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Temporary location for S-TAG to get to VCE")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="nm-profile-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Network Management profile of this VNF")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="software-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="VNF instance specific software version")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="application-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="vnf application-id")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ <xs:element ref="tns:l-interfaces" minOccurs="0"/>
+ <xs:element ref="tns:lag-interfaces" minOccurs="0"/>
+ <xs:element ref="tns:vf-modules" minOccurs="0"/>
+ <xs:element ref="tns:licenses" minOccurs="0"/>
+ <xs:element ref="tns:bgp-groups" minOccurs="0"/>
+ <xs:element ref="tns:bgp-neighbors" minOccurs="0"/>
+ <xs:element ref="tns:entitlements" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="generic-vnfs">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of VNFs")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:generic-vnf" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="lag-link">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="LAG links can connect lag-interfaces",indexedProps="link-name",container="lag-links",namespace="network",uriTemplate="/network/lag-links/lag-link/{link-name}",requiredProps="link-name")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="link-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Alphabetical concatenation of lag-interface names")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="lag-links">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of link aggregation connections")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:lag-link" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="newvce">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="This object fills in the gaps from vce that were incorporated into generic-vnf. This object will be retired with vce.",nameProps="vnf-name",indexedProps="vnf-name,vnf-name2,vnf-type,heat-stack-id,prov-status,vnf-id2,orchestration-status",searchable="vnf-id2,vnf-name,vnf-name2",uniqueProps="vnf-id2",container="newvces",namespace="network",uriTemplate="/network/newvces/newvce/{vnf-id2}",requiredProps="vnf-id2,vnf-name,vnf-type")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="vnf-id2" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Unique id of VNF, can't use same attribute name right now until we promote this new object")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vnf-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Name of VNF.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vnf-name2" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Alternate name of VNF.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vnf-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="String capturing type of vnf, that was intended to identify the ASDC resource. This field has been overloaded in service-specific ways and clients should expect changes to occur in the future to this field as ECOMP matures.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="prov-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Trigger for operational monitoring of this VNF by BAU Service Assurance systems.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="operational-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Indicator for whether the resource is considered operational")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="license-key" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="OBSOLETE - do not use")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ipv4-oam-address" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Address tail-f uses to configure generic-vnf, also used for troubleshooting and is IP used for traps generated by GenericVnf (v4-loopback0-ip-address).")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="equipment-role" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Client should send valid enumerated value.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ipv4-loopback0-address" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="v4 Loopback0 address")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="orchestration-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Orchestration status of this VNF, mastered by MSO.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="heat-stack-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Heat stack id corresponding to this instance, managed by MSO")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="mso-catalog-key" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Corresponds to the SDN-C catalog id used to configure this VCE")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ <xs:element ref="tns:l-interfaces" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="newvces">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="This object fills in the gaps from vce that were incorporated into generic-vnf. This object will be retired with vce.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:newvce" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="software-version">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Software Version",indexedProps="software-version-id,is-active-sw-ver",dependentOn="pnf",container="pnf",requiredProps="software-version-id,is-active-sw-ver",uriTemplate="/pnf/software-version/{software-version-id}")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="software-version-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Identifier of the software version")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="is-active-sw-ver" type="xs:boolean" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(defaultValue="false",description="used to indicate whether or not this software-version is the active one (activeSw = true)")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="software-versions">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of software versions.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:software-version" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vrf">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Definition of vrf",indexedProps="vrf-id,vrf-role,vrf-function",nameProps="vrf-name",dependentOn="pnf",container="vrfs",uriTemplate="/vrfs/vrf/{vrf-id}",requiredProps="vrf-id,vrf-name")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="vrf-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="VRF UUID.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vrf-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="VRF Name")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vrf-description" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="VRF Description")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="route-distinguisher" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Route Distinguisher")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vrf-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="The type of vrf (bridge-domain as an example)")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vrf-address-family" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="IP address family (v6/v4/both)")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ops-note" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Notes to aid OPs in troubleshooting, such as attribute aliases or additional descriptions/instructions about an object.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vrf-role" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Indicator for the use of this physical link")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vrf-function" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="The function performed by this Linterface")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vrf-group-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Bridge domain group name")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:bgp-groups" minOccurs="0"/>
+ <xs:element ref="tns:bgp-neighbors" minOccurs="0"/>
+ <xs:element ref="tns:aggregate-routes" minOccurs="0"/>
+ <xs:element ref="tns:route-targets" minOccurs="0"/>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vrfs">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="tns:vrf" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="pnf">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="PNF represents a physical network function. typically equipment used in the D1 world. in 1607, this will be populated by SDN-C to represent a premises router that a uCPE connects to. But this can be used to represent any physical device that is not an AIC node or uCPE.",indexedProps="pnf-name,orchestration-status,inv-status,model-invariant-id,model-version-id,operational-status,nf-type,admin-status,nf-role,prov-status,nf-naming-code,equipment-clli",searchable="pnf-name",uniqueProps="pnf-name",container="pnfs",namespace="network",uriTemplate="/network/pnfs/pnf/{pnf-name}",requiredProps="pnf-name,in-maint")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="pnf-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="unique name of Physical Network Function.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="pnf-name2" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="name of Physical Network Function.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="selflink" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="URL to endpoint where AAI can get more details.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="pnf-name2-source" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="source of name2")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="pnf-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="id of pnf")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="nf-naming-code" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Naming code for network function")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="network-operating-system" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Network operating system used on the device.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="nf-function" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="The function performed by the pnf.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="equip-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Equipment type. Source of truth should define valid values.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="equip-vendor" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Equipment vendor. Source of truth should define valid values.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="equip-model" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Equipment model. Source of truth should define valid values.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="management-option" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="identifier of managed customer")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="orchestration-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Orchestration status of this pnf")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ipaddress-v4-oam" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="ipv4-oam-address with new naming convention for IP addresses")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="sw-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="sw-version is the version of SW for the hosted application on the PNF.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="in-maint" type="xs:boolean" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(defaultValue="false",description="Used to indicate whether or not this object is in maintenance mode (maintenance mode = true). This field (in conjunction with prov-status) is used to suppress alarms and vSCL on VNFs/VMs.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="frame-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="ID of the physical frame (relay rack) where pnf is installed.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="serial-number" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Serial number of the device")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ipaddress-v4-loopback-0" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="IPV4 Loopback 0 address")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ipaddress-v6-loopback-0" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="IPV6 Loopback 0 address")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ipaddress-v4-aim" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="IPV4 AIM address")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ipaddress-v6-aim" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="IPV6 AIM address")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ipaddress-v6-oam" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="IPV6 OAM address")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="inv-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="CANOPI's inventory status. Only set with values exactly as defined by CANOPI.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="prov-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Prov Status of this device (not under canopi control) Valid values [PREPROV/NVTPROV/PROV]")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="nf-role" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Nf Role is the role performed by this instance in the network.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="admin-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="admin Status of this PNF")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="operational-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the operational-status for this object.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-customization-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the model-customization-id for this object.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-invariant-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="The ASDC model id for this resource model.",visibility="deployment",requires="model-version-id",dbAlias="model-invariant-id-local")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-version-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="The ASDC model version for this resource model.",visibility="deployment",requires="model-invariant-id",dbAlias="model-version-id-local",privateEdge="service-design-and-creation/models/model/{model-invariant-id}/model-vers/model-ver/{model-version-id}")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ops-note" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Notes to aid OPs in troubleshooting, such as attribute aliases or additional descriptions/instructions about an object.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="config-validation-request-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Contains the value of the request id to the most recent configuration file/validation report for this PNF.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="config-validation-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Status of latest configuration attempt represented by the config-url.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="nf-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Subtype used to categorize this pnf")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="common-base-indicator" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Indicates the PNF/R-Leaf was built with the VNF agnostic common base")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="equipment-clli" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="11-character equipment CLLI.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="pnf-ipv4-address" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="This is the IP address (IPv4) for the PNF itself. This is the IPv4 address that the PNF iself can be accessed at.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="pnf-ipv6-address" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="This is the IP address (IPv6) for the PNF itself. This is the IPv6 address that the PNF iself can be accessed at.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:software-versions" minOccurs="0"/>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ <xs:element ref="tns:p-interfaces" minOccurs="0"/>
+ <xs:element ref="tns:l-interfaces" minOccurs="0"/>
+ <xs:element ref="tns:lag-interfaces" minOccurs="0"/>
+ <xs:element ref="tns:activities" minOccurs="0"/>
+ <xs:element ref="tns:vrfs" minOccurs="0"/>
+ <xs:element ref="tns:bgp-groups" minOccurs="0"/>
+ <xs:element ref="tns:bgp-neighbors" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="pnfs">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of Physical Network Functions.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:pnf" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="port">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Definition of port",indexedProps="port-name",dependentOn="chassis,pluggable,card",container="ports",uriTemplate="/ports/port/{port-name}",requiredProps="port-name,port-type,port-role,speed-value,speed-units")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="port-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="A unique name for the port relative to the containing hardware.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="port-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="The type of port.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="port-role" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="The role of the port.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="speed-value" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="The numeric value for the speed of the port.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="speed-units" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="The units for the speed of the port.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="xcvr-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Type of transceiver that creates this port.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="equip-identifier" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="clei-code or other similar identifier")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="part-number" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="part number")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="port-start" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Port range start")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="port-end" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Port range end")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="ports">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="tns:port" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="pluggable">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Definition of pluggable",indexedProps="pluggable-type,part-number,equip-identifier",dependentOn="pluggable-slot",container="pluggables",uriTemplate="/pluggables/pluggable/{pluggable-type}",requiredProps="pluggable-type")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="pluggable-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="The type of pluggable.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="part-number" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Part number for this pluggable.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="equip-identifier" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="CLEI or other specification for pluggable hardware.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ <xs:element ref="tns:ports" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="pluggables">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="tns:pluggable" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="pluggable-slot">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Definition of card-slot",indexedProps="slot-name",dependentOn="chassis,card",container="pluggable-slots",uriTemplate="/pluggable-slots/pluggable-slot/{slot-name}",requiredProps="slot-name")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="slot-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="The name of the pluggable-slot. (unique relative to the chassis or card).")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:pluggables" minOccurs="0"/>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="pluggable-slots">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="tns:pluggable-slot" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="card">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Definition of card",indexedProps="card-type",dependentOn="card-slot",container="cards",uriTemplate="/cards/card/{card-type}",requiredProps="card-type")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="card-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="The type of card.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ <xs:element ref="tns:ports" minOccurs="0"/>
+ <xs:element ref="tns:pluggable-slots" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="cards">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="tns:card" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="card-slot">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Definition of card-slot",indexedProps="slot-name",dependentOn="chassis",container="card-slots",uriTemplate="/card-slots/card-slot/{slot-name}",requiredProps="slot-name")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="slot-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="The name of the card-slot (unique relative to the chassis).")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:cards" minOccurs="0"/>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="card-slots">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="tns:card-slot" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="chassis">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Definition of chassis",uniqueProps="chassis-name",indexedProps="chassis-name,part-number,orchestration-status,equip-model,equip-vendor,equip-identifier",container="chassies",namespace="network",uriTemplate="/network/chassies/chassis/{chassis-name}",requiredProps="chassis-name,chassis-type,chassis-role")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="chassis-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="A globally unique name for the chassis.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="chassis-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="The type of chassis..")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="chassis-role" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="The role of the chassis relative to the pnf/pserver..")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="operating-system" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Operating system of the hardware.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="serial-number" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="The serial number of the chassis..")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="asset-tag" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="The asset tag of the chassis.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="chassis-description" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Description of the chassis.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="part-number" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Part number for this chassis.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="orchestration-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Orchestration status of this chassis.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="equip-model" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Equipment model.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="equip-vendor" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Equipment vendor. Source of truth should define valid values.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="equip-identifier" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="CLEI or other specification for chassis hardware.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="slot-number" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Slot number associated with this chassis.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="admin-state" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Reflects the admin-state of the device.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:ports" minOccurs="0"/>
+ <xs:element ref="tns:card-slots" minOccurs="0"/>
+ <xs:element ref="tns:pluggable-slots" minOccurs="0"/>
+ <xs:element ref="tns:licenses" minOccurs="0"/>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="chassies">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="tns:chassis" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="physical-link">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of physical connections, typically between p-interfaces",indexedProps="circuit-id,link-name,link-function,link-role,link-type",alternateKeys1="circuit-id",container="physical-links",namespace="network",searchable="link-name,circuit-id,operational-status",uriTemplate="/network/physical-links/physical-link/{link-name}",requiredProps="link-name")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="link-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="e.g., hostnameA_p-connection_nameA_hostnameZ+p_connection-nameZ")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="speed-value" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Captures the numeric part of the speed")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="speed-units" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Captures the units corresponding to the speed")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="circuit-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Circuit it")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="dual-mode" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Dual access mode (e.g., primary, secondary")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="management-option" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="To provide information on who manages this circuit. A&amp;AI or 3rd party transport provider")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="service-provider-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Name of the service Provider on this link.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="service-provider-bandwidth-up-value" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Upstream Bandwidth value agreed with the service provider")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="service-provider-bandwidth-up-units" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Units for the upstream BW value")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="service-provider-bandwidth-down-value" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Downstream Bandwidth value agreed with the service provider")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="service-provider-bandwidth-down-units" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Units for downstream BW value")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="link-function" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="The function performed by this physical link")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="link-role" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Indicator for the use of this physical link")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="link-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Subtype used to categorize this physical link")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="operational-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Indicator for whether the resource is considered operational. Valid values are in-service-path and out-of-service-path.",suggestibleOnSearch="true")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="physical-links">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of physical connections, typically between p-interfaces")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:physical-link" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vig-server">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="vig-server contains information about a vig server used for IPSec-configuration. Populated by SDN-C from 1607",indexedProps="vig-address-type",dependentOn="ipsec-configuration",container="vig-servers",uriTemplate="/vig-servers/vig-server/{vig-address-type}",requiredProps="vig-address-type")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="vig-address-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="indicates whether the VIG is for AVPN or INTERNET")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ipaddress-v4-vig" type="xs:string" minOccurs="0" maxOccurs="5000">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="v4 IP of the vig server")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ipaddress-v6-vig" type="xs:string" minOccurs="0" maxOccurs="5000">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="v6 IP of the vig server")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vig-servers">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="tns:vig-server" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="ipsec-configuration">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="IPSec configuration node will contain various configuration data for the NMTE VNF. This node will have an edge to the generic-vnf (vnf type = TE). Starting 1607, this data will be populated by SDN-C",indexedProps="ipsec-configuration-id",uniqueProps="ipsec-configuration-id",container="ipsec-configurations",namespace="network",uriTemplate="/network/ipsec-configurations/ipsec-configuration/{ipsec-configuration-id}",requiredProps="ipsec-configuration-id")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="ipsec-configuration-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="UUID of this configuration")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="requested-vig-address-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Indicate the type of VIG server like AVPN, INTERNET, BOTH")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="requested-encryption-strength" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Encryption values like 3des-cbc, des-cbc, aes-128-cbc, aes-192-cbc, aes-265-cbc")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="requested-dmz-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Shared DMZ or a DMZ specific to a customer")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="shared-dmz-network-address" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Network address of shared DMZ")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="requested-customer-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="If the DMZ is a custom DMZ, this field will indicate the customer information")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ike-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="can be 1 or 2")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ikev1-authentication" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Contains values like md5, sha1, sha256, sha384")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ikev1-encryption" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Encyption values like 3des-cbc, des-cbc, aes-128-cbc, aes-192-cbc, aes-265-cbc")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ikev1-dh-group" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Diffie-Hellman group like DH-GROUP2, DH-GROUP5, DH-GROUP14")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ikev1-am-group-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Group name defined in VIG for clients using aggressive mode")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ikev1-am-password" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="pre-shared key for the above group name ")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ikev1-sa-lifetime" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Lifetime for IKEv1 SA")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ipsec-authentication" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="md5, sha1, sha256, sha384")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ipsec-encryption" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="3des-cbc, des-cbc, aes-128-cbc, aes-192-cbc, aes-265-cbc")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ipsec-sa-lifetime" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Life time for IPSec SA")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ipsec-pfs" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="enable PFS or not")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="xauth-userid" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="user ID for xAuth, sm-user,ucpeHostName,nmteHostName")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="xauth-user-password" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Encrypted using the Juniper $9$ algorithm")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="dpd-interval" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="The time between DPD probe")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="dpd-frequency" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Maximum number of DPD before claiming the tunnel is down")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ <xs:element ref="tns:vig-servers" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="ipsec-configurations">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="tns:ipsec-configuration" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="route-table-reference">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Openstack route table reference.",nameProps="route-table-reference-fqdn",uniqueProps="route-table-reference-id",indexedProps="route-table-reference-id,route-table-reference-fqdn",container="route-table-references",namespace="network",uriTemplate="/network/route-table-references/route-table-reference/{route-table-reference-id}",requiredProps="route-table-reference-id,route-table-reference-fqdn")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="route-table-reference-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Route Table Reference id, UUID assigned to this instance.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="route-table-reference-fqdn" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="FQDN entry in the route table.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Concurrency value")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="route-table-references">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of openstack route table references")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:route-table-reference" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="instance-group">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="General mechanism for grouping instances",nameProps="description,instance-group-name",uniqueProps="id",searchable="id,description",indexedProps="id,model-invariant-id,model-version-id",container="instance-groups",namespace="network",uriTemplate="/network/instance-groups/instance-group/{id}",requiredProps="id,instance-group-type")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Instance Group ID, UUID assigned to this instance.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="instance-group-role" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="role of the instance group.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-invariant-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="ASDC model id for this resource or service model.",visibility="deployment",requires="model-version-id",dbAlias="model-invariant-id-local")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-version-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="ASDC model version uid for this resource model.",visibility="deployment",requires="model-invariant-id",dbAlias="model-version-id-local",privateEdge="service-design-and-creation/models/model/{model-invariant-id}/model-vers/model-ver/{model-version-id}")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="description" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Descriptive text to help identify the usage of this instance-group")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="instance-group-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Only valid value today is lower case ha for high availability")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Concurrency value")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="instance-group-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Instance-Group Name.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="instance-group-function" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Instance-Group Function")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="instance-group-number" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Number used to identify an instance-group")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="priority-number" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used to identify the primary and secondary priority")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="instance-groups">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of openstack route table references")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:instance-group" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="zone">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="A zone is a grouping of assets in a location homing to the same connections into the CBB",nameProps="zone-name",indexedProps="zone-id,design-type,zone-context",uniqueProps="zone-id",container="zones",namespace="network",uriTemplate="/network/zones/zone/{zone-id}",requiredProps="zone-id,zone-name,design-type,zone-context,in-maint")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="zone-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Code assigned by AIC to the zone")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="zone-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="English name associated with the zone")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="zone-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="The type of zone (ex. AIC or NC).")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="design-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Design of zone [Medium/Large…]")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="zone-context" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Context of zone [production/test]")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Status of a zone.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="zone-role" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Role of a zone.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="zone-function" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Function of a zone.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Concurrency value")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="in-maint" type="xs:boolean" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(defaultValue="false",description="Used to indicate whether or not zone object is in maintenance mode.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ <xs:element ref="tns:subnets" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="zones">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of zones")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:zone" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="autonomous-system">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Description of Autonomous System",nameProps="autonomous-system-id,autonomous-system-number",indexedProps="autonomous-system-id,autonomous-system-number,autonomous-system-type",uniqueProps="autonomous-system-id",container="autonomous-systems",namespace="network",uriTemplate="/network/autonomous-systems/autonomous-system/{autonomous-system-id}",requiredProps="autonomous-system-id,autonomous-system-number,autonomous-system-type")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="autonomous-system-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="UUID")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="autonomous-system-number" type="xs:unsignedInt" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="asn in the range of 0 to 9223372036854775807")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="autonomous-system-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="type (global vs. local).")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="autonomous-system-region" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="geographic region")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="autonomous-system-role" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="role of autonomous system")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Concurrency value")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="autonomous-systems">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of Autonomous Systems")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:autonomous-system" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="network-range">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Description of Network Range",nameProps="network-range-name,network-range-type",indexedProps="network-range-id,network-range-name",container="network-ranges",namespace="network",uriTemplate="/network/network-ranges/network-range/{network-range-id}",requiredProps="network-range-id,network-range-name,network-range-type")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="network-range-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="UUID")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="network-range-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="name")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="network-range-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="type (ex, esi, vni, vni-rt, lacp-id).")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="network-range-role" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="role of network-range")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="network-range-function" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="descriptive function")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="start-range" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="starting range for simple network ranges.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="end-range" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="end range for simple network ranges.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="last-assigned" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="last assigned value for simple network ranges")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="range-format" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Format Decimal, Hexadecimal, etc.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="range-prefix" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Prefix of network range.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Concurrency value")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:activities" minOccurs="0"/>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="network-ranges">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of Network Ranges")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:network-range" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="mapping">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="General mechanism for mapping between instances; cg-nat.",indexedProps="mapping-id",uniqueProps="mapping-id",container="mappings",namespace="network",uriTemplate="/network/mappings/mapping/{mapping-id}",requiredProps="mapping-id")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="mapping-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Key for mapping object.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="mapping-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Name of mapping")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="mapping-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Type of mapping.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="mapping-role" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Role of mapping")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="mapping-function" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Function of mapping")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="mapping-number" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Number of mapping")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="location-1" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Location 1")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="location-2" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Location 2")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="mapping-group-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Non-unique ID for grouping mappings")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="prov-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Provision status for the mapping object. Valid values can be found at (https://wiki.web.att.com/display/SPTIIRP/prov-status).")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="homed-location" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Location the object is homed to")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="planned-location" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Location the object is planned for")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="mappings">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of mappings.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:mapping" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="hw-component">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="create/update/delete the hw-component node",indexedProps="hw-component-id",uriTemplate="/network/hw-components/hw-component/{hw-component-id}",requiredProps="hw-component-id",namespace="network",container="hw-components")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="hw-component-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="UUID")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="hw-component-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Name of hardware component")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="hw-component-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Type of hardware component")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="hw-component-role" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Role of hardware component")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="hw-component-function" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Function of hardware component")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="hw-components">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="tns:hw-component" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="sw-component">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="create/update/delete the sw-component node",indexedProps="sw-component-id",uriTemplate="/network/sw-components/sw-component/{sw-component-id}",requiredProps="sw-component-id",namespace="network",container="sw-components")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="sw-component-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="UUID")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="sw-component-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Name of software component")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="sw-component-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Type of software component")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="sw-component-role" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Role of software component")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="sw-component-function" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Function of software component")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="sw-components">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="tns:sw-component" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="network-route">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="This object represents a network route. For instance, host-route, static-route.",indexedProps="route-id,type,role,function,ip-address,prefix-length,next-hop",uriTemplate="/network/network-routes/network-route/{route-id}",requiredProps="route-id,type,role,function,ip-address,prefix-length,address-family",namespace="network",container="network-routes")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="route-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="unique identifier example uuid.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="used to categorize this object in conjunction with role &amp; function. The most generic category.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="role" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="used to categorize this object in conjunction with type &amp; function.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="function" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="used to categorize this object in conjunction with type &amp; role. The most specific category.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ip-address" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="ip address that of the specific network-route.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="prefix-length" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="ip-address prefix length.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="logical-interface-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Identity of a logical interface, e.g., VLAN ID.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="next-hop" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Could be ip-address, hostname, or service-instance.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="next-hop-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Should be ip-address, hostname, or service-instance to match next-hop.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="metric" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Value that is assigned to an IP route for a particular network interface that identifies the cost that is associated with using that route.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="address-family" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="whether the route address is ipv4, ipv6.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="network-routes">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="tns:network-route" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vlan-mapping">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="vlan-mapping object is an optional child object of the forwarder-evc object. A given forwarder-evc object may have multiple vlan-mapping objects.",dependentOn="forwarder-evc",uniqueProps="vlan-mapping-id",container="vlan-mappings",uriTemplate="/vlan-mappings/vlan-mapping/{vlan-mapping-id}",requiredProps="vlan-mapping-id")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="vlan-mapping-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Key for vlan-mapping object.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="uni-cvlan" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="CVLAN value from the UNI/ingress side of the SAREA gateway access device.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="nni-svlan" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="SVLAN value from the NNI/egress side of the SAREA gateway access device.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="nni-cvlan" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="CVLAN value from the NNI/egress side of the SAREA gateway access device.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ivlan" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="The internal VLAN ('IVLAN') value. Specific to Arista devices.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vlan-mappings">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of vlan mappings.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:vlan-mapping" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="forwarder-evc">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="forwarder object is an optional child object of the Configuration object.",dependentOn="configuration",uniqueProps="forwarder-evc-id",container="forwarder-evcs",uriTemplate="/forwarder-evcs/forwarder-evc/{forwarder-evc-id}",requiredProps="forwarder-evc-id",indexedProps="circuit-id")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="forwarder-evc-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Key for forwarder-evc object")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="circuit-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Circuit ID from customer/ESP/ingress end of EVC, or reference to beater circuit on gateway/network/egress end of EVC")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ivlan" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Internal VLAN.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="svlan" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="SVLAN value for ingress of egress forwarder.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="cvlan" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="CVLAN value for ingress of egress forwarder.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:vlan-mappings" minOccurs="0"/>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="forwarder-evcs">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="tns:forwarder-evc" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="evc">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="evc object is an optional child object of the Configuration object.",dependentOn="configuration",uniqueProps="evc-id",container="evcs",uriTemplate="/evcs/evc/{evc-id}",requiredProps="evc-id")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="evc-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Unique/key field for the evc object")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="forwarding-path-topology" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Point-to-Point, Multi-Point")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="cir-value" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Commited Information Rate")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="cir-units" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="CIR units")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="connection-diversity-group-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Diversity Group ID")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="service-hours" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="formerly Performance Group")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="esp-evc-circuit-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="EVC Circuit ID of ESP EVC")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="esp-evc-cir-value" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Committed Information Rate (For ESP)")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="esp-evc-cir-units" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="CIR units (For ESP)")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="esp-itu-code" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Identifies ESP")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="collector-pop-clli" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Collector POP CLLI (from the hostname of the access pnf)")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="inter-connect-type-ingress" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Interconnect type on ingress side of EVC.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="tagmode-access-ingress" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="tagode for collector side of EVC")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="tagmode-access-egress" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="tagMode for network side of EVC")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="product-entry-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Product ID")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="evcs">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="tns:evc" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="configuration">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Generic configuration object.",indexedProps="configuration-id,configuration-name,configuration-type,model-invariant-id,model-version-id,orchestration-status,configuration-role,configuration-function,orchestration-version",uniqueProps="configuration-id",container="configurations",namespace="network",uriTemplate="/network/configurations/configuration/{configuration-id}",requiredProps="configuration-id,configuration-type")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="configuration-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="UUID assigned to configuration.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="management-option" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Indicates the entity that will manage this feature. Could be an organization or the name of the application as well.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="configuration-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Name of the configuration.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="configuration-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="port-mirroring-configuration.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="configuration-sub-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="vprobe, pprobe.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-invariant-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="the ASDC model id for this resource or service model.",visibility="deployment",requires="model-version-id",dbAlias="model-invariant-id-local")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-version-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="the ASDC model version for this resource or service model.",visibility="deployment",requires="model-invariant-id",dbAlias="model-version-id-local",privateEdge="service-design-and-creation/models/model/{model-invariant-id}/model-vers/model-ver/{model-version-id}")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="orchestration-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Orchestration status of the configuration.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="operational-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Indicator for whether the resource is considered operational.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="configuration-selflink" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="URL to endpoint where AAI can get more details from SDN-GC.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-customization-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="id of the configuration used to customize the resource")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="tunnel-bandwidth" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="DHV Site Effective Bandwidth")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vendor-allowed-max-bandwidth" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Velocloud Nominal Throughput - VNT")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="config-policy-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used to capture the name of the fabric configuration policy that was used to generate the payload sent to PINC for fabric configuration.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="configuration-role" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used to categorize the configuration.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="configuration-function" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used to categorize the configuration.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="primary-role" type="xs:boolean" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used by some configurations to identify if it's filling a primary role.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="orchestration-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used to categorize the configuration.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ <xs:element ref="tns:metadata" minOccurs="0"/>
+ <xs:element ref="tns:forwarder-evcs" minOccurs="0"/>
+ <xs:element ref="tns:evcs" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="configurations">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of configurations")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:configuration" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="forwarder">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(indexedProps="sequence",description="Entity describing a sequenced segment of forwarding path",container="forwarders",dependentOn="forwarding-path",uriTemplate="/forwarders/forwarder/{sequence}",requiredProps="sequence")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="sequence" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Unique ID of this segmentation")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="forwarder-role" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="ingress, intermediate, egress")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="forwarders">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="tns:forwarder" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="forwarding-path">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(namespace="network",indexedProps="forwarding-path-id,forwarding-path-name",description="Entity that describes the sequenced forwarding path between interfaces of services or resources",container="forwarding-paths",nameProps="forwarding-path-name",uniqueProps="forwarding-path-id",uriTemplate="/network/forwarding-paths/forwarding-path/{forwarding-path-id}",requiredProps="forwarding-path-id,forwarding-path-name")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="forwarding-path-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Unique ID of this FP")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="forwarding-path-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Name of the FP")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="selflink" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="the self link for this FP")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:forwarders" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="forwarding-paths">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="tns:forwarding-path" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="collection">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(namespace="network",description="represents the collection resource in the TOSCA model",uniqueProps="collection-id",indexedProps="collection-id,model-invariant-id,model-version-id,orchestration-status",container="collections",uriTemplate="/network/collections/collection/{collection-id}",requiredProps="collection-id")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="collection-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Collection Object UUID")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-invariant-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="ASDC model id for this resource or service model",visibility="deployment",requires="model-version-id",dbAlias="model-invariant-id-local")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-version-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Model Version",visibility="deployment",requires="model-invariant-id",dbAlias="model-version-id-local",privateEdge="service-design-and-creation/models/model/{model-invariant-id}/model-vers/model-ver/{model-version-id}")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="collection-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="collection name")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="collection-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Collection type")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="collection-role" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Collection Role")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="collection-function" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Collection function")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="orchestration-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="orchestration status")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="collection-customization-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Captures the id of all the configuration used to customize the resource for the service")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="collections">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="tns:collection" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="next-hop">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Is among the series of routers that are connected together in a network and is the next possible destination for a data packet.",indexedProps="next-hop-id",namespace="network",container="next-hops",uriTemplate="/network/next-hops/next-hop/{next-hop-id}",uniqueProps="next-hop-id",requiredProps="next-hop-id,next-hop-type")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="next-hop-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="UUID.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="next-hop-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used to categorize this object in conjunction with role &amp; function. The most generic category.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="next-hop-role" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used to categorize this object in conjunction with type &amp; function.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="next-hop-function" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used to categorize this object in conjunction with type &amp; role. The most specific category.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="sequence" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Sequence number.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="address-family" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Ipv4 or Ipv6.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ip-address" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Next hop ip-address.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="metric" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Cost that is associated with using the route.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="next-hops">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="tns:next-hop" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="bfd">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="BFD (Bidirectional Forwarding Detection) is a protocol for detecting link failures.The BFD object is for persisting attributes for the links that have BFD enabled.",indexedProps="bfd-id",namespace="network",container="bfds",uriTemplate="/network/bfds/bfd/{bfd-id}",uniqueProps="bfd-id",requiredProps="bfd-id,bfd-type",nameProps="bfd-id")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="bfd-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Unique identifier.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="bfd-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used to categorize this object in conjunction with role &amp; function. The most generic category.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="bfd-role" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used to categorize this object in conjunction with type &amp; function.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="bfd-function" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used to categorize this object in conjunction with type &amp; role. The most specific category.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="bfd-keep-alive" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="bfd keep-alive parameter")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="bfd-timeout" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="bfd timeout parameter")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="bfds">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="tns:bfd" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="fqdn">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="A fully qualified domain name (FQDN) is the complete domain name for a specific computer, or host, on the internet.",requiredProps="fqdn,dns-domain",indexedProps="fqdn",namespace="network",container="fqdns",uriTemplate="/network/fqdns/fqdn/{fqdn}")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="fqdn" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Fully qualified domain name.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="fqdn-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used to categorize this object in conjunction with role &amp; function. The most generic category.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="fqdn-role" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used to categorize this object in conjunction with type &amp; function.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="fqdn-function" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used to categorize this object in conjunction with type &amp; role. The most specific category.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="dns-domain" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Domain name.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="fqdns">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="tns:fqdn" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="connectivity">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Instance of a connectivity",indexedProps="connectivity-id,etht-svc-name,bandwidth-profile-name,vpn-type,color-aware,coupling-flag,access-provider-id,access-client-id,access-topology-id,access-node-id,access-ltp-id,operational-status,model-invariant-id,model-version-id",nameProps="etht-svc-name",searchable="connectivity-id",uniqueProps="connectivity-id",container="connectivities",namespace="network",requiredProps="connectivity-id",uriTemplate="/network/connectivities/connectivity/{connectivity-id}")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="connectivity-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Uniquely identifies this connectivity by id")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="bandwidth-profile-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the name of a bandwidth profile.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vpn-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the type of a bandwidth profile.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="cir" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the CIR of this connectivity.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="eir" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the EIR of this connectivity.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="cbs" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the CBS of this connectivity.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ebs" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the EBS of this connectivity.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="color-aware" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the color-awareness of this connectivity.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="coupling-flag" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the coupling flag of this connectivity.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="etht-svc-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="The ethernet service name for this connectivity.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="access-provider-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the id of the access provider of this connectivity.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="access-client-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the id of the access client of this connectivity.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="access-topology-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the id of the access topology of this connectivity.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="access-node-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the id of the access node of this connectivity.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="access-ltp-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the id of the access ltp of this connectivity.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="connectivity-selflink" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the link to get more information for this connectivity.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="cvlan" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the cvlan for this connectivity.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="operational-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the operational-status for this object.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-customization-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the model-customization-id for this object.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-invariant-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="the ASDC model id for this resource or service model.",visibility="deployment",requires="model-version-id",dbAlias="model-invariant-id-local")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-version-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="the ASDC model version for this resource or service model.",visibility="deployment",requires="model-invariant-id",dbAlias="model-version-id-local",privateEdge="service-design-and-creation/models/model/{model-invariant-id}/model-vers/model-ver/{model-version-id}")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="connectivities">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of connectivities")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:connectivity" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="dhcp-service">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Instance of a dhcp-service",indexedProps="dhcp-service-id,dhcp-service-type,domain-name,server-ipv4-address,server-ipv6-address",nameProps="domain-name",searchable="dhcp-service-id",uniqueProps="dhcp-service-id",container="dhcp-services",dependentOn="lan-port-config",namespace="network",requiredProps="dhcp-service-id",uriTemplate="/network/dhcp-services/dhcp-service/{dhcp-service-id}")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="dhcp-service-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Uniquely identifies this dhcp-service by id")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="server-ipv4-address" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the server-ip4-address of this dhcp-service.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="server-ipv6-address" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the server-ipv6-address of this dhcp-service.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="service-enable" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the service-enable of this dhcp-service.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="dhcp-service-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the dhcp-service-type of this dhcp-service.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="lease-time" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the lease-time of this dhcp-service.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="domain-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the domain-name of this dhcp-service.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="dns" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the dns of this dhcp-service.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ntp-primary" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the ntp-primary of this dhcp-service.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ntp-secondary" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the ntp-secondary of this dhcp-service.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="nbns" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the nbns of this dhcp-service.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="dhcp-services">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of dhcp-services")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:dhcp-service" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="lan-port-config">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Instance of a lan-port-config",indexedProps="lan-port-config-id,lan-port-config-name,device-id,port-id,ipv4-address,ipv6-address,vlan-tag",nameProps="lan-port-config-name",searchable="lan-port-config-id",uniqueProps="lan-port-config-id",container="lan-port-configs",namespace="network",requiredProps="lan-port-config-id",uriTemplate="/network/lan-port-configs/lan-port-config/{lan-port-config-id}")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="lan-port-config-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Uniquely identifies this lan-port-config by id")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="lan-port-config-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the name of this lan-port-config.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="description" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the description of this lan-port-config.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="device-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the device-id of this lan-port-config.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="port-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the port-id of this lan-port-config.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ipv4-address" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the ipv4-address of this lan-port-config.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ipv6-address" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the ipv6-address of this lan-port-config.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vlan-tag" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the vlan-tag of this lan-port-config.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="input-bandwidth" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the input-bandwidth of this lan-port-config.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="output-bandwidth" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the output-bandwidth of this lan-port-config.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:dhcp-services" minOccurs="0"/>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="lan-port-configs">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of lan-port-configs")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:lan-port-config" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="network-resource">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Instance of a network-resource",indexedProps="network-id,provider-id,client-id,te-topo-id",nameProps="network-id",searchable="network-id",uniqueProps="network-id",container="network-resources",namespace="network",requiredProps="network-id",uriTemplate="/network/network-resources/network-resource/{network-id}")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="network-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Uniquely identifies this network-resource by id")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="provider-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the id of the provider of this network-resource.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="client-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the id of the client of this network-resource.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="te-topo-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the id of the te-topo of this network-resource.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="network-resource-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Type of a network topology, e.g., Ethernet, OTN, WSON.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="selflink" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the link to get more information for this object.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="network-resources">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of network-resources")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:network-resource" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="site-resource">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Instance of a site-resource",indexedProps="site-resource-id,site-resource-name,type,role,generated-site-id,operational-status,model-invariant-id,model-version-id",nameProps="site-resource-name",searchable="site-resource-id",uniqueProps="site-resource-id",container="site-resources",namespace="network",requiredProps="site-resource-id",uriTemplate="/network/site-resources/site-resource/{site-resource-id}")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="site-resource-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Uniquely identifies this site-resource by id")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="site-resource-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the name of this site-resource.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="description" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the description of this site-resource.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the type of this site-resource.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="role" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the role of this site-resource.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="generated-site-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the generated-site-id of this site-resource.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="selflink" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the link to get more information for this object.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="operational-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the operational-status for this object.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-customization-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the model-customization-id for this object.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-invariant-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="the ASDC model id for this resource or service model.",visibility="deployment",requires="model-version-id",dbAlias="model-invariant-id-local")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-version-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="the ASDC model version for this resource or service model.",visibility="deployment",requires="model-invariant-id",dbAlias="model-version-id-local",privateEdge="service-design-and-creation/models/model/{model-invariant-id}/model-vers/model-ver/{model-version-id}")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="site-resources">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of site-resources")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:site-resource" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="sdwan-vpn">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Instance of an sdwan-vpn",indexedProps="sdwan-vpn-id,sdwan-vpn-name,vxlan-id,topology,operational-status,model-invariant-id,model-version-id",nameProps="sdwan-vpn-name",searchable="sdwan-vpn-id",uniqueProps="sdwan-vpn-id",container="sdwan-vpns",namespace="network",requiredProps="sdwan-vpn-id",uriTemplate="/network/sdwan-vpns/sdwan-vpn/{sdwan-vpn-id}")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="sdwan-vpn-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Uniquely identifies this sdwan-vpn by id")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="sdwan-vpn-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the name of this sdwan-vpn.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vxlan-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the vxlan-id of this sdwan-vpn.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="topology" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the topology of this sdwan-vpn.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="tenant-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the tenant-id of this sdwan-vpn.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vpn-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the vpn-id of this sdwan-vpn.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="selflink" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the link to get more information for this object.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="operational-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the operational-status for this object.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-customization-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the model-customization-id for this object.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-invariant-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="the ASDC model id for this resource or service model.",visibility="deployment",requires="model-version-id",dbAlias="model-invariant-id-local")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-version-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="the ASDC model version for this resource or service model.",visibility="deployment",requires="model-invariant-id",dbAlias="model-version-id-local",privateEdge="service-design-and-creation/models/model/{model-invariant-id}/model-vers/model-ver/{model-version-id}")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="sdwan-vpns">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of sdwan-vpns")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:sdwan-vpn" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="device">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Instance of a device",indexedProps="device-id,device-name,esn,vendor,class,type,version,system-ip,system-ipv4,system-ipv6,operational-status,model-invariant-id,model-version-id",nameProps="device-name",searchable="device-id",uniqueProps="device-id",container="devices",namespace="network",requiredProps="device-id",uriTemplate="/network/devices/device/{device-id}")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="device-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Uniquely identifies this device by id")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="esn" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the esn of this device.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="device-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the name of this device.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="description" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the description of this device.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vendor" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the vendor of this device.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="class" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the class of this device.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the type of this device.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the version of this device.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="system-ip" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the system-ip of this device.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="system-ipv4" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the system-ipv4 of this device.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="system-ipv6" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the system-ipv6 of this device.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="selflink" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the link to get more information for this object.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="operational-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the operational-status for this object.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-customization-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the model-customization-id for this object.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-invariant-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="the ASDC model id for this resource or service model.",visibility="deployment",requires="model-version-id",dbAlias="model-invariant-id-local")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-version-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="the ASDC model version for this resource or service model.",visibility="deployment",requires="model-invariant-id",dbAlias="model-version-id-local",privateEdge="service-design-and-creation/models/model/{model-invariant-id}/model-vers/model-ver/{model-version-id}")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="devices">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of devices")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:device" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="wan-port-config">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Instance of a wan-port-config",indexedProps="wan-port-config-id,wan-port-config-name,device-id,ip-address,ipv4-address,ipv6-address,port-type,port-number,device-port-id,wan-port-id,operational-status,model-invariant-id,model-version-id",nameProps="wan-port-config-name",searchable="wan-port-config-id",uniqueProps="wan-port-config-id",container="wan-port-configs",namespace="network",requiredProps="wan-port-config-id",uriTemplate="/network/wan-port-configs/wan-port-config/{wan-port-config-id}")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="wan-port-config-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Uniquely identifies this wan-port-config by id")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="wan-port-config-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the name of this wan-port-config.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="device-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the id of the device of this wan-port-config.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vlan-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the id of the vlan of this wan-port-config.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ip-address" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the ip-address of this wan-port-config.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ipv4-address" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the ipv4-address of this wan-port-config.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="ipv6-address" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the ipv6-address of this wan-port-config.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="provider-ip-address" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the provider-ip-address of this wan-port-config.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="provider-ipv4-address" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the provider-ipv4-address of this wan-port-config.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="provider-ipv6-address" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the provider-ipv6-address of this wan-port-config.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="input-bandwidth" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the input-bandwidth of this wan-port-config.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="output-bandwidth" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the output-bandwidth of this wan-port-config.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="description" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the description of this wan-port-config.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="port-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the port-type of this wan-port-config.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="port-number" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the port-number of this wan-port-config.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="transport-network-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the transport-network-name of this wan-port-config.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="device-port-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the device-port-id of this wan-port-config.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="wan-port-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the wan-port-id of this wan-port-config.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="selflink" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the link to get more information for this object.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="operational-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the operational-status for this object.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-customization-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the model-customization-id for this object.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-invariant-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="the ASDC model id for this resource or service model.",visibility="deployment",requires="model-version-id",dbAlias="model-invariant-id-local")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-version-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="the ASDC model version for this resource or service model.",visibility="deployment",requires="model-invariant-id",dbAlias="model-version-id-local",privateEdge="service-design-and-creation/models/model/{model-invariant-id}/model-vers/model-ver/{model-version-id}")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="wan-port-configs">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of wan-port-configs")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:wan-port-config" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="ext-aai-network">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Refer to an external AAI in another ONAP.",indexedProps="aai-id",searchable="aai-id",container="ext-aai-networks",namespace="network",requiredProps="aai-id",uriTemplate="/network/ext-aai-networks/ext-aai-network/{aai-id}")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="aai-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Unique ID of the referenced AAI.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="schema-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Schema version of the referenced AAI.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:esr-system-info" minOccurs="0"/>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="ext-aai-networks">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="tns:ext-aai-network" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="network">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Namespace for network inventory resources.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:logical-links" minOccurs="0"/>
+ <xs:element ref="tns:site-pair-sets" minOccurs="0"/>
+ <xs:element ref="tns:vpn-bindings" minOccurs="0"/>
+ <xs:element ref="tns:vpls-pes" minOccurs="0"/>
+ <xs:element ref="tns:multicast-configurations" minOccurs="0"/>
+ <xs:element ref="tns:vces" minOccurs="0"/>
+ <xs:element ref="tns:vnfcs" minOccurs="0"/>
+ <xs:element ref="tns:l3-networks" minOccurs="0"/>
+ <xs:element ref="tns:network-policies" minOccurs="0"/>
+ <xs:element ref="tns:generic-vnfs" minOccurs="0"/>
+ <xs:element ref="tns:lag-links" minOccurs="0"/>
+ <xs:element ref="tns:newvces" minOccurs="0"/>
+ <xs:element ref="tns:pnfs" minOccurs="0"/>
+ <xs:element ref="tns:chassies" minOccurs="0"/>
+ <xs:element ref="tns:physical-links" minOccurs="0"/>
+ <xs:element ref="tns:ipsec-configurations" minOccurs="0"/>
+ <xs:element ref="tns:route-table-references" minOccurs="0"/>
+ <xs:element ref="tns:instance-groups" minOccurs="0"/>
+ <xs:element ref="tns:zones" minOccurs="0"/>
+ <xs:element ref="tns:autonomous-systems" minOccurs="0"/>
+ <xs:element ref="tns:network-ranges" minOccurs="0"/>
+ <xs:element ref="tns:mappings" minOccurs="0"/>
+ <xs:element ref="tns:hw-components" minOccurs="0"/>
+ <xs:element ref="tns:sw-components" minOccurs="0"/>
+ <xs:element ref="tns:network-routes" minOccurs="0"/>
+ <xs:element ref="tns:configurations" minOccurs="0"/>
+ <xs:element ref="tns:forwarding-paths" minOccurs="0"/>
+ <xs:element ref="tns:collections" minOccurs="0"/>
+ <xs:element ref="tns:next-hops" minOccurs="0"/>
+ <xs:element ref="tns:bfds" minOccurs="0"/>
+ <xs:element ref="tns:fqdns" minOccurs="0"/>
+ <xs:element ref="tns:connectivities" minOccurs="0"/>
+ <xs:element ref="tns:lan-port-configs" minOccurs="0"/>
+ <xs:element ref="tns:network-resources" minOccurs="0"/>
+ <xs:element ref="tns:site-resources" minOccurs="0"/>
+ <xs:element ref="tns:sdwan-vpns" minOccurs="0"/>
+ <xs:element ref="tns:devices" minOccurs="0"/>
+ <xs:element ref="tns:wan-port-configs" minOccurs="0"/>
+ <xs:element ref="tns:ext-aai-networks" minOccurs="0"/>
+ <xs:element ref="tns:label-restrictions" minOccurs="0"/>
+ <xs:element ref="tns:unis" minOccurs="0"/>
+ <xs:element ref="tns:te-link-attributes" minOccurs="0"/>
+ <xs:element ref="tns:interlayer-attachments" minOccurs="0"/>
+ <xs:element ref="tns:tunnel-termination-points" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="reserved-prop-names">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Internal map to define some reserved properties of a vertex",uniqueProps="aai-unique-key,aai-uri",indexedProps="aai-unique-key,source-of-truth,aai-node-type,aai-uri")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="last-mod-source-of-truth" type="xs:string" minOccurs="0"/>
+ <xs:element name="aai-node-type" type="xs:string" minOccurs="0"/>
+ <xs:element name="aai-created-ts" type="xs:unsignedInt" minOccurs="0"/>
+ <xs:element name="aai-unique-key" type="xs:string" minOccurs="0"/>
+ <xs:element name="aai-last-mod-ts" type="xs:unsignedInt" minOccurs="0"/>
+ <xs:element name="source-of-truth" type="xs:string" minOccurs="0"/>
+ <xs:element name="aai-uri" type="xs:string" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="edge-prop-names">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Internal map to define the properties of an edge and interpret the map EdgeRules",edgeInfo="aaiUuid,edgeLabel,direction,multiplicityRule,isParent,usesResource,hasDelTarget,SVC-INFRA,SVC-INFRA-REV",uniqueProps="aai-uuid",indexedProps="aai-uuid")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="edgeLabel" type="xs:string" minOccurs="0"/>
+ <xs:element name="direction" type="xs:string" minOccurs="0"/>
+ <xs:element name="multiplicityRule" type="xs:string" minOccurs="0"/>
+ <xs:element name="contains-other-v" type="xs:string" minOccurs="0"/>
+ <xs:element name="delete-other-v" type="xs:string" minOccurs="0"/>
+ <xs:element name="SVC-INFRA" type="xs:string" minOccurs="0"/>
+ <xs:element name="prevent-delete" type="xs:string" minOccurs="0"/>
+ <xs:element name="aai-uuid" type="xs:string" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="aai-internal">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="tns:reserved-prop-names" minOccurs="0" maxOccurs="5000"/>
+ <xs:element ref="tns:edge-prop-names" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="hardware-catalog-item">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="describes an hardware-catalog-items",indexedProps="item-name",uniqueProps="item-name",container="hardware-catalog-items",namespace="common",uriTemplate="/common/hardware-catalog-items/hardware-catalog-item/{item-name}",requiredProps="item-name,system-type,manufacturer,model,sku")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="item-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Unique name for the hardware-catalog-item")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="system-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Type of system defined by ATT")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="manufacturer" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Manufacturer of the hardware-catalog-item (ex,Cisco)")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Model of the hardware-catalog-item (ex,5501 NCS)")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="part-number" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Part number assigned by the manufacturer")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="description" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Description of the hardware-catalog-item")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="sku" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Stock-keeping-unit (ATT specific identifier for the hardware-catalog-item)")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="hardware-catalog-items">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of hardware-catalog-items")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:hardware-catalog-item" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="contact">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Contacts store the vendor information and have a relationship to the generic-vnf. In 1902, this will be populated by SDN-GC",uniqueProps="contact-name",container="contacts",namespace="common",nameProps="contact-name,vendor-type",uriTemplate="/common/contacts/contact/{contact-name}",requiredProps="contact-name")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="contact-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Name of the contact")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="contact-telephone" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Tel no. of contact")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="contact-email" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="e-mail of contact")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="vendor-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="NI (Network Integrator)SI (System Integrator) 3rd Party LCM")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="contacts">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of contacts")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:contact" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="profile">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="describes an profiles",indexedProps="profile-name,profile-role,profile-function",uniqueProps="profile-name",nameProps="profile-type",container="profiles",namespace="common",uriTemplate="/common/profiles/profile/{profile-name}",requiredProps="profile-name,profile-type,characteristics")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="profile-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Name of the profile")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="profile-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Type of profile (ex,network-power-profile)")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="profile-characteristics" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Set of characteristics of the profile.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="profile-subtype" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Descriptive subtype.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="profile-role" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="used to categorize this object in conjunction with profile-type and profile-function.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="profile-function" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="used to categorize this object in conjunction with profile-type and profile-role. The most specific category")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="profile-selflink" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="URL to endpoint where AAI can get more details")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ <xs:element ref="tns:metadata" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="profiles">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of profiles")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:profile" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="port-list">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Port List Range",dependentOn="endpoint,rule,object-group",uriTemplate="/port-list/{port}",requiredProps="port")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="port" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Port number")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="assignment" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Name or assignment for the port")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Type or usage of the port")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="operator" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Operator to apply to the port (greater than, less than, etc).")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="selector-list">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Selectors list",dependentOn="rule,object-group,endpoint,policy",uriTemplate="/selector-list/{selector}",requiredProps="selector")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="selector" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Selector")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="assignment" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Name or assignment for the selector")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Type or usage of the selector")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="rule">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="describes an rules",container="rules",dependentOn="policy",uriTemplate="/rules/rule/{rule-id}",requiredProps="rule-id,log")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="rule-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="UUID.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="direction" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="ingress or egress")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="protocol" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Positive protocol match. tcp, udp, icmpv6, sctp, udplite, integer 1-255.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="not-protocol" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Negative protocol match. tcp, udp, icmpv6, sctp, udplite, integer 1-255.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="action" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Action to perform when matching this rule.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="icmp" type="xs:string" minOccurs="0" maxOccurs="5000">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="not-icmp" type="xs:string" minOccurs="0" maxOccurs="5000">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="sequence" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Sequence number of the rule.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="threshold" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Threshold")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="status")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Version")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="count-variable" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Named variable used for counting transactions.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="log" type="xs:boolean" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(defaultValue="false",description="Boolean to indicate whether or not logging is required.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="description" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Description.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:port-list" minOccurs="0" maxOccurs="5000"/>
+ <xs:element ref="tns:selector-list" minOccurs="0" maxOccurs="5000"/>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="rules">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of rules")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:rule" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="policy">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Definition of policy",indexedProps="policy-id",uniqueProps="policy-id",container="policies",namespace="common",uriTemplate="/common/policies/policy/{policy-id}",requiredProps="policy-id,do-not-track,pre-dnat,apply-on-forward")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="policy-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Unique Policy UUID.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="policy-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Policy Name")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="policy-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Policy Type")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="policy-role" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Policy role")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="policy-function" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="policy function")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="do-not-track" type="xs:boolean" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(defaultValue="false",description="Do not track")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="pre-dnat" type="xs:boolean" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(defaultValue="false",description="Pre destination NAT")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="apply-on-forward" type="xs:boolean" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(defaultValue="false",description="apply on forward")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="selector" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Host and Interface Type Selector",dbAlias="selector-local")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="order" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Order")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Version")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Status")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="remote-asn" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Remote ASN")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="namespace" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Namespace filter to apply the policy")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="policy-description" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Description of the policy")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="policy-variables" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Set of rule variables")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:rules" minOccurs="0"/>
+ <xs:element ref="tns:selector-list" minOccurs="0" maxOccurs="5000"/>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="policies">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="tns:policy" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vlan-characteristic">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="describes an vlan characteristic",indexedProps="vlan-characteristic-id",container="vlan-characteristics",namespace="common",uriTemplate="/common/vlan-characteristics/vlan-characteristic/{vlan-characteristic-id}",requiredProps="vlan-characteristic-id,dhcp-pool,internet-access")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="vlan-characteristic-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="UUID.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="root-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Name.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="applies-to" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Device role the vlan-characteristic applies to (c-agg-leaf-a, c-agg-leaf-b, r-leaf).")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="dhcp-pool" type="xs:boolean" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(defaultValue="false",description="DHCP Agent access.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="internet-access" type="xs:boolean" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(defaultValue="false",description="Boolean to represent if requires internet access.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vlan-characteristics">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of vlan characteristics")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:vlan-characteristic" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="relationship-component">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="describes an relationship component",indexedProps="rule-node,rule-property,rule-value,component-order",container="relationship-components",dependentOn="relationship-rule",uriTemplate="common/relationship-components/relationship-component/{rule-node}",requiredProps="rule-node,rule-property,rule-value,component-order")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="rule-node" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="NARAD object")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="rule-property" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Object property")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="rule-value" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Property value")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="component-order" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Order in traversal")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="relationship-components">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of relationship components")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:relationship-component" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="relationship-rule">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="describes an relationship rule",indexedProps="rule-id,context,rule-traversals,applies-to",uniqueProps="rule-id",container="relationship-rules",namespace="common",uriTemplate="/common/relationship-rules/relationship-rule/{rule-id}",requiredProps="rule-id,context,rule-traversals,applies-to")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="rule-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="UUID.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="context" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Example global,site")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="rule-traversals" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Number of traversals")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="applies-to" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Node the related object applies to")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-components" minOccurs="0"/>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="relationship-rules">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of relationship rules")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:relationship-rule" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="common">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Namespace for common inventory resources.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:hardware-catalog-items" minOccurs="0"/>
+ <xs:element ref="tns:contacts" minOccurs="0"/>
+ <xs:element ref="tns:profiles" minOccurs="0"/>
+ <xs:element ref="tns:policies" minOccurs="0"/>
+ <xs:element ref="tns:vlan-characteristics" minOccurs="0"/>
+ <xs:element ref="tns:relationship-rules" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="notification-event-header">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="id" type="xs:string" minOccurs="0"/>
+ <xs:element name="timestamp" type="xs:string" minOccurs="0"/>
+ <xs:element name="source-name" type="xs:string" minOccurs="0"/>
+ <xs:element name="domain" type="xs:string" minOccurs="0"/>
+ <xs:element name="sequence-number" type="xs:string" minOccurs="0"/>
+ <xs:element name="severity" type="xs:string" minOccurs="0"/>
+ <xs:element name="event-type" type="xs:string" minOccurs="0"/>
+ <xs:element name="version" type="xs:string" minOccurs="0"/>
+ <xs:element name="action" type="xs:string" minOccurs="0"/>
+ <xs:element name="entity-type" type="xs:string" minOccurs="0"/>
+ <xs:element name="top-entity-type" type="xs:string" minOccurs="0"/>
+ <xs:element name="entity-link" type="xs:string" minOccurs="0"/>
+ <xs:element name="status" type="xs:string" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="notification-event">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="cambria.partition" type="xs:string" minOccurs="0"/>
+ <xs:element ref="tns:notification-event-header" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="overloaded-model">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Allows for legacy POST of old-style and new-style models",requiredProps="model-invariant-id,model-name-version-id,model-type,model-name,model-id,model-version")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="model-invariant-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Unique identifier corresponding to the main definition of a model in ASDC")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-name-version-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Unique identifier corresponding to one version of a model in ASDC")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Type of the model, e.g., service, resource, widget, etc.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Name of the model, which can change from version to version.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Invariant unique ID which does not change from version to version")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Version")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-description" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Description")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:model-vers" minOccurs="0"/>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="query-parameters">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="QueryParameters for performing a named-query or model query")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:named-query" minOccurs="0"/>
+ <xs:element ref="tns:overloaded-model" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="instance-filter">
+ <xs:complexType>
+ <xs:sequence/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="instance-filters">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="InstanceFilters for performing a named-query or model query")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:instance-filter" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="secondary-filt">
+ <xs:complexType>
+ <xs:sequence/>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="secondary-filts">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="SecondaryFilts for performing a named-query or model query")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:secondary-filt" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="model-and-named-query-search">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="ModelAndNamedQuerySearch holds query-parameters and instance-properties for performing a named-query or model query")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:query-parameters" minOccurs="0"/>
+ <xs:element ref="tns:instance-filters" minOccurs="0"/>
+ <xs:element ref="tns:secondary-filts" minOccurs="0"/>
+ <xs:element name="top-node-type" type="xs:string" minOccurs="0"/>
+ <xs:element name="secondary-filter-cut-point" type="xs:string" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="properties">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Property holder for query properties or instance properties")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="property-name" type="xs:string" minOccurs="0"/>
+ <xs:element name="property-value" type="xs:string" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="extra-property">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element name="property-name" type="xs:string" minOccurs="0"/>
+ <xs:element name="property-value" type="xs:string" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="extra-properties">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Extra properties for inventory item for response list")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:extra-property" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="inventory-response-item">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Inventory item for response list",container="inventory-response-items")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="model-name" type="xs:string" minOccurs="0"/>
+ <xs:element ref="tns:extra-properties" minOccurs="0"/>
+ <xs:element ref="tns:inventory-response-items" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="inventory-response-items">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Container for inventory items in response list",container="response-list")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:inventory-response-item" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="response-list">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Response container for the results of a named-query or model query")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:inventory-response-items" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="vnf">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Abstract vnf class",indexedProps="vnf-id",uniqueProps="vnf-id",inheritors="vce,generic-vnf",isAbstract="true",requiredProps="vnf-id")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="vnf-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Unique id of VNF. This is unique across the graph.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="uni">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Instance of an User network interface",indexedProps="id,tp-id,cvlan,operational-status,model-invariant-id,model-version-id",searchable="id",uniqueProps="id",container="unis",namespace="network",requiredProps="id",uriTemplate="/network/unis/uni/{id}")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Id that identifies the UNI")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="tp-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Termination point ID.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="cvlan" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="The cvlan for the site used for ethernet type connectivity.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="selflink" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the link to get more information for this object.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="operational-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the operational-status for this object.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-customization-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the model-customization-id for this object.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-invariant-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="the ASDC model id for this resource or service model.",visibility="deployment",requires="model-version-id",dbAlias="model-invariant-id-local")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-version-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="the ASDC model version for this resource or service model.",visibility="deployment",requires="model-invariant-id",dbAlias="model-version-id-local",privateEdge="service-design-and-creation/models/model/{model-invariant-id}/model-vers/model-ver/{model-version-id}")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="unis">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of User network interface.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:uni" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="interlayer-attachment">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Instance of an inter layer topology attachment",indexedProps="id,model-invariant-id,model-version-id",searchable="id",uniqueProps="id",container="interlayer-attachments",namespace="network",requiredProps="id",uriTemplate="/network/interlayer-attachments/interlayer-attachment/{id}")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Id that identifies the interlayer topology attachment")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="inter-layer-lockId" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Inter layer lock id")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="selflink" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the link to get more information for this object.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-customization-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the model-customization-id for this object.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-invariant-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="the ASDC model id for this resource or service model.",visibility="deployment",requires="model-version-id",dbAlias="model-invariant-id-local")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-version-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="the ASDC model version for this resource or service model.",visibility="deployment",requires="model-invariant-id",dbAlias="model-version-id-local",privateEdge="service-design-and-creation/models/model/{model-invariant-id}/model-vers/model-ver/{model-version-id}")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="interlayer-attachments">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of interlayer topology connectivities.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:interlayer-attachment" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="te-link-attribute">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Instance of an te-link-attribute",indexedProps="id,link-protection-type,access-type,operational-status,model-invariant-id,model-version-id",searchable="id",uniqueProps="id",container="te-link-attributes",namespace="network",requiredProps="id",uriTemplate="/network/te-link-attributes/te-link-attribute/{id}")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Id that identifies the TE link attribute")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="link-protection-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Indicate desired protection type of the link e.g, unprotected, shared or 1+1")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="access-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Indicate link access type e.g, point-to-point or multi-access.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="available-bandwidth" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Bandwidth available on link.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="odu-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="The type of ODU e.g, ODU1, ODU2, ODU3, ODU4.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="number" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="The value of available bandwidth.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="is-abstract" type="xs:boolean" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Indicate wheather link is abstract or native")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="selflink" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the link to get more information for this object.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="operational-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the operational-status for this object.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-customization-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the model-customization-id for this object.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-invariant-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="the ASDC model id for this resource or service model.",visibility="deployment",requires="model-version-id",dbAlias="model-invariant-id-local")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-version-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="the ASDC model version for this resource or service model.",visibility="deployment",requires="model-invariant-id",dbAlias="model-version-id-local",privateEdge="service-design-and-creation/models/model/{model-invariant-id}/model-vers/model-ver/{model-version-id}")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="te-link-attributes">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of TE link attributes.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:te-link-attribute" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="label-restriction">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Instance of an label restriction",indexedProps="id,label-start,label-end,range-bitmap,operational-status,model-invariant-id,model-version-id",searchable="id",uniqueProps="id",container="label-restrictions",namespace="network",requiredProps="id",uriTemplate="/network/label-restrictions/label-restriction/{id}")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Id that identifies the label restriction")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="label-start" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="First number in the label range")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="label-end" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Last number in the label range")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="range-bitmap" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Bitmap of available labels starting from label-start to label-end.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="label-step" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Step of labels in label range.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="inclusive-exclusive" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Indicate wheather range-bitmap items are inclusive or exclusive.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="range-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Indicate the label range e.g.trib-slot, trib-port")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="trib-slot-granularity" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Indicate trib slot granularity.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="priority" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Priority.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="selflink" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the link to get more information for this object.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="operational-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the operational-status for this object.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-customization-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the model-customization-id for this object.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-invariant-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="the ASDC model id for this resource or service model.",visibility="deployment",requires="model-version-id",dbAlias="model-invariant-id-local")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-version-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="the ASDC model version for this resource or service model.",visibility="deployment",requires="model-invariant-id",dbAlias="model-version-id-local",privateEdge="service-design-and-creation/models/model/{model-invariant-id}/model-vers/model-ver/{model-version-id}")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="label-restrictions">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of Label Restriction.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:label-restriction" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="tunnel-termination-point">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Instance of an tunnel termination point",indexedProps="ttp-id,tunnel-tp-id,name,operational-status,model-invariant-id,model-version-id",searchable="ttp-id",uniqueProps="ttp-id",container="tunnel-termination-points",namespace="network",requiredProps="ttp-id",uriTemplate="/network/tunnel-termination-points/tunnel-termination-point/{ttp-id}")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element name="ttp-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(isKey=true,description="Id that identifies the tunnel termination point")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="tunnel-tp-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="TTP ID discovered from controller")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="name" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Name of tunnel termination point")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="admin-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Admin status of TTP e.g, up,down,testing,preparing-maintenance,maintenance.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="oper-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Operational status of TTP e.g, up,down,testing,preparing-maintenance,maintenance.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="switching-capability" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Indicate switching capability of TTP e.g,PSC-1, EVPL,L2SC,TDM,OTN.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="encoding" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Encoding support by the TTP e.g, packet,ethernet,PDH,SDH,digital-wrapper,lambda,fiber,ODUK,line.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="protection-type" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Indicate supported protection type of this TTP e.g, unprotected,reroute,reroute-extra,1-for-n,unidir-1-to-1.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="inter-layer-lock-id" type="xs:int" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="correlation between related objects in ETH and OTN topology.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="selflink" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the link to get more information for this object.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="operational-status" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the operational-status for this object.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-customization-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Store the model-customization-id for this object.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-invariant-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="the ASDC model id for this resource or service model.",visibility="deployment",requires="model-version-id",dbAlias="model-invariant-id-local")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="model-version-id" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="the ASDC model version for this resource or service model.",visibility="deployment",requires="model-invariant-id",dbAlias="model-version-id-local",privateEdge="service-design-and-creation/models/model/{model-invariant-id}/model-vers/model-ver/{model-version-id}")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element name="resource-version" type="xs:string" minOccurs="0">
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="field">@org.onap.aai.annotations.Metadata(description="Used for optimistic concurrency. Must be empty on create, valid on update and delete.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ </xs:element>
+ <xs:element ref="tns:relationship-list" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="tunnel-termination-points">
+ <xs:complexType>
+ <xs:annotation>
+ <xs:appinfo>
+ <annox:annotate target="class">@org.onap.aai.annotations.Metadata(description="Collection of Tunnel Termination Point.")</annox:annotate>
+ </xs:appinfo>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:element ref="tns:tunnel-termination-point" minOccurs="0" maxOccurs="5000"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <xs:element name="inventory">
+ <xs:complexType>
+ <xs:sequence>
+ <xs:element ref="tns:search" minOccurs="0"/>
+ <xs:element ref="tns:actions" minOccurs="0"/>
+ <xs:element ref="tns:cloud-infrastructure" minOccurs="0"/>
+ <xs:element ref="tns:external-system" minOccurs="0"/>
+ <xs:element ref="tns:business" minOccurs="0"/>
+ <xs:element ref="tns:service-design-and-creation" minOccurs="0"/>
+ <xs:element ref="tns:network" minOccurs="0"/>
+ <xs:element ref="tns:aai-internal" minOccurs="0"/>
+ <xs:element ref="tns:common" minOccurs="0"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+</xs:schema>
diff --git a/adaptors/aai-service/provider/src/main/resources/aaiclient.properties b/adaptors/aai-service/provider/src/main/resources/aaiclient.properties
new file mode 100755
index 000000000..979537f8e
--- /dev/null
+++ b/adaptors/aai-service/provider/src/main/resources/aaiclient.properties
@@ -0,0 +1,76 @@
+###
+# ============LICENSE_START=======================================================
+# openECOMP : SDN-C
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights
+# reserved.
+# ================================================================================
+# 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.
+# ============LICENSE_END=========================================================
+###
+
+#
+# Configuration file for A&AI Client
+#
+
+#
+# Certificate keystore and truststore
+#
+org.onap.ccsdk.sli.adaptors.aai.ssl.trust=/opt/onap/ccsdk/data/stores/truststore.onap.client.jks
+org.onap.ccsdk.sli.adaptors.aai.ssl.trust.psswd=adminadmin
+org.onap.ccsdk.sli.adaptors.aai.host.certificate.ignore=true
+
+org.onap.ccsdk.sli.adaptors.aai.client.name=SDNC
+org.onap.ccsdk.sli.adaptors.aai.client.psswd=SDNC
+
+org.onap.ccsdk.sli.adaptors.aai.application=CCSDK
+#
+# Configuration file for A&AI Client
+#
+org.onap.ccsdk.sli.adaptors.aai.uri=https://aai.api.simpledemo.onap.org:8443
+connection.timeout=60000
+read.timeout=60000
+
+# aai version
+org.onap.ccsdk.sli.adaptors.aai.version=/v21/
+
+# query
+org.onap.ccsdk.sli.adaptors.aai.path.query=/aai/v21/search/sdn-zone-query
+org.onap.ccsdk.sli.adaptors.aai.query.nodes=/aai/v21/search/nodes-query?search-node-type={node-type}&filter={entity-identifier}:EQUALS:{entity-name}
+org.onap.ccsdk.sli.adaptors.aai.query.generic=/aai/v21/search/generic-query?key={identifier}:{value}&start-node-type={start-node-type}&include=complex&depth=3
+
+#update
+org.onap.ccsdk.sli.adaptors.aai.update=/aai/v21/actions/update
+
+# UBB Notify
+org.onap.ccsdk.sli.adaptors.aai.path.notify=/aai/v21/actions/notify
+org.onap.ccsdk.sli.adaptors.aai.notify.selflink.fqdn=<%= @ubbUri %>/restconf/config/L3SDN-API:services/layer3-service-list/{service-instance-id}
+org.onap.ccsdk.sli.adaptors.aai.notify.selflink.avpn=<%= @ubbUri %>/restconf/config/L3AVPN-EVC-API:services/service-list/{service-instance-id}/service-data/avpn-logicalchannel-information
+
+# VNF IMAGES
+org.onap.ccsdk.sli.adaptors.aai.path.vnf.image.query=/aai/v21/service-design-and-creation/vnf-images/vnf-image?application={application_model}&application-vendor={application_vendor}
+
+# service instance
+org.onap.ccsdk.sli.adaptors.aai.path.svcinst.query=/aai/v21/search/generic-query?key=service-instance.service-instance-id:{svc-instance-id}&start-node-type=service-instance&include=service-instance
+org.onap.ccsdk.sli.adaptors.aai.path.service.instance=/aai/v21/business/customers/customer/{global-customer-id}/service-subscriptions/service-subscription/{service-type}/service-instances/service-instance/{service-instance-id}
+
+# VNF IMAGES QUERY
+org.onap.ccsdk.sli.adaptors.aai.path.vnf.image.query=/aai/v21/service-design-and-creation/vnf-images/vnf-image?application={application_model}&application-vendor={application_vendor}
+
+#
+# Formatting
+#
+org.onap.ccsdk.sli.adaptors.aai.param.format=filter=%s:%s
+org.onap.ccsdk.sli.adaptors.aai.param.vnf_type=vnf-type
+org.onap.ccsdk.sli.adaptors.aai.param.physical.location.id=physical-location-id
+org.onap.ccsdk.sli.adaptors.aai.param.service.type=service-type
diff --git a/adaptors/aai-service/provider/src/main/resources/org/opendaylight/blueprint/aaiservice-blueprint.xml b/adaptors/aai-service/provider/src/main/resources/org/opendaylight/blueprint/aaiservice-blueprint.xml
new file mode 100755
index 000000000..970936610
--- /dev/null
+++ b/adaptors/aai-service/provider/src/main/resources/org/opendaylight/blueprint/aaiservice-blueprint.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ============LICENSE_START=======================================================
+ openECOMP : SDN-C
+ ================================================================================
+ Copyright (C) 2017 - 2018 AT&T Intellectual Property. All rights
+ reserved.
+ ================================================================================
+ 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.
+ ============LICENSE_END=========================================================
+ -->
+
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+ xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0"
+ odl:use-default-for-reference-types="true">
+
+ <bean id="provider" class="org.onap.ccsdk.sli.adaptors.aai.AAIServiceProvider" />
+
+ <bean id="aaiService" class="org.onap.ccsdk.sli.adaptors.aai.AAIService">
+ <argument ref="provider" />
+ </bean>
+ <service ref="aaiService">
+ <interfaces>
+ <value>org.onap.ccsdk.sli.adaptors.aai.AAIService</value>
+ <value>org.onap.ccsdk.sli.adaptors.aai.AAIClient</value>
+ </interfaces>
+ </service>
+
+</blueprint>
diff --git a/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/AAIClientRESTExecutorTest.java b/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/AAIClientRESTExecutorTest.java
new file mode 100644
index 000000000..f60b2da64
--- /dev/null
+++ b/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/AAIClientRESTExecutorTest.java
@@ -0,0 +1,126 @@
+package org.onap.ccsdk.sli.adaptors.aai;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+import static org.junit.Assert.assertNotNull;
+
+public class AAIClientRESTExecutorTest {
+
+ private static AAIClientRESTExecutor aaiExecute;
+ private static AAIService aaiService;
+
+ @BeforeClass
+ public static void setUpBeforeClass() throws Exception {
+ Properties properties = new Properties();
+ properties.setProperty("org.onap.ccsdk.sli.adaptors.aai.host.certificate.ignore", "true");
+ properties.setProperty("org.onap.ccsdk.sli.adaptors.aai.client.name", "SDNC");
+ properties.setProperty("org.onap.ccsdk.sli.adaptors.aai.client.psswd", "SDNC");
+ properties.setProperty("org.onap.ccsdk.sli.adaptors.aai.application", "CCSDK");
+ properties.setProperty("org.onap.ccsdk.sli.adaptors.aai.uri", "http://localhost:8181");
+ properties.setProperty("connection.timeout", "60000");
+ properties.setProperty("read.timeout", "60000");
+ aaiExecute = new AAIClientRESTExecutor(properties);
+ aaiService = new AAIService(properties);
+
+
+ }
+
+ @Test
+ public void testGet() {
+ Map<String, String> nameValues = new HashMap<>();
+ nameValues.put("generic-vnf.vnf-id", "vnf-001");
+ AAIRequest request = AAIRequest.createRequest("generic-vnf", nameValues);
+ try {
+ aaiExecute.get(request);
+ } catch (AAIServiceException e) {
+ }
+ assert(true);
+ assertNotNull(nameValues);
+ }
+
+ @Test
+ public void testPost() {
+ Map<String, String> nameValues = new HashMap<>();
+ nameValues.put("generic-vnf.vnf-id", "vnf-001");
+ AAIRequest request = AAIRequest.createRequest("generic-vnf", nameValues);
+ try {
+ aaiExecute.get(request);
+ } catch (AAIServiceException e) {
+ }
+ assert(true);
+ assertNotNull(nameValues);
+ }
+
+ @Test
+ public void testDelete() {
+ Map<String, String> nameValues = new HashMap<>();
+ nameValues.put("generic-vnf.vnf-id", "vnf-001");
+ AAIRequest request = AAIRequest.createRequest("generic-vnf", nameValues);
+ try {
+ aaiExecute.get(request);
+ } catch (AAIServiceException e) {
+ }
+ assert(true);
+ assertNotNull(nameValues);
+ }
+
+ @Test
+ public void testQuery() {
+ Map<String, String> nameValues = new HashMap<>();
+ nameValues.put("generic-vnf.vnf-id", "vnf-001");
+ AAIRequest request = AAIRequest.createRequest("generic-vnf", nameValues);
+ try {
+ aaiExecute.get(request);
+ } catch (AAIServiceException e) {
+ }
+ assert(true);
+ assertNotNull(nameValues);
+ }
+
+ @Test
+ public void testPatch() {
+ Map<String, String> nameValues = new HashMap<>();
+ nameValues.put("generic-vnf.vnf-id", "vnf-001");
+ AAIRequest request = AAIRequest.createRequest("generic-vnf", nameValues);
+ try {
+ aaiExecute.patch(request, "1234567890");
+ } catch (AAIServiceException e) {
+ }
+ assert(true);
+ assertNotNull(nameValues);
+ }
+
+
+
+ @Test
+ public void testLOGwriteFirstTrace() {
+ try {
+ aaiExecute.LOGwriteFirstTrace("GET", null);
+ } catch (Exception e) {
+ }
+ assert(true);
+ }
+
+ @Test
+ public void testLOGwriteDateTrace() {
+ try {
+ aaiExecute.LOGwriteDateTrace("GET", "<----- test data ------>");
+ } catch (Exception e) {
+ }
+ assert(true);
+ }
+
+ @Test
+ public void testLOGwriteEndingTrace() {
+ try {
+ aaiExecute.LOGwriteEndingTrace(200, "GET", "<----- test data ------>");
+ } catch (Exception e) {
+ }
+ assert(true);
+ }
+
+}
diff --git a/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/AAIServiceProviderTest.java b/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/AAIServiceProviderTest.java
new file mode 100644
index 000000000..bfe3738e0
--- /dev/null
+++ b/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/AAIServiceProviderTest.java
@@ -0,0 +1,31 @@
+package org.onap.ccsdk.sli.adaptors.aai;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class AAIServiceProviderTest {
+
+ private static AAIServiceProvider provider = null;
+
+ @BeforeClass
+ public static void setUpBeforeClass() throws Exception {
+ }
+
+ @Test
+ public void testAAIServiceProvider() {
+ provider = new AAIServiceProvider();
+ }
+
+ @Test
+ public void testGetProperties() {
+ provider.getProperties();
+ assert(true);
+ }
+
+ @Test
+ public void testDeterminePropertiesFile() {
+ provider.determinePropertiesFile();
+ assert(true);
+ }
+
+}
diff --git a/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/AAIServiceTest.java b/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/AAIServiceTest.java
new file mode 100755
index 000000000..079c76cbd
--- /dev/null
+++ b/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/AAIServiceTest.java
@@ -0,0 +1,212 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.aai;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.when;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.ProtocolException;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.net.ssl.HttpsURLConnection;
+import javax.ws.rs.HttpMethod;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.Spy;
+import org.mockito.runners.MockitoJUnitRunner;
+
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.databind.JsonMappingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import org.onap.aai.inventory.v21.*;
+
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.core.sli.SvcLogicResource.QueryStatus;
+import org.onap.ccsdk.sli.adaptors.aai.AAIService.TransactionIdTracker;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+
+@RunWith(MockitoJUnitRunner.class)
+public class AAIServiceTest {
+ private static AAIService aaiService = new AAIService(
+ AAIService.class.getResource(AAIService.AAICLIENT_PROPERTIES));
+
+ @Spy private AAIService aaiServiceSpy = new AAIService(
+ AAIService.class.getResource(AAIService.AAICLIENT_PROPERTIES));
+
+ @Mock private HttpsURLConnection connMock;
+
+ // @Test
+ public void existsInvalidResource_shouldReturnFailure() throws MalformedURLException, Exception {
+ QueryStatus queryStatus = aaiServiceSpy.exists("InvalidResource", null, null, null);
+ assertEquals(QueryStatus.FAILURE, queryStatus);
+ }
+
+// @Test
+ public void existsGetPserverByCallBackUrl_shouldReturnSuccess() throws MalformedURLException, Exception {
+ String key = "https://aai.api.simpledemo.onap.org:8443/aai/v11/cloud-infrastructure/pservers/pserver/chcil129snd";
+ String fileLocation = "json/pserverJson.txt";
+ SvcLogicContext ctx = new SvcLogicContext();
+ setConnMock();
+
+ when(aaiServiceSpy.getConfiguredConnection(new URL(key), HttpMethod.GET)).thenReturn(connMock);
+ when(connMock.getResponseCode()).thenReturn(200);
+ when(connMock.getInputStream()).thenReturn(getClass().getClassLoader().getResourceAsStream(fileLocation));
+
+ QueryStatus queryStatus = aaiServiceSpy.exists("pserver", key, "prefix.", ctx);
+
+ assertEquals(QueryStatus.SUCCESS, queryStatus);
+ }
+
+// @Test
+ public void existsGetPserverByCallBackUrl_throwsExceptionAndReturnsFailure()
+ throws MalformedURLException, Exception {
+ String key = "https://aai.api.simpledemo.onap.org:8443/aai/v11/cloud-infrastructure/pservers/pserver/chcil129snd";
+ String fileLocation = "json/pserverJson.txt";
+ SvcLogicContext ctx = new SvcLogicContext();
+ setConnMock();
+
+ when(aaiServiceSpy.getConfiguredConnection(new URL(key), HttpMethod.GET)).thenReturn(connMock);
+ when(connMock.getResponseCode()).thenReturn(200);
+ when(connMock.getInputStream()).thenReturn(getClass().getClassLoader().getResourceAsStream(fileLocation));
+
+ when(aaiServiceSpy.dataChangeRequestAaiData(key, Pserver.class)).thenThrow(
+ new AAIServiceException("testException"));
+
+ QueryStatus queryStatus = aaiServiceSpy.exists("pserver", key, "prefix.", ctx);
+
+ assertEquals(QueryStatus.FAILURE, queryStatus);
+ }
+
+// @Test
+ public void pserverDataChangeRequestData_shouldSucceed() throws Exception {
+ String fileLocation = "json/pserverJson.txt";
+ String url = "https://aai.api.simpledemo.onap.org:8443/aai/v11/cloud-infrastructure/pservers/pserver/chcil129snd";
+ setConnMock();
+
+ when(aaiServiceSpy.getConfiguredConnection(new URL(url), HttpMethod.GET)).thenReturn(connMock);
+ when(connMock.getResponseCode()).thenReturn(200);
+ when(connMock.getInputStream()).thenReturn(getClass().getClassLoader().getResourceAsStream(fileLocation));
+
+ Pserver pserver = aaiServiceSpy.dataChangeRequestAaiData(url, Pserver.class);
+
+ assertEquals("chcil129snd", pserver.getHostname());
+ }
+
+// @Test
+ public void pserverDataChangeRequestData_shouldReturnNullFor404() throws Exception {
+ String fileLocation = "json/pserverJson.txt";
+ String url = "https://aai.api.simpledemo.onap.org:8443/aai/v11/cloud-infrastructure/pservers/pserver/chcil129snd";
+ setConnMock();
+
+ when(aaiServiceSpy.getConfiguredConnection(new URL(url), HttpMethod.GET)).thenReturn(connMock);
+ when(connMock.getResponseCode()).thenReturn(404);
+ when(connMock.getErrorStream()).thenReturn(getClass().getClassLoader().getResourceAsStream(fileLocation));
+
+ Pserver pserver = aaiServiceSpy.dataChangeRequestAaiData(url, Pserver.class);
+
+ assertEquals(null, pserver);
+ }
+
+ @Test(expected = AAIServiceException.class)
+ public void dataChangeRequestData_throwsAAIServiceException() throws Exception {
+ String fileLocation = "json/pserverJson.txt";
+ String url = "https://aai.api.simpledemo.onap.org:8443/aai/v11/cloud-infrastructure/pservers/pserver/chcil129snd";
+ setConnMock();
+
+ // The following lines are not needed and cause latest version of mockito to throw an exception
+// when(aaiServiceSpy.getConfiguredConnection(new URL(url), HttpMethod.GET)).thenReturn(connMock);
+// when(connMock.getResponseCode()).thenReturn(500);
+// when(connMock.getInputStream()).thenReturn(getClass().getClassLoader().getResourceAsStream(fileLocation));
+
+ aaiServiceSpy.dataChangeRequestAaiData(url, Class.class);
+ }
+
+ public String readFileToString(String fileName) throws IOException, URISyntaxException {
+ URL url = AAIServiceTest.class.getResource(fileName);
+ Path resPath = Paths.get(url.toURI());
+
+ return new String(Files.readAllBytes(resPath), "UTF8");
+ }
+
+ public <T> T getObjectFromJson(String text, Class<T> type)
+ throws JsonParseException, JsonMappingException, IOException {
+ ObjectMapper mapper = AAIService.getObjectMapper();
+
+ return type.cast(mapper.readValue(text, type));
+ }
+
+ private void setConnMock() throws ProtocolException {
+ // Set up the connection properties
+ connMock.setRequestProperty("Connection", "close");
+ connMock.setDoInput(true);
+ connMock.setDoOutput(true);
+ connMock.setUseCaches(false);
+ connMock.setConnectTimeout(1000);
+ connMock.setReadTimeout(1000);
+ connMock.setRequestMethod(HttpMethod.GET);
+ connMock.setRequestProperty("Accept", "application/json");
+ connMock.setRequestProperty("Content-Type", "application/json");
+ connMock.setRequestProperty("X-FromAppId", "testId");
+ connMock.setRequestProperty("X-TransactionId", TransactionIdTracker.getNextTransactionId());
+ }
+
+ @Test
+ public void testSetStatusMessage_shouldSucceed() throws SvcLogicException, MalformedURLException {
+ SvcLogicContext ctx = new SvcLogicContext();
+ Map<String, String> parameters = new HashMap<String, String>();
+
+ parameters.put("key1", "ActivateSubnet failure, need to manually activate in EIPAM.");
+ aaiService.setStatusMethod(parameters, ctx);
+
+ Pattern r8601 = Pattern.compile(
+ "(\\d{4})-(\\d{2})-(\\d{2})T((\\d{2}):(\\d{2}):(\\d{2}))Z");
+ Matcher isoDate = r8601.matcher(ctx.getAttribute("aai-summary-status-message"));
+
+ assertTrue(isoDate.lookingAt());
+
+ assertTrue(ctx.getAttribute("aai-summary-status-message")
+ .contains("ActivateSubnet failure, need to manually activate in EIPAM."));
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void testSetStatusMessage_nullContext() throws SvcLogicException, MalformedURLException {
+ SvcLogicContext ctx = null;
+ Map<String, String> parameters = new HashMap<String, String>();
+
+ parameters.put("key1", "ActivateSubnet failure, need to manually activate in EIPAM.");
+ aaiService.setStatusMethod(parameters, ctx);
+ }
+}
diff --git a/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/ActionUpdateTest.java b/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/ActionUpdateTest.java
new file mode 100755
index 000000000..64f9b45ef
--- /dev/null
+++ b/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/ActionUpdateTest.java
@@ -0,0 +1,44 @@
+package org.onap.ccsdk.sli.adaptors.aai;
+
+import static org.junit.Assert.*;
+
+import java.util.ArrayList;
+
+import org.onap.ccsdk.sli.adaptors.aai.update.Action;
+import org.onap.ccsdk.sli.adaptors.aai.update.ActionDatum;
+import org.junit.Test;
+
+public class ActionUpdateTest {
+ @Test
+ public void getActionData() throws Exception {
+ final Action resolver = new Action();
+ assertNotNull(resolver.getActionData());
+ }
+
+ @Test
+ public void setActionData() throws Exception {
+ final Action resolver = new Action();
+ resolver.setActionData( new ArrayList<ActionDatum>());
+ assertNotNull(resolver);
+ }
+
+ @Test
+ public void setActionType() throws Exception {
+ final Action resolver = new Action();
+ resolver.setActionType("create");
+ assertEquals("create", resolver.getActionType());
+ }
+
+ @Test
+ public void getAdditionalProperties() throws Exception {
+ final Action resolver = new Action();
+ assertNotNull(resolver.getAdditionalProperties());
+ }
+
+ @Test
+ public void setAdditionalProperty() throws Exception {
+ final Action resolver = new Action();
+ resolver.setAdditionalProperty("outcome", "success");
+ assertEquals("success", resolver.getAdditionalProperties().get("outcome"));
+ }
+} \ No newline at end of file
diff --git a/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/AutoGeneratedRegressionTest.java b/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/AutoGeneratedRegressionTest.java
new file mode 100755
index 000000000..5ac503ff5
--- /dev/null
+++ b/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/AutoGeneratedRegressionTest.java
@@ -0,0 +1,906 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.aai;
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.File;
+import java.io.IOException;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Scanner;
+import java.util.Set;
+import java.util.Stack;
+import java.util.UUID;
+
+import javax.xml.bind.SchemaOutputResolver;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.transform.Result;
+import javax.xml.transform.stream.StreamResult;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathExpression;
+import javax.xml.xpath.XPathFactory;
+
+import org.apache.commons.lang.RandomStringUtils;
+import org.apache.commons.lang.StringUtils;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+import org.onap.ccsdk.sli.adaptors.aai.data.AAIDatum;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicResource.QueryStatus;
+import org.onap.aai.inventory.v21.GenericVnf;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.core.annotation.AnnotationUtils;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class AutoGeneratedRegressionTest {
+
+ static {
+ System.setProperty(org.slf4j.impl.SimpleLogger.DEFAULT_LOG_LEVEL_KEY, "INFO");
+ System.setProperty(org.slf4j.impl.SimpleLogger.LOG_FILE_KEY, String.format("AutoGeneratedRegressionTest-%d.txt", System.currentTimeMillis()));
+ }
+ private static final Logger LOG = LoggerFactory.getLogger(AutoGeneratedRegressionTest.class);
+
+
+ protected static AAIClient client;
+
+ protected Map<String, String> cache = new HashMap<String, String>();
+
+ @BeforeClass
+ public static void setUp() throws Exception {
+ URL url = AAIService.class.getResource(AAIService.AAICLIENT_PROPERTIES);
+ client = new AAIService(url);
+ LOG.info("----------------------- aicAAIResourceTest.setUp -----------------------");
+ }
+
+ @AfterClass
+ public static void tearDown() throws Exception {
+ client = null;
+ LOG.info("----------------------- AAIResourceTest.tearDown -----------------------");
+ }
+
+
+ @Test
+ public void mainLoadTest ()
+ {
+ try
+ {
+ String currentDir = System.getProperty("user.dir");
+ File dir = new File(currentDir);
+ if(!dir.exists()) {
+ System.exit(1);
+ }
+ dir = new File(dir, "src/main/resources");
+ if(!dir.exists()) {
+ System.exit(1);
+ }
+ // parse the document
+ File file = new File(dir, "aai_schema_v11.xsd");
+ if(!file.exists()) {
+ assert(false);
+ return;
+ }
+
+ DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
+ DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
+ Document doc = dBuilder.parse(file);
+
+ Stack<String> stack = new Stack<String>();
+ List<String> commands = new ArrayList<String>();
+ listSubNodes("network", doc, stack, commands);
+ listSubNodes("cloud-infrastructure", doc, stack, commands);
+ listSubNodes("service-design-and-creation", doc, stack, commands);
+ listSubNodes("license-management", doc, stack, commands);
+ listSubNodes("business", doc, stack, commands);
+
+ String[] requestDefinition = commands.toArray(new String[0]);
+ LOG.info("\n----------------------------");
+
+ executeTests(requestDefinition);
+ }
+ catch (Throwable e)
+ {
+ LOG.error("", e);
+ }
+ }
+
+ @Test
+ public void testFromFile() {
+ String filename = "testCommands.txt";
+ List<String> lines = new ArrayList<String>();
+ Scanner scanner = null;
+
+ try {
+ File testFile = new File(filename);
+ if(!testFile.exists())
+ return;
+ scanner = new Scanner(testFile);
+ while (scanner.hasNextLine()) {
+ lines.add(scanner.nextLine());
+ }
+ } catch (Exception exc) {
+
+ } finally {
+ if(scanner != null)
+ scanner.close();
+ }
+
+ String[] requestDefinition = lines.toArray(new String[0]);
+ executeTests(requestDefinition);
+ }
+
+
+ @Test
+ public void test01AutoGeneratedRequest() {
+
+ String[] requestDefinition = {
+ "save|generic-vnf|generic-vnf.vnf-id:assign:value:adb28ac0-a260-4b7d-9ce5-adf15733c458",
+ "update|generic-vnf|generic-vnf.vnf-id:assign:value:adb28ac0-a260-4b7d-9ce5-adf15733c458",
+ "query|generic-vnf|generic-vnf.vnf-id:assign:value:adb28ac0-a260-4b7d-9ce5-adf15733c458",
+ "delete|generic-vnf|generic-vnf.vnf-id:assign:value:adb28ac0-a260-4b7d-9ce5-adf15733c458"
+ };
+
+ executeTests(requestDefinition);
+ }
+
+ public void executeTests(String[] requestDefinition) {
+
+ for(String line : requestDefinition){
+ LOG.info("Executing: " + line);
+
+ // parse request line resource | key structure
+ String[] segments = line.split("\\|");
+ String action = segments[0];
+ String resource = segments[1];
+ String[] tmpKeys = segments[2].split("&");
+ // String array keyStructure can be tmpKey.
+ // options :assign:uuid:cache
+ // :cached
+ // :query:random
+
+
+ String localId = null;
+
+ List<String> keys = new ArrayList<String>();
+ String keyLine = null;
+
+ for(String instruction : tmpKeys) {
+ String[] parts = instruction.split(":");
+ String identifier = parts[0];
+ String method = parts[2];
+
+ if(identifier.startsWith(resource)) {
+ localId = identifier;
+ } else if(identifier.startsWith("l-interface") && "l2-bridge-bgf".equals(resource)) {
+ localId = identifier;
+ } else if(identifier.startsWith("l-interface") && "l2-bridge-sbg".equals(resource)) {
+ localId = identifier;
+ } else if("nodes-query".equals(resource)) {
+ localId = identifier;
+ }
+
+ switch(parts[1]) {
+ case "assign":
+ String postProcesss = parts[3];
+ keyLine = processAssign(identifier, method, postProcesss);
+ if(keyLine != null && !keyLine.trim().isEmpty()) {
+ keys.add(keyLine);
+ }
+ break;
+ case "cached":
+ keyLine = processCached(identifier, method);
+ if(keyLine != null && !keyLine.trim().isEmpty()) {
+ keys.add(keyLine);
+ }
+ break;
+ }
+
+ }
+
+ List<String> x = Arrays.asList(localId.split("\\."));
+ switch(action){
+ case "save":
+ testAutoGeneratedSaveRequest(resource, keys, x.get(x.size() - 1), cache.get(localId));
+ break;
+ case "update":
+ testAutoGeneratedUpdateRequest(resource, keys, x.get(x.size() - 1), cache.get(localId));
+ break;
+
+ case "query":
+ test03AutoGeneratedQueryRequest(resource, keys);
+ break;
+ case "delete":
+ test03AutoGeneratedDeleteRequest(resource, keys);
+ break;
+ }
+ }
+
+ LOG.info("done");
+ }
+
+
+ public void testAutoGeneratedSaveRequest(String resource, List<String> requestKeys, String identifier, String idValue) {
+ LOG.info("----------------------- Test: " + new Object(){}.getClass().getEnclosingMethod().getName() + " -----------------------");
+
+ try
+ {
+ Map<String, String> nameValues = keyToHashMap(StringUtils.join(requestKeys, " AND "), new SvcLogicContext());
+ AAIRequest request = AAIRequest.createRequest(resource, nameValues);
+ Class<AAIDatum> resourceClass = (Class<AAIDatum>) (request==null ? GenericVnf.class : request.getModelClass());
+
+ Map<String, String> data = new HashMap<String, String>();
+
+ for(Field field : resourceClass.getDeclaredFields()) {
+ String type = field.getType().getName();
+ switch(type){
+ case "bool":
+ case "boolean":
+ type = Boolean.class.getName();
+ break;
+ case "int":
+ type = Integer.class.getName();
+ break;
+ case "long":
+ type = Long.class.getName();
+ break;
+
+ }
+ if(type.startsWith("java.lang.")){
+ Annotation[] fieldAnnotations = field.getAnnotations();
+ for(int i = 0; i < fieldAnnotations.length; i++) {
+ Annotation a = fieldAnnotations[i];
+ if(a instanceof JsonProperty){
+ JsonProperty pa = (JsonProperty)a;
+ String name = pa.value();
+ String value;
+ switch(type) {
+ case "java.lang.Integer":
+ case "java.lang.Long":
+ value = RandomStringUtils.random(6, false, true);
+ break;
+ case "java.lang.Boolean":
+ value = "false";
+ break;
+ default:
+ if(name.equals(identifier)) {
+ value = idValue;
+ } else {
+ value = RandomStringUtils.random(10, true, false);
+ }
+ }
+ data.put(name, value);
+ } else
+ if(a instanceof javax.xml.bind.annotation.XmlElement) {
+ XmlElement xe = (XmlElement)a;
+ String name = xe.name();
+ if("model-version-id".equals(name)) {
+ continue;
+ }
+ if("model-invariant-id".equals(name)) {
+ continue;
+ }
+ if("link-type".equals(name)){
+ data.put(name, "roadmTail");
+ continue;
+ }
+ if("operational-status".equals(name)){
+ data.put(name, "available");
+ continue;
+ }
+ if(name.equals(identifier)) {
+ data.put(name, idValue);
+ continue;
+ }
+
+ String value;
+ switch(type) {
+ case "java.lang.Integer":
+ case "java.lang.Long":
+ value = RandomStringUtils.random(6, false, true);
+ break;
+ case "java.lang.Boolean":
+ value = "false";
+ break;
+ default:
+ if(name.equals(identifier)) {
+ value = idValue;
+ } else {
+ value = RandomStringUtils.random(10, true, false);
+ }
+ }
+ data.put(name, value);
+ }
+ }
+ }
+ }
+
+ SvcLogicContext ctx = new SvcLogicContext();
+
+ data.remove("resource-version");
+
+ QueryStatus resp = null;
+
+ //(String resource, boolean force, boolean localOnly, String key, Map<String, String> parms, String prefix, SvcLogicContext ctx)
+ resp = client.save(resource, false, false, StringUtils.join(requestKeys, " AND "), data, "aaidata", ctx);
+ if(resp == QueryStatus.SUCCESS) {
+ LOG.info(String.format("Save %s successfull", resource));
+ } else {
+ LOG.info(String.format("Save %s failed due to : %s", resource, ctx.getAttribute("aaidata.error.message")));
+ }
+ }
+ catch (Throwable e)
+ {
+ LOG.error("Caught exception", e);
+ fail("Caught exception");
+ }
+ }
+
+ public void test03AutoGeneratedQueryRequest(String resource, List<String> requestKeys) {
+ LOG.info("----------------------- Test: " + new Object(){}.getClass().getEnclosingMethod().getName() + " -----------------------");
+
+ SvcLogicContext ctx = new SvcLogicContext();
+ try
+ {
+
+ QueryStatus response = null;
+
+ response = client.query(resource, false, null, StringUtils.join(requestKeys, " AND "), "aaiTest", null, ctx);
+ if(response == QueryStatus.SUCCESS) {
+ LOG.info(String.format("Query %s successfull", resource));
+ Set<String> tokens = ctx.getAttributeKeySet();
+ Map<String, String> reponseData = new HashMap<String, String>();
+
+ String responsePrefix = String.format("%s", "aaiTest");
+
+ for(String token : tokens) {
+ if(token.startsWith(responsePrefix)){
+ reponseData.put(token, ctx.getAttribute(token));
+ } else {
+ LOG.info(String.format("%s = ", token, ctx.getAttribute(token)));
+ }
+ }
+
+ LOG.info("AAIResponse: " + response.toString());
+ assertTrue("AAIRequest:"+resource, reponseData.size() > 0);
+ } else {
+ LOG.info(String.format("Query %s failed due to : %s", resource, ctx.getAttribute("aaidata.error.message")));
+ assert(false);
+ }
+ }
+ catch (Throwable e)
+ {
+ LOG.error("Caught exception", e);
+ }
+ }
+
+
+ public void test03AutoGeneratedDeleteRequest(String resource, List<String> requestKeys) {
+ LOG.info("----------------------- Test: " + new Object(){}.getClass().getEnclosingMethod().getName() + " -----------------------");
+
+ try
+ {
+ SvcLogicContext ctx = new SvcLogicContext();
+
+ QueryStatus response = null;
+
+ response = client.delete(resource, StringUtils.join(requestKeys, " AND "), ctx);
+ if(response == QueryStatus.SUCCESS) {
+ LOG.info(String.format("Delete %s successfull", resource));
+ } else {
+ LOG.info(String.format("Delete %s failed due to : %s", resource, ctx.getAttribute("aaiDelete.error.message")));
+ }
+ }
+ catch (Throwable e)
+ {
+ LOG.error("Caught exception", e);
+ fail("Caught exception");
+ }
+ }
+
+ public void testAutoGeneratedUpdateRequest(String resource, List<String> requestKeys, String identifier, String idValue) {
+ LOG.info("----------------------- Test: " + new Object(){}.getClass().getEnclosingMethod().getName() + " -----------------------");
+
+ try
+ {
+ Map<String, String> nameValues = keyToHashMap(StringUtils.join(requestKeys, " AND "), new SvcLogicContext());
+ AAIRequest request = AAIRequest.createRequest(resource, nameValues);
+ Class<AAIDatum> resourceClass = (Class<AAIDatum>) (request==null ? GenericVnf.class : request.getModelClass());
+
+ Map<String, String> data = new HashMap<String, String>();
+
+ boolean skipFirst = true;
+ boolean breakLoop = false;
+ for(Field field : resourceClass.getDeclaredFields()) {
+ if(skipFirst){
+ skipFirst = false;
+ continue;
+ }
+ if(breakLoop){
+ break;
+ }
+ String type = field.getType().getName();
+ if(type.startsWith("java.lang.")){
+ Annotation[] fieldAnnotations = field.getAnnotations();
+ for(int i = 0; i < fieldAnnotations.length; i++) {
+ Annotation a = fieldAnnotations[i];
+ if(a instanceof JsonProperty){
+ JsonProperty pa = (JsonProperty)a;
+ String name = pa.value();
+ String value;
+ switch(type) {
+ case "java.lang.Integer":
+ case "java.lang.Long":
+ value = RandomStringUtils.random(6, false, true);
+ break;
+ case "java.lang.Boolean":
+ value = "false";
+ break;
+ default:
+ if(name.equals(identifier)) {
+ value = idValue;
+ } else {
+ value = RandomStringUtils.random(10, true, false);
+ }
+ }
+ data.put(name, value);
+ breakLoop = true;
+ } else
+ if(a instanceof javax.xml.bind.annotation.XmlElement) {
+ XmlElement xe = (XmlElement)a;
+ String name = xe.name();
+ if("link-type".equals(name)){
+ data.put(name, "roadmTail");
+ continue;
+ }
+ if("operational-status".equals(name)){
+ data.put(name, "available");
+ continue;
+ }
+ String value;
+ switch(type) {
+ case "java.lang.Integer":
+ case "java.lang.Long":
+ value = RandomStringUtils.random(6, false, true);
+ break;
+ case "java.lang.Boolean":
+ value = "false";
+ break;
+ default:
+ if(name.equals(identifier)) {
+ value = idValue;
+ } else {
+ value = RandomStringUtils.random(10, true, false);
+ }
+ }
+ data.put(name, value);
+ breakLoop = true;
+ }
+ }
+ }
+ }
+
+ SvcLogicContext ctx = new SvcLogicContext();
+
+ data.remove("resource-version");
+
+ QueryStatus resp = null;
+
+ //client.update("ipsec-configuration", "ipsec-configuration.ipsec-configuration-id = 'testConfigurationId01'", data, "aaiTest", ctx);
+ resp = client.update(resource, StringUtils.join(requestKeys, " AND "), data, "aaidata", ctx);
+ if(resp == QueryStatus.SUCCESS) {
+ LOG.info(String.format("Update %s successfull", resource));
+ } else {
+ LOG.info(String.format("Update %s failed due to : %s", resource, ctx.getAttribute("aaidata.error.message")));
+ }
+
+ }
+ catch (Throwable e)
+ {
+ LOG.error("Caught exception", e);
+ fail("Caught exception");
+ }
+ }
+
+ static ArrayList<Method> findSetters(Class<?> c) {
+ ArrayList<Method> list = new ArrayList<Method>();
+ Method[] methods = c.getDeclaredMethods();
+ for (Method method : methods)
+ if (isGetter(method))
+ list.add(method);
+ return list;
+ }
+
+
+ public static boolean isGetter(Method method) {
+ if (Modifier.isPublic(method.getModifiers()) &&
+ method.getParameterTypes().length == 0) {
+ if (method.getName().matches("^get[A-Z].*") &&
+ !method.getReturnType().equals(void.class))
+ return true;
+ if (method.getName().matches("^is[A-Z].*") &&
+ method.getReturnType().equals(boolean.class))
+ return true;
+ }
+ return false;
+ }
+
+ public static boolean isSetter(Method method) {
+ return Modifier.isPublic(method.getModifiers()) &&
+ method.getReturnType().equals(void.class) &&
+ method.getParameterTypes().length == 1 &&
+ method.getName().matches("^set[A-Z].*");
+ }
+
+ private String processAssign(String identifier, String method, String postProcess) {
+ String value = null;
+ if("uuid".equals(method)) {
+ value = UUID.randomUUID().toString();
+ }
+
+ if("cache".equals(postProcess)) {
+ cache.put(identifier, value);
+ }
+
+ if("value".equals(method)) {
+ cache.put(identifier, postProcess);
+ value = postProcess;
+ }
+
+ String key = String.format("%s = '%s'", identifier, value);
+ return key;
+ }
+
+ private String processCached(String identifier, String method) {
+ String value = cache.get(identifier);
+
+ String key = String.format("%s = '%s'", identifier, value);
+ return key;
+ }
+
+ protected HashMap<String,String> keyToHashMap(String key, SvcLogicContext ctx) {
+ if (key == null) {
+ return (null);
+ }
+
+ LOG.debug("Converting key [" + key + "] to where clause");
+
+ if (key.startsWith("'") && key.endsWith("'")) {
+ key = key.substring(1, key.length() - 1);
+
+ LOG.debug("Stripped outer single quotes - key is now [" + key + "]");
+ }
+
+ String[] keyTerms = key.split("\\s+");
+
+ String term1 = null;
+ String op = null;
+ String term2 = null;
+ HashMap<String, String> results = new HashMap<String, String>();
+
+ for (int i = 0; i < keyTerms.length; i++) {
+ if (term1 == null) {
+ if ("and".equalsIgnoreCase(keyTerms[i])
+ || "or".equalsIgnoreCase(keyTerms[i])) {
+ // Skip over ADD/OR
+ } else {
+ term1 = resolveTerm(keyTerms[i], ctx);
+ }
+ } else if (op == null) {
+ if ("==".equals(keyTerms[i])) {
+ op = "=";
+ } else {
+ op = keyTerms[i];
+ }
+ } else {
+ term2 = resolveTerm(keyTerms[i], ctx);
+ term2 = term2.trim().replace("'", "").replace("$", "").replace("'", "");
+ results.put(term1, term2);
+
+ term1 = null;
+ op = null;
+ term2 = null;
+ }
+ }
+
+ return (results);
+ }
+
+ private String resolveTerm(String term, SvcLogicContext ctx) {
+ if (term == null) {
+ return (null);
+ }
+
+ LOG.debug("resolveTerm: term is " + term);
+
+ if (term.startsWith("$") && (ctx != null)) {
+ // Resolve any index variables.
+
+ return ("'" + resolveCtxVariable(term.substring(1), ctx) + "'");
+ } else if (term.startsWith("'") || term.startsWith("\"")) {
+ return (term);
+ } else {
+ return (term.replaceAll("-", "_"));
+
+ }
+
+ }
+
+ private String resolveCtxVariable(String ctxVarName, SvcLogicContext ctx) {
+
+ if (ctxVarName.indexOf('[') == -1) {
+ // Ctx variable contains no arrays
+ return (ctx.getAttribute(ctxVarName));
+ }
+
+ // Resolve any array references
+ StringBuffer sbuff = new StringBuffer();
+ String[] ctxVarParts = ctxVarName.split("\\[");
+ sbuff.append(ctxVarParts[0]);
+ for (int i = 1; i < ctxVarParts.length; i++) {
+ if (ctxVarParts[i].startsWith("$")) {
+ int endBracketLoc = ctxVarParts[i].indexOf("]");
+ if (endBracketLoc == -1) {
+ // Missing end bracket ... give up parsing
+ LOG.warn("Variable reference " + ctxVarName
+ + " seems to be missing a ']'");
+ return (ctx.getAttribute(ctxVarName));
+ }
+
+ String idxVarName = ctxVarParts[i].substring(1, endBracketLoc);
+ String remainder = ctxVarParts[i].substring(endBracketLoc);
+
+ sbuff.append("[");
+ sbuff.append(ctx.getAttribute(idxVarName));
+ sbuff.append(remainder);
+
+ } else {
+ // Index is not a variable reference
+ sbuff.append("[");
+ sbuff.append(ctxVarParts[i]);
+ }
+ }
+
+ return (ctx.getAttribute(sbuff.toString()));
+ }
+
+// @Test
+ public void test90QueryTenantRequest()
+ {
+ LOG.info("----------------------- Test: " + new Object(){}.getClass().getEnclosingMethod().getName() + " -----------------------");
+
+ URL url;
+
+ try {
+ url = client.requestVserverURLNodeQuery("bpsx0001vm001bps001");
+ url = new URL("https://mtanjv9aaas03.aic.cip.att.com:8443/aai/v4/cloud-infrastructure/tenants/tenant/6b012c07bdf1427190ae58f794a86344/vservers/vserver/5acfe828-82e9-swgk092815-13-4d2c-85bb-9c2c1fafcce6");
+ client.getTenantIdFromVserverUrl(url);
+ } catch (Exception e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+ static class MySchemaOutputResolver extends SchemaOutputResolver {
+
+ public Result createOutput(String namespaceURI, String suggestedFileName) throws IOException {
+ File file = new File(suggestedFileName);
+ StreamResult result = new StreamResult(file);
+ result.setSystemId(file.getAbsolutePath());
+ return result;
+ }
+
+ }
+
+ private static void listSubNodes(String parent, Document doc, Stack<String> stack, List<String> commands) throws Exception {
+ XPathFactory xFactory = XPathFactory.newInstance();
+ XPath xPath = xFactory.newXPath();
+ String format = "/schema/element[@name='%s']/complexType/sequence/element[@ref]";
+
+ String path = String.format(format, parent);
+
+// XPathExpression exp = xPath.compile("/schema/element[@name='generic-vnf']/complexType/sequence/element[@ref]");
+ XPathExpression exp = xPath.compile(path);
+
+ NodeList nl = (NodeList)exp.evaluate(doc.getFirstChild(), XPathConstants.NODESET);
+ LOG.debug("Nodes to process : "+nl.getLength());
+ for (int index = 0; index < nl.getLength(); index++) {
+
+ Node node = nl.item(index);
+
+ if(!(node instanceof Element))
+ continue;
+
+ String classAlias = null;
+
+ if(node.hasAttributes())
+ {
+ String nm = ((Element)node).getAttribute("ref");
+ if(nm != null && !nm.isEmpty()) {
+ String[] split = nm.split(":");
+ classAlias = split[split.length - 1];
+ if("relationship-list".equals(classAlias))
+ continue;
+ if("metadata".equals(classAlias))
+ continue;
+ if("classes-of-service".equals(classAlias)) {
+ classAlias = "class-of-service";
+ } else if("l3-interface-ipv4-address-list".equals(classAlias)) {
+ ;
+ } else if("l3-interface-ipv6-address-list".equals(classAlias)) {
+ ;
+ } else if("cvlan-tags".equals(classAlias)) {
+ classAlias = "cvlan-tag-entry";
+ } else if("network-policies".equals(classAlias)) {
+ classAlias = "network-policy";
+ } else if("complexes".equals(classAlias)) {
+ classAlias = "complex";
+ } else if("dvs-switches".equals(classAlias)) {
+ classAlias = "dvs-switch";
+ } else if("service-capabilities".equals(classAlias)) {
+ classAlias = "service-capability";
+ } else {
+ classAlias = classAlias.substring(0, classAlias.length() -1);
+ }
+ AAIRequest request = AAIRequest.createRequest(classAlias, new HashMap<String, String>());
+ if(request != null) {
+ Class<?> clazz = request.getModelClass();
+ Field[] fieldz = clazz.getDeclaredFields();
+ Field field = fieldz[0];
+ String fieldName = field.getName();
+ XmlElement annotation = field.getAnnotation(XmlElement.class);
+
+ Map<String, Object> map = AnnotationUtils.getAnnotationAttributes(annotation);
+ String id = (String)map.get("name");
+ if("##default".equals(id)) {
+ id = fieldName;
+ }
+
+ if("cloud-region".equals(classAlias)) {
+ String keystring = "cloud-region.cloud-owner:assign:value:att-aic&cloud-region.cloud-region-id:assign:value:AAIAIC25";
+ stack.push(keystring);
+ String[] array = stack.toArray(new String[0]);
+ String key = StringUtils.join(array, "&");
+
+ String query = String.format("query|%s|%s", classAlias, key);
+ commands.add(query);
+ listSubNodes(classAlias, doc, stack, commands);
+ stack.pop();
+ } else if("entitlement".equals(classAlias)) {
+ String keystring = "entitlement.group-uuid:assign:value:"+UUID.randomUUID()+"&entitlement.resource-uuid:assign:value:"+UUID.randomUUID();
+ stack.push(keystring);
+ String[] array = stack.toArray(new String[0]);
+ String key = StringUtils.join(array, "&");
+
+ String query = String.format("query|%s|%s", classAlias, key);
+ commands.add(query);
+ listSubNodes(classAlias, doc, stack, commands);
+ stack.pop();
+ } else if("license".equals(classAlias)) {
+ String keystring = "license.group-uuid:assign:value:"+UUID.randomUUID()+"&license.resource-uuid:assign:value:"+UUID.randomUUID();
+ stack.push(keystring);
+ String[] array = stack.toArray(new String[0]);
+ String key = StringUtils.join(array, "&");
+
+ String query = String.format("query|%s|%s", classAlias, key);
+ commands.add(query);
+ listSubNodes(classAlias, doc, stack, commands);
+ stack.pop();
+ } else if("route-target".equals(classAlias)) {
+ String keystring = "route-target.global-route-target:assign:value:"+UUID.randomUUID()+"&route-target.route-target-role:assign:value:"+UUID.randomUUID();
+ stack.push(keystring);
+ String[] array = stack.toArray(new String[0]);
+ String key = StringUtils.join(array, "&");
+
+ String query = String.format("query|%s|%s", classAlias, key);
+ commands.add(query);
+ listSubNodes(classAlias, doc, stack, commands);
+ stack.pop();
+ } else if("service-capability".equals(classAlias)) {
+ String keystring = "service-capability.service-type:assign:value:"+UUID.randomUUID()+"&service-capability.vnf-type:assign:value:"+UUID.randomUUID();
+ stack.push(keystring);
+ String[] array = stack.toArray(new String[0]);
+ String key = StringUtils.join(array, "&");
+
+ String query = String.format("query|%s|%s", classAlias, key);
+ commands.add(query);
+ listSubNodes(classAlias, doc, stack, commands);
+ stack.pop();
+ } else if("ctag-pool".equals(classAlias)) {
+ String keystring = "ctag-pool.target-pe:assign:value:"+UUID.randomUUID()+"&ctag-pool.availability-zone-name:assign:value:"+UUID.randomUUID();
+ stack.push(keystring);
+ String[] array = stack.toArray(new String[0]);
+ String key = StringUtils.join(array, "&");
+
+ String query = String.format("query|%s|%s", classAlias, key);
+ commands.add(query);
+ listSubNodes(classAlias, doc, stack, commands);
+ stack.pop();
+ } else {
+ String keystring = String.format("%s.%s:assign:value:%s", classAlias, id, UUID.randomUUID());
+ stack.push(keystring);
+ String[] array = stack.toArray(new String[0]);
+ String key = StringUtils.join(array, "&");
+
+ String save = String.format("save|%s|%s", classAlias, key);
+ commands.add(save);
+
+ String query = String.format("query|%s|%s", classAlias, key);
+ commands.add(query);
+
+ String update = String.format("update|%s|%s", classAlias, key);
+ commands.add(update);
+
+ if(!parent.equals(classAlias) && !containsCircular(classAlias, id, stack)) {
+ listSubNodes(classAlias, doc, stack, commands);
+ }
+ String delete = String.format("delete|%s|%s", classAlias, key);
+ commands.add(delete);
+ stack.pop();
+ }
+ }
+ }
+ }
+ }
+ }
+
+ public static boolean containsCircular(String classAlias, String id, Stack<String> stack) {
+ String keystring = String.format("%s.%s", classAlias, id);
+
+ Stack<String> localStack = new Stack<String>();
+ localStack.addAll(stack);
+
+ localStack.pop();
+
+ while(!localStack.isEmpty()) {
+ String instruction = localStack.pop();
+ if(instruction.contains(keystring)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+}
diff --git a/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/CustomQueryRequestTest.java b/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/CustomQueryRequestTest.java
new file mode 100644
index 000000000..955f5c4a1
--- /dev/null
+++ b/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/CustomQueryRequestTest.java
@@ -0,0 +1,117 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.aai;
+
+import static org.junit.Assert.assertNotNull;
+
+import java.io.UnsupportedEncodingException;
+import java.net.MalformedURLException;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+import org.onap.ccsdk.sli.adaptors.aai.data.AAIDatum;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class CustomQueryRequestTest {
+
+ private static final Logger LOG = LoggerFactory.getLogger(CustomQueryRequestTest.class);
+
+ private static AAIRequest request;
+ private static AAIService aaiService;
+
+ @BeforeClass
+ public static void setUp() throws Exception {
+ aaiService = new AAIService(AAIService.class.getResource(AAIService.AAICLIENT_PROPERTIES));
+ Map<String, String> nameValues = new HashMap<>();
+ nameValues.put("generic-vnf.vnf-id", "vnf-001");
+ request = AAIRequest.createRequest("generic-vnf", nameValues);
+ LOG.info("\nEchoRequestTest.setUp\n");
+ }
+
+ @AfterClass
+ public static void tearDown() throws Exception {
+ request = null;
+ LOG.info("----------------------- EchoRequestTest.tearDown -----------------------");
+ }
+
+ @Test
+ public void runGetRequestUrlTest() {
+ LOG.info("----------------------- Test: " + new Object(){}.getClass().getEnclosingMethod().getName() + " -----------------------");
+
+ URL url;
+ try {
+ url = request.getRequestUrl("GET", null);
+ assertNotNull(url);
+ } catch (UnsupportedEncodingException | MalformedURLException | URISyntaxException exc) {
+ LOG.error("Failed test", exc);
+ }
+
+ }
+
+ @Test
+ public void runToJSONStringTest() {
+ LOG.info("----------------------- Test: " + new Object(){}.getClass().getEnclosingMethod().getName() + " -----------------------");
+
+ try {
+ String json = request.toJSONString();
+ assertNotNull(json);
+ } catch (Exception exc) {
+ LOG.error("Failed test", exc);
+ }
+
+ }
+
+ @Test
+ public void runGetArgsListTest() {
+ LOG.info("----------------------- Test: " + new Object(){}.getClass().getEnclosingMethod().getName() + " -----------------------");
+
+ try {
+ String[] args = request.getArgsList();
+ assertNotNull(args);
+ } catch (Exception exc) {
+ LOG.error("Failed test", exc);
+ }
+
+ }
+
+ @Test
+ public void runGetModelTest() {
+ LOG.info("----------------------- Test: " + new Object(){}.getClass().getEnclosingMethod().getName() + " -----------------------");
+
+ try {
+ Class<? extends AAIDatum> clazz = request.getModelClass();
+ assertNotNull(clazz);
+ } catch (Exception exc) {
+ LOG.error("Failed test", exc);
+ }
+
+ }
+}
diff --git a/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/EchoRequestTest.java b/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/EchoRequestTest.java
new file mode 100755
index 000000000..3e0a72f3a
--- /dev/null
+++ b/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/EchoRequestTest.java
@@ -0,0 +1,136 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.aai;
+
+import static org.junit.Assert.assertNotNull;
+
+import java.io.UnsupportedEncodingException;
+import java.net.MalformedURLException;
+import java.net.URISyntaxException;
+import java.net.URL;
+
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+import org.onap.ccsdk.sli.adaptors.aai.data.AAIDatum;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicResource.QueryStatus;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class EchoRequestTest {
+
+ private static final Logger LOG = LoggerFactory.getLogger(EchoRequestTest.class);
+
+ private static EchoRequest request;
+ private static AAIService aaiService;
+
+ @BeforeClass
+ public static void setUp() throws Exception {
+ aaiService = new AAIService(
+ AAIService.class.getResource(AAIService.AAICLIENT_PROPERTIES));
+ request = new EchoRequest();
+ LOG.info("\nEchoRequestTest.setUp\n");
+ }
+
+ @AfterClass
+ public static void tearDown() throws Exception {
+ request = null;
+ LOG.info("----------------------- EchoRequestTest.tearDown -----------------------");
+ }
+
+ @Test
+ public void runGetRequestUrlTest() {
+ LOG.info("----------------------- Test: " + new Object(){}.getClass().getEnclosingMethod().getName() + " -----------------------");
+
+ URL url;
+ try {
+ url = request.getRequestUrl("GET", null);
+ assertNotNull(url);
+ } catch (UnsupportedEncodingException | MalformedURLException exc) {
+ LOG.error("Failed test", exc);
+ }
+
+ }
+
+ @Test
+ public void runToJSONStringTest() {
+ LOG.info("----------------------- Test: " + new Object(){}.getClass().getEnclosingMethod().getName() + " -----------------------");
+
+ try {
+ String json = request.toJSONString();
+ assertNotNull(json);
+ } catch (Exception exc) {
+ LOG.error("Failed test", exc);
+ }
+
+ }
+
+ @Test
+ public void runGetArgsListTest() {
+ LOG.info("----------------------- Test: " + new Object(){}.getClass().getEnclosingMethod().getName() + " -----------------------");
+
+ try {
+ String[] args = request.getArgsList();
+ assertNotNull(args);
+ } catch (Exception exc) {
+ LOG.error("Failed test", exc);
+ }
+
+ }
+
+ @Test
+ public void runGetModelTest() {
+ LOG.info("----------------------- Test: " + new Object(){}.getClass().getEnclosingMethod().getName() + " -----------------------");
+
+ try {
+ Class<? extends AAIDatum> clazz = request.getModelClass();
+ assertNotNull(clazz);
+ } catch (Exception exc) {
+ LOG.error("Failed test", exc);
+ }
+
+ }
+
+// @Test
+ public void EchoTest() {
+ LOG.info("----------------------- Test: " + new Object(){}.getClass().getEnclosingMethod().getName() + " -----------------------");
+ try
+ {
+ SvcLogicContext ctx = new SvcLogicContext();
+
+ QueryStatus resp = null;
+
+// (String resource, boolean localOnly, String select, String key, String prefix, String orderBy, SvcLogicContext ctx)
+ resp = aaiService.query("echo", false, null, "", "aaidata", null, ctx);
+ assert(resp == QueryStatus.SUCCESS);
+ }
+ catch (Throwable e)
+ {
+ LOG.error("Caught exception", e);
+// fail("Caught exception");
+ }
+ }
+}
diff --git a/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/GenericRequestTest.java b/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/GenericRequestTest.java
new file mode 100755
index 000000000..3ce8a6dc5
--- /dev/null
+++ b/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/GenericRequestTest.java
@@ -0,0 +1,190 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.aai;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+
+import java.io.File;
+import java.io.UnsupportedEncodingException;
+import java.net.MalformedURLException;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+import org.onap.ccsdk.sli.adaptors.aai.data.AAIDatum;
+import org.onap.aai.inventory.v21.LInterface;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class GenericRequestTest {
+
+ private static final Logger LOG = LoggerFactory.getLogger(GenericRequestTest.class);
+
+ protected static AAIClient client;
+ protected static AAIRequest request;
+
+ @BeforeClass
+ public static void setUp() throws Exception {
+ URL url = AAIService.class.getResource(AAIService.AAICLIENT_PROPERTIES);
+ client = new AAIService(url);
+ request = AAIRequest.createRequest("generic-vnf", new HashMap<String, String>());
+ LOG.info("\nTaicAAIResourceTest.setUp\n");
+ }
+
+ @AfterClass
+ public static void tearDown() throws Exception {
+ client = null;
+ LOG.info("----------------------- AAIResourceTest.tearDown -----------------------");
+ }
+
+ @Test
+ public void test001()
+ {
+ LOG.info("----------------------- Test: " + new Object(){}.getClass().getEnclosingMethod().getName() + " -----------------------");
+
+ try
+ {
+ Map<String, String> key = new HashMap<String, String>();
+ AAIRequest request = AAIRequest.createRequest("vserver", key);
+ key.put("vserver.vserver_id", "e8faf166-2402-4ae2-be45-067954c63aed");
+ key.put("tenant.tenant_id", "1863027683132547");
+ request.processRequestPathValues(key);
+ String uri = request.getTargetUri();
+
+ assertNotNull(uri);
+
+ }
+ catch (Exception e)
+ {
+ LOG.error("Caught exception", e);
+ fail("Caught exception");
+ }
+ }
+
+ @Test
+ public void test002() {
+ LOG.info("----------------------- Test: " + new Object(){}.getClass().getEnclosingMethod().getName() + " -----------------------");
+ try
+ {
+ URL resource = this.getClass().getResource("json/linterfaceJson.txt");
+
+ LOG.info("Resource is " + resource.getFile());
+ File requestFile = new File(resource.getFile());
+ if(!requestFile.exists()) {
+ fail("Test file does not exist");
+ }
+
+ ObjectMapper mapper = AAIService.getObjectMapper();
+ LInterface request = mapper.readValue(requestFile, LInterface.class);
+ String vnf_id = request.getInterfaceName();
+ LOG.info(vnf_id);
+
+ }
+ catch (Exception e)
+ {
+ LOG.error("Caught exception", e);
+ }
+ }
+
+// @Test
+// public void test003() {
+// LOG.info("----------------------- Test: " + new Object(){}.getClass().getEnclosingMethod().getName() + " -----------------------");
+// try
+// {
+// String vnf_id = "4718302b-7884-4959-a499-f470c62418ff";
+//
+// GenericVnf genericVnf = client.requestGenericVnfData(vnf_id);
+//
+// client.deleteGenericVnfData(vnf_id, genericVnf.getResourceVersion());
+//
+// }
+// catch (Throwable e)
+// {
+// LOG.error("Caught exception", e);
+// }
+// }
+
+
+ @Test
+ public void test004() {
+ LOG.info("----------------------- Test: " + new Object(){}.getClass().getEnclosingMethod().getName() + " -----------------------");
+
+ URL url;
+ try {
+ url = request.getRequestUrl("GET", null);
+ assertNotNull(url);
+ } catch (UnsupportedEncodingException | MalformedURLException | URISyntaxException exc) {
+ LOG.error("Failed test", exc);
+ }
+
+ }
+
+ @Test
+ public void runToJSONStringTest() {
+ LOG.info("----------------------- Test: " + new Object(){}.getClass().getEnclosingMethod().getName() + " -----------------------");
+
+ try {
+ String json = request.toJSONString();
+ assertNotNull(json);
+ } catch (Exception exc) {
+ LOG.error("Failed test", exc);
+ }
+
+ }
+
+ @Test
+ public void runGetArgsListTest() {
+ LOG.info("----------------------- Test: " + new Object(){}.getClass().getEnclosingMethod().getName() + " -----------------------");
+
+ try {
+ String[] args = request.getArgsList();
+ assertNotNull(args);
+ } catch (Exception exc) {
+ LOG.error("Failed test", exc);
+ }
+
+ }
+
+ @Test
+ public void runGetModelTest() {
+ LOG.info("----------------------- Test: " + new Object(){}.getClass().getEnclosingMethod().getName() + " -----------------------");
+
+ try {
+ Class<? extends AAIDatum> clazz = request.getModelClass();
+ assertNotNull(clazz);
+ } catch (Exception exc) {
+ LOG.error("Failed test", exc);
+ }
+
+ }
+}
diff --git a/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/GenericVnfRequestTest.java b/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/GenericVnfRequestTest.java
new file mode 100644
index 000000000..062e02d1f
--- /dev/null
+++ b/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/GenericVnfRequestTest.java
@@ -0,0 +1,117 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.aai;
+
+import static org.junit.Assert.assertNotNull;
+
+import java.io.UnsupportedEncodingException;
+import java.net.MalformedURLException;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+import org.onap.ccsdk.sli.adaptors.aai.data.AAIDatum;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class GenericVnfRequestTest {
+
+ private static final Logger LOG = LoggerFactory.getLogger(GenericVnfRequestTest.class);
+
+ private static AAIRequest request;
+ private static AAIService aaiService;
+
+ @BeforeClass
+ public static void setUp() throws Exception {
+ aaiService = new AAIService(AAIService.class.getResource(AAIService.AAICLIENT_PROPERTIES));
+ Map<String, String> nameValues = new HashMap<>();
+ nameValues.put("generic-vnf.vnf-id", "vnf-001");
+ request = AAIRequest.createRequest("generic-vnf", nameValues);
+ LOG.info("\nEchoRequestTest.setUp\n");
+ }
+
+ @AfterClass
+ public static void tearDown() throws Exception {
+ request = null;
+ LOG.info("----------------------- EchoRequestTest.tearDown -----------------------");
+ }
+
+ @Test
+ public void runGetRequestUrlTest() {
+ LOG.info("----------------------- Test: " + new Object(){}.getClass().getEnclosingMethod().getName() + " -----------------------");
+
+ URL url;
+ try {
+ url = request.getRequestUrl("GET", null);
+ assertNotNull(url);
+ } catch (UnsupportedEncodingException | MalformedURLException | URISyntaxException exc) {
+ LOG.error("Failed test", exc);
+ }
+
+ }
+
+ @Test
+ public void runToJSONStringTest() {
+ LOG.info("----------------------- Test: " + new Object(){}.getClass().getEnclosingMethod().getName() + " -----------------------");
+
+ try {
+ String json = request.toJSONString();
+ assertNotNull(json);
+ } catch (Exception exc) {
+ LOG.error("Failed test", exc);
+ }
+
+ }
+
+ @Test
+ public void runGetArgsListTest() {
+ LOG.info("----------------------- Test: " + new Object(){}.getClass().getEnclosingMethod().getName() + " -----------------------");
+
+ try {
+ String[] args = request.getArgsList();
+ assertNotNull(args);
+ } catch (Exception exc) {
+ LOG.error("Failed test", exc);
+ }
+
+ }
+
+ @Test
+ public void runGetModelTest() {
+ LOG.info("----------------------- Test: " + new Object(){}.getClass().getEnclosingMethod().getName() + " -----------------------");
+
+ try {
+ Class<? extends AAIDatum> clazz = request.getModelClass();
+ assertNotNull(clazz);
+ } catch (Exception exc) {
+ LOG.error("Failed test", exc);
+ }
+
+ }
+}
diff --git a/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/GenericVnfTest.java b/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/GenericVnfTest.java
new file mode 100755
index 000000000..5a594298f
--- /dev/null
+++ b/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/GenericVnfTest.java
@@ -0,0 +1,243 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 - 2018 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.aai;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+import java.nio.charset.StandardCharsets;
+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 java.util.Properties;
+import java.util.UUID;
+
+import org.apache.commons.lang.StringUtils;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+import org.onap.ccsdk.sli.adaptors.aai.AAIClient;
+import org.onap.ccsdk.sli.adaptors.aai.AAIRequest;
+import org.onap.ccsdk.sli.adaptors.aai.AAIService;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicResource.QueryStatus;
+import org.onap.aai.inventory.v21.GenericVnf;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class GenericVnfTest {
+
+ private static final Logger LOG = LoggerFactory.getLogger(GenericVnfTest.class);
+
+ protected static AAIClient client;
+
+ @BeforeClass
+ public static void setUp() throws Exception {
+ Properties properties = new Properties();
+ properties.setProperty("org.onap.ccsdk.sli.adaptors.aai.host.certificate.ignore", "true");
+ properties.setProperty("org.onap.ccsdk.sli.adaptors.aai.client.name", "SDNC");
+ properties.setProperty("org.onap.ccsdk.sli.adaptors.aai.client.psswd", "SDNC");
+ properties.setProperty("org.onap.ccsdk.sli.adaptors.aai.application", "CCSDK");
+ properties.setProperty("org.onap.ccsdk.sli.adaptors.aai.uri", "http://localhost:8181");
+ properties.setProperty("connection.timeout", "60000");
+ properties.setProperty("read.timeout", "60000");
+ client = new AAIService(properties);
+ ((AAIService)client).setExecutor(new TestExecutor());
+ LOG.info("\nTaicAAIResourceTest.setUp\n");
+ }
+
+ @AfterClass
+ public static void tearDown() throws Exception {
+ client = null;
+ LOG.info("----------------------- GenericVnfTest.tearDown -----------------------");
+ }
+
+
+ @Test
+ public void test01SaveGenericVnf() {
+ LOG.info("----------------------- Test: " + new Object(){}.getClass().getEnclosingMethod().getName() + " -----------------------");
+ try
+ {
+ SvcLogicContext ctx = new SvcLogicContext();
+
+ String uuid = UUID.randomUUID().toString();
+ Map<String, String> data = new HashMap<String, String>();
+ data.put("vnf-id", uuid);
+ data.put("vnf-name" , "Demo-vmtn5scpx01");
+ data.put("vnf-type", "asc_heat-int");
+ data.put("service-id", "SDN-MOBILITY");
+ data.put("equipment-role", "vSCP");
+ data.put("orchestration-status", "active");
+ data.put("heat-stack-id", "Devmtn5scpx04/" + data.get("vnf-id"));
+ data.put("in-maint", "false");
+ data.put("is-closed-loop-disabled", "false");
+ data.put("encrypted-access-flag","true");
+
+ QueryStatus resp = client.save("generic-vnf", false, false, "generic-vnf.vnf-id = '"+uuid+"'", data, "aaidata", ctx);
+ assertNotNull(ctx);
+
+ }
+ catch (Throwable e)
+ {
+
+ }
+ ;
+ }
+
+ @Test
+ public void test02QueryGenericVnf()
+ {
+ LOG.info("----------------------- Test: " + new Object(){}.getClass().getEnclosingMethod().getName() + " -----------------------");
+
+ try
+ {
+ List<String> keys = new ArrayList<String>();
+ keys.add("vnf-id = 'ec14a84d-7b43-45ad-bb04-c12b74083648'");
+ keys.add("depth = 'all'");
+
+ SvcLogicContext ctx = new SvcLogicContext();
+ QueryStatus response = client.query("generic-vnf", false, null, StringUtils.join(keys, " AND "), "aaiTest", null, ctx);
+
+ assertTrue(response == QueryStatus.SUCCESS);
+ LOG.info("AAIResponse: " + response.toString());
+ }
+ catch (Exception e) {
+ LOG.error("Caught exception", e);
+ fail("Caught exception");
+ }
+ }
+
+ @Test
+ public void test03UpdateGenericVnf() {
+ LOG.info("----------------------- Test: " + new Object(){}.getClass().getEnclosingMethod().getName() + " -----------------------");
+ try
+ {
+ SvcLogicContext ctx = new SvcLogicContext();
+
+ String uuid = UUID.randomUUID().toString();
+ Map<String, String> data = new HashMap<String, String>();
+ data.put("service-id", "SDN-MOBILITY");
+ data.put("equipment-role", "vSCP");
+ data.put("orchestration-status", "active");
+ data.put("heat-stack-id", "Devmtn5scpx04/" + data.get("vnf-id"));
+ data.put("in-maint", "false");
+ data.put("is-closed-loop-disabled", "false");
+ data.put("encrypted-access-flag","true");
+
+ QueryStatus resp = client.update("generic-vnf", "generic-vnf.vnf-id = '"+uuid+"'", data, "aaidata", ctx);
+ assertNotNull(uuid);
+ }
+ catch (Throwable e)
+ {
+
+ }
+ }
+
+ @Test
+ public void test04DeleteGenericVnf()
+ {
+ LOG.info("----------------------- Test: " + new Object(){}.getClass().getEnclosingMethod().getName() + " -----------------------");
+
+ try
+ {
+ SvcLogicContext ctx = new SvcLogicContext();
+
+ List<String> keys = new ArrayList<String>();
+ keys.add("generic-vnf.vnf-id = 'VNF-S7'");
+
+ QueryStatus response = client.delete("generic-vnf", StringUtils.join(keys, " AND "), ctx);
+
+ assertTrue(response == QueryStatus.SUCCESS);
+ LOG.info("AAIResponse: " + response.toString());
+ }
+ catch (Exception e)
+ {
+ LOG.error("Caught exception", e);
+ fail("Caught exception");
+ }
+ }
+
+ @Test
+ public void test05GetResource()
+ {
+ LOG.info("----------------------- Test: " + new Object(){}.getClass().getEnclosingMethod().getName() + " -----------------------");
+
+ try
+ {
+ SvcLogicContext ctx = new SvcLogicContext();
+ GenericVnf response = ((AAIService)client).getResource("/network/generic-vnfs/generic-vnf/ec14a84d-7b43-45ad-bb04-c12b74083648", GenericVnf.class);
+
+ assertNotNull(response);
+ }
+ catch (Exception e)
+ {
+
+ }
+ }
+
+ static class TestExecutor implements AAIExecutorInterface {
+ private String data = "{\"vnf-id\":\"7324200933\",\"vnf-name\":\"vnfinst1m001\",\"vnf-type\":\"TestVnf\",\"service-id\":\"9a77d5a-123e-4ca2-9eb9-0b015d2ee0fb\",\"equipment-role\":\"vTEST\",\"orchestration-status\":\"active\",\"in-maint\":false,\"is-closed-loop-disabled\":false,\"resource-version\":\"1520720941585\"}";
+
+ @Override
+ public String get(AAIRequest request) throws AAIServiceException {
+ return data;
+ }
+
+ @Override
+ public String post(AAIRequest request) throws AAIServiceException {
+ return "success";
+ }
+
+ @Override
+ public Boolean delete(AAIRequest request, String resourceVersion) throws AAIServiceException {
+ return Boolean.TRUE;
+ }
+
+ @Override
+ public Object query(AAIRequest request, Class clas) throws AAIServiceException {
+ ObjectMapper mapper = AAIService.getObjectMapper();
+ try {
+ return mapper.readValue(data, GenericVnf.class);
+ } catch (IOException e) {
+ return new GenericVnf();
+ }
+ }
+
+ @Override
+ public Boolean patch(AAIRequest request, String resourceVersion) throws AAIServiceException {
+ return Boolean.TRUE;
+ }
+
+ }
+}
diff --git a/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/NodesQueryRequestTest.java b/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/NodesQueryRequestTest.java
new file mode 100644
index 000000000..e52f1de04
--- /dev/null
+++ b/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/NodesQueryRequestTest.java
@@ -0,0 +1,88 @@
+package org.onap.ccsdk.sli.adaptors.aai;
+
+import static org.junit.Assert.assertNotNull;
+
+import java.net.URL;
+import java.util.Properties;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.onap.ccsdk.sli.adaptors.aai.data.AAIDatum;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class NodesQueryRequestTest {
+
+ private static final Logger LOG = LoggerFactory.getLogger(NodesQueryRequestTest.class);
+
+ private static NodesQueryRequest request;
+
+ @BeforeClass
+ public static void setUp() throws Exception {
+ Properties properties = new Properties();
+ properties.setProperty("org.onap.ccsdk.sli.adaptors.aai.host.certificate.ignore", "true");
+ properties.setProperty("org.onap.ccsdk.sli.adaptors.aai.client.name", "SDNC");
+ properties.setProperty("org.onap.ccsdk.sli.adaptors.aai.client.psswd", "SDNC");
+ properties.setProperty("org.onap.ccsdk.sli.adaptors.aai.application", "CCSDK");
+ properties.setProperty("org.onap.ccsdk.sli.adaptors.aai.uri", "http://localhost:8181");
+ properties.setProperty("connection.timeout", "60000");
+ properties.setProperty("read.timeout", "60000");
+ properties.setProperty("org.onap.ccsdk.sli.adaptors.aai.query.nodes","/aai/v11/search/nodes-query?search-node-type={node-type}&filter={entity-identifier}:EQUALS:{entity-name}");
+
+ AAIRequest.configProperties = properties;
+ request = new NodesQueryRequest();
+ LOG.info("\nEchoRequestTest.setUp\n");
+ }
+
+ @Test
+ public void runGetRequestUrlTest() {
+ LOG.info("----------------------- Test: " + new Object(){}.getClass().getEnclosingMethod().getName() + " -----------------------");
+
+ try {
+ URL url = request.getRequestUrl("GET", null);
+ assertNotNull(url);
+ } catch (Exception exc) {
+ }
+ assert(true);
+
+ }
+
+ @Test
+ public void runToJSONStringTest() {
+ LOG.info("----------------------- Test: " + new Object(){}.getClass().getEnclosingMethod().getName() + " -----------------------");
+
+ try {
+ String json = request.toJSONString();
+ assertNotNull(json);
+ } catch (Exception exc) {
+ LOG.error("Failed test", exc);
+ }
+
+ }
+
+ @Test
+ public void runGetArgsListTest() {
+ LOG.info("----------------------- Test: " + new Object(){}.getClass().getEnclosingMethod().getName() + " -----------------------");
+
+ try {
+ String[] args = request.getArgsList();
+ assertNotNull(args);
+ } catch (Exception exc) {
+ LOG.error("Failed test", exc);
+ }
+
+ }
+
+ @Test
+ public void runGetModelTest() {
+ LOG.info("----------------------- Test: " + new Object(){}.getClass().getEnclosingMethod().getName() + " -----------------------");
+
+ try {
+ Class<? extends AAIDatum> clazz = request.getModelClass();
+ assertNotNull(clazz);
+ } catch (Exception exc) {
+ LOG.error("Failed test", exc);
+ }
+
+ }
+}
diff --git a/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/PathCreationTest.java b/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/PathCreationTest.java
new file mode 100755
index 000000000..098414fd9
--- /dev/null
+++ b/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/PathCreationTest.java
@@ -0,0 +1,204 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 - 2018 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.aai;
+
+import static org.junit.Assert.fail;
+import static org.junit.Assert.assertNotNull;
+
+import java.io.File;
+import java.io.FileReader;
+import java.net.URL;
+import java.util.Arrays;
+import java.util.BitSet;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.ListIterator;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.TreeSet;
+
+import org.apache.commons.lang3.StringUtils;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+import org.onap.ccsdk.sli.adaptors.aai.AAIRequest;
+import org.onap.ccsdk.sli.adaptors.aai.AAIService;
+import org.onap.ccsdk.sli.adaptors.aai.AAIServiceUtils;
+import org.onap.ccsdk.sli.adaptors.aai.EchoRequest;
+import org.onap.ccsdk.sli.adaptors.aai.data.AAIDatum;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class PathCreationTest {
+
+ private static final Logger LOG = LoggerFactory.getLogger(PathCreationTest.class);
+
+ private static AAIService aaiService;
+
+ @BeforeClass
+ public static void setUp() throws Exception {
+ aaiService = new AAIService(
+ AAIService.class.getResource(AAIService.AAICLIENT_PROPERTIES));
+ LOG.info("\nTaicAAIResourceTest.setUp\n");
+ }
+
+ @AfterClass
+ public static void tearDown() throws Exception {
+ LOG.info("----------------------- AAIResourceTest.tearDown -----------------------");
+ }
+
+ static Set<String> resourceNames = new TreeSet<String>();
+ static Map<String, String> tagValues = new LinkedHashMap<String, String>();
+
+
+ @Test
+ public void test01()
+ {
+ LOG.info("----------------------- Test: " + new Object(){}.getClass().getEnclosingMethod().getName() + " -----------------------");
+
+ try
+ {
+ File file = new File(this.getClass().getResource("/aai-path.properties").getFile());
+ if(!file.exists()) {
+ fail("File does not exist");
+ return;
+ }
+ FileReader reader = new FileReader(file);
+
+ Properties properties = new Properties();
+ properties.load(reader);
+ LOG.info("loaded " + properties.size());
+
+ Set<String> keys = properties.stringPropertyNames();
+
+ int index = 0;
+
+ for(String key : keys) {
+ String[] tags = key.split("\\|");
+ for(String tag : tags) {
+ if(!resourceNames.contains(tag)) {
+ resourceNames.add(tag);
+ tagValues.put(tag, Integer.toString(++index));
+ }
+ }
+ BitSet bs = new BitSet(256);
+ for(String tag : tags) {
+ String value = tagValues.get(tag);
+ Integer bitIndex = Integer.parseInt(value) ;
+ bs.set(bitIndex);
+ }
+ String path = properties.getProperty(key);
+ LOG.info(String.format("bitset %s\t\t%s", bs.toString(), path));
+ }
+ }
+ catch (Exception e)
+ {
+ LOG.error("Caught exception", e);
+ fail("Caught exception");
+ }
+ }
+
+ @Test
+ public void test02() {
+ try {
+ Map<String, String> nameValues = new HashMap<String, String> ();
+ nameValues.put("pserver.hostname", "USAUTOUFTIL0205UJZZ01");
+
+ AAIRequest request = AAIRequest.createRequest("pserver", nameValues);
+ request.addRequestProperty("pserver.hostname", "USAUTOUFTIL0205UJZZ01");
+
+ URL url = request.getRequestUrl("GET", null);
+ url.getPath();
+ LOG.info("Received response");
+ assertNotNull(nameValues);
+
+ } catch(Exception exc) {
+ LOG.info("Caught exception", exc);
+ }
+ }
+
+ @Test
+ public void test03() {
+ HashMap<String, String> nameValues = new HashMap<String, String>();
+
+ String path =
+// "/aai/v11/network/site-pair-sets/site-pair-set/a3839637-575e-49b3-abb7-a003b0d4cc35/routing-instances/routing-instance/7f08a85e-716f-4bc2-a4f4-70801b07a5e6";
+ "/aai/v10/cloud-infrastructure/cloud-regions/cloud-region/att-aic/AAIAIC25";
+
+ String[] split = path.split("/");
+
+ LinkedList<String> list = new LinkedList<String>( Arrays.asList(split));
+ ListIterator<String> it = list.listIterator();
+
+// for(String tag : split) {
+ while(it.hasNext()) {
+ String tag = it.next();
+ if(!tag.isEmpty()) {
+ if(resourceNames.contains(tag)){
+ LOG.info(tag);
+ // get the class from tag
+ Class<? extends AAIDatum> clazz = null;
+ try {
+ clazz = AAIRequest.getClassFromResource(tag);
+ String fieldName = AAIServiceUtils.getPrimaryIdFromClass(clazz);
+ int nextIndex = it.nextIndex();
+
+ String value = list.get(nextIndex);
+ if(!StringUtils.isEmpty(value)){
+ nameValues.put(String.format("%s.%s", tag, fieldName), value);
+ switch(tag) {
+ case "cloud-region":
+ case "entitlement":
+ case "license":
+ case "route-target":
+ case "service-capability":
+ case "ctag-pool":
+ String secondaryFieldName = AAIServiceUtils.getSecondaryIdFromClass(clazz);
+ if(secondaryFieldName != null) {
+ value = it.next();
+ nameValues.put(String.format("%s.%s", tag, secondaryFieldName), value);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ } catch (Exception exc) {
+ LOG.info("Caught exception", exc);
+ }
+ // get id from class
+ // read the follwoing field
+ // create relationship data
+ }
+ }
+ }
+ LOG.info(nameValues.toString());
+ assertNotNull(nameValues);
+ }
+}
diff --git a/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/RegressionTest.java b/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/RegressionTest.java
new file mode 100755
index 000000000..eb8dbc4a8
--- /dev/null
+++ b/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/RegressionTest.java
@@ -0,0 +1,422 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.aai;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import org.apache.commons.lang.StringUtils;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+import org.onap.ccsdk.sli.adaptors.aai.data.AAIDatum;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicResource.QueryStatus;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class RegressionTest {
+
+ static {
+ System.setProperty(org.slf4j.impl.SimpleLogger.DEFAULT_LOG_LEVEL_KEY, "INFO");
+// System.setProperty(org.slf4j.impl.SimpleLogger.LOG_FILE_KEY, String.format("RegressionTest-%d.txt", System.currentTimeMillis()));
+ }
+
+ private static final Logger LOG = LoggerFactory.getLogger(RegressionTest.class);
+
+ protected static AAIService client;
+
+ @BeforeClass
+ public static void setUp() throws Exception {
+// super.setUp();
+ URL url = AAIService.class.getResource(AAIService.AAICLIENT_PROPERTIES);
+ client = new AAIService(url);
+ LOG.info("\nTaicAAIResourceTest.setUp\n");
+ }
+
+ @AfterClass
+ public static void tearDown() throws Exception {
+// super.tearDown();
+ client = null;
+ LOG.info("----------------------- AAIResourceTest.tearDown -----------------------");
+ }
+
+// @Test
+// public void R1510Test05GenericVnfDataRequestDelete() {
+// LOG.info("----------------------- Test: " + new Object(){}.getClass().getEnclosingMethod().getName() + " -----------------------");
+// try
+// {
+// String vnf_id = "bpsx0001v-7071";
+// boolean response = client.deleteGenericVnfData(vnf_id, null);
+// assertTrue(response);
+//
+// }
+// catch (Throwable e)
+// {
+// assert(true);
+// }
+// }
+
+ @Test
+ public void R1604TestWanConnectorSave01Request()
+ {
+ LOG.info("----------------------- Test: " + new Object(){}.getClass().getEnclosingMethod().getName() + " -----------------------");
+
+ try
+ {
+ SvcLogicContext ctx = new SvcLogicContext();
+
+ Map<String, String> data = new HashMap<String, String>();
+ data.put("resource-instance-id", "12345");
+ data.put("resource-model-uuid", "45678");
+
+ data.put("relationship-list.relationship[0].related-to", "service-instance");
+
+ data.put("relationship-list.relationship[0].relationship-data[0].relationship-key", "customer.global-customer-id");
+ data.put("relationship-list.relationship[0].relationship-data[0].relationship-value", "$global-customer-id");
+
+ data.put("relationship-list.relationship[0].relationship-data[1].relationship-key", "service-subscription.service-type");
+ data.put("relationship-list.relationship[0].relationship-data[1].relationship-value", "$service-type");
+
+ data.put("relationship-list.relationship[0].relationship-data[2].relationship-key", "service-instance.service-instance-id");
+ data.put("relationship-list.relationship[0].relationship-data[2].relationship-value", "$serviceInstanceID");
+
+
+
+ //(String resource, boolean force, boolean localOnly, String key, Map<String, String> parms, String prefix, SvcLogicContext ctx)
+ QueryStatus resp = client.save("connector", false, false, "resource-instance-id = '12345'", data, "aaidata", ctx);
+
+ LOG.info("AAIResponse: " + resp.toString());
+ assertNotNull(ctx);
+ }
+ catch (Exception e)
+ {
+ assert(true);
+ }
+ }
+
+
+ @Test
+ public void R1604TestWanConnectorSave02Request()
+ {
+ LOG.info("----------------------- Test: " + new Object(){}.getClass().getEnclosingMethod().getName() + " -----------------------");
+
+ try
+ {
+ SvcLogicContext ctx = new SvcLogicContext();
+
+ Map<String, String> data = new HashMap<String, String>();
+ data.put("resource-instance-id", "11012345");
+ data.put("widget-model-id", "45678");
+ data.put("persona-model-version", "0.1");
+ data.put("persona-model-id", "dc700a83-c507-47d9-b775-1fdfcdd5f9eb");
+ data.put("relationship-list.relationship[0].relationship-data[0].relationship-key", "customer.global-customer-id");
+ data.put("metadata.metadatum[0].meta-value", "100640");
+ data.put("metadata.metadatum[0].meta-key", "vni");
+ data.put("relationship-list.relationship[0].relationship-data[1].relationship-value", "ATT-COLLABORATE");
+ data.put("relationship-list.relationship[0].relationship-data[0].relationship-value", "ds828e091614l");
+ data.put("relationship-list.relationship[0].relationship-data[2].relationship-key", "service-instance.service-instance-id");
+ data.put("relationship-list.relationship[0].relationship-data[1].relationship-key", "service-subscription.service-type");
+ data.put("relationship-list.relationship[0].related-to", "service-instance");
+ data.put("relationship-list.relationship[0].relationship-data[2].relationship-value", "1990e84d-546d-4b61-8069-e0db1318ade2");
+
+
+ //(String resource, boolean force, boolean localOnly, String key, Map<String, String> parms, String prefix, SvcLogicContext ctx)
+ QueryStatus resp = client.save("connector", false, false, "resource-instance-id = '11012345'", data, "aaidata", ctx);
+
+ LOG.info("AAIResponse: " + resp.toString());
+ assertNotNull(ctx);
+ }
+ catch (Exception e)
+ {
+ assert(true);
+ }
+ }
+
+
+ @Test
+ public void R1604TestLogicalLinkSaveRequest()
+ {
+ LOG.info("----------------------- Test: " + new Object(){}.getClass().getEnclosingMethod().getName() + " -----------------------");
+
+ try
+ {
+ SvcLogicContext ctx = new SvcLogicContext();
+
+ Map<String, String> data = new HashMap<String, String>();
+ data.put("link-name" , "1252541");
+ data.put("link-type" , "L2 Bridge between IPE and BorderElement");
+ data.put("speed-value" , "1000");
+
+ data.put("speed-units" , "MBPS");
+ data.put("ip-version" , "IP-V6");
+ data.put("routing-protocol" , "BGP");
+ data.put("resource-version" , "1.0.0");
+ data.put("resource-model-uuid" , "TEST01");
+
+ data.put("relationship-list.relationship[0].related-to" , "virtual-data-center");
+ data.put("relationship-list.relationship[0].relationship-data[0].relationship-key", "virtual-data-center.vdc-id");
+ data.put("relationship-list.relationship[0].relationship-data[0].relationship-value", "dpa2_cci_att_com-1068");
+
+ data.put("relationship-list.relationship[1].related-to" , "generic-vnf");
+ data.put("relationship-list.relationship[1].relationship-data[0].relationship-key", "generic-vnf.vnf-id");
+ data.put("relationship-list.relationship[1].relationship-data[0].relationship-value" , "basx0001v-1189");
+
+ data.put("relationship-list.relationship[2].related-to" , "l-interface");
+ data.put("relationship-list.relationship[2].relationship-data[0].relationship-key", "pserver.hostname");
+ data.put("relationship-list.relationship[2].relationship-data[0].relationship-value" , "ptpbe101snd");
+
+ data.put("relationship-list.relationship[2].relationship-data[1].relationship-key", "lag-interface.interface-name");
+ data.put("relationship-list.relationship[2].relationship-data[1].relationship-value" , "$name");
+
+ data.put("relationship-list.relationship[2].relationship-data[2].relationship-key", "l-interface.interface-name");
+ data.put("relationship-list.relationship[2].relationship-data[2].relationship-value" , "$hostname");
+
+
+
+ //(String resource, boolean force, boolean localOnly, String key, Map<String, String> parms, String prefix, SvcLogicContext ctx)
+ QueryStatus resp = client.save("logical-link", false, false, "link-name = '1252541'", data, "aaidata", ctx);
+
+ LOG.info("AAIResponse: " + resp.toString());
+ assertNotNull(data);
+ }
+ catch (Exception e)
+ {
+ assert(true);
+ }
+ }
+
+ @Test
+ public void R1604TestVDCISaveRequest()
+ {
+ LOG.info("----------------------- Test: " + new Object(){}.getClass().getEnclosingMethod().getName() + " -----------------------");
+
+ try
+ {
+ SvcLogicContext ctx = new SvcLogicContext();
+
+ Map<String, String> data = new HashMap<String, String>();
+ data.put("vdc-id" , "1252541");
+ data.put("vdc-name" , "put.the.variable.of.your.data.here");
+
+ data.put("relationship-list.relationship[0].related-to" , "connector");
+
+ data.put("relationship-list.relationship[0].relationship-data[0].relationship-key" , "connector.resource-instance-id");
+ data.put("relationship-list.relationship[0].relationship-data[0].relationship-value" , "$resource-instance-id");
+
+
+
+ //(String resource, boolean force, boolean localOnly, String key, Map<String, String> parms, String prefix, SvcLogicContext ctx)
+ QueryStatus resp = client.save("virtual-data-center", false, false, "vdc-id = '1252541'", data, "aaidata", ctx);
+
+ LOG.info("AAIResponse: " + resp.toString());
+ assertNotNull(data);
+ }
+ catch (Exception e)
+ {
+ assert(true);
+ }
+ }
+
+// @Test
+ public void R1510Test03RequestGenericVnfDataRequest()
+ {
+ LOG.info("----------------------- Test: " + new Object(){}.getClass().getEnclosingMethod().getName() + " -----------------------");
+
+ try
+ {
+ SvcLogicContext ctx = new SvcLogicContext();
+
+ QueryStatus response = client.query("generic-vnf:relationship-list", false, null, "vnf-id = '34e94596-bdfa-411d-a664-16dea8583139' AND related-to = 'l3-network' ", "aaiTest", null, ctx);
+// QueryStatus response = client.delete("generic-vnf:relationship-list", "vnf-id = '34e94596-bdfa-411d-a664-16dea8583139' AND related-to = 'pserver' ", ctx);
+
+ assertTrue(response == QueryStatus.SUCCESS);
+ LOG.info("AAIResponse: " + response.toString());
+ }
+ catch (Exception e)
+ {
+ LOG.error("Caught exception", e);
+ fail("Caught exception");
+ }
+ }
+
+ @Test
+ public void R1510Test03RequestVserverDataRequest()
+ {
+ LOG.info("----------------------- Test: " + new Object(){}.getClass().getEnclosingMethod().getName() + " -----------------------");
+
+ try
+ {
+ SvcLogicContext ctx = new SvcLogicContext();
+ QueryStatus response = client.query("vserver", false, null,
+ "vserver.vserver-id = 'FRNKGEFF1' AND depth = 'all' AND cloud-region.cloud-owner = 'att-aic' AND tenant.tenant-id = '1710vPEPROJECTS::297135PROJECT' AND cloud-region.cloud-region-id = 'FRN1'"
+ , "aaiTest", null, ctx);
+
+ assertNotNull(response);
+ }
+ catch (Exception e)
+ {
+ LOG.error("Caught exception", e);
+ fail("Caught exception");
+ }
+ }
+
+// @Test
+ public void R1510Test03UpdateVserverDataRequest()
+ {
+ LOG.info("----------------------- Test: " + new Object(){}.getClass().getEnclosingMethod().getName() + " -----------------------");
+
+ try
+ {
+ Properties prop = new Properties();
+ String propFileName = "vserver-issue.txt";
+
+ InputStream inputStream = getClass().getClassLoader().getResourceAsStream(propFileName);
+
+ if (inputStream != null) {
+ prop.load(inputStream);
+ } else {
+ throw new FileNotFoundException("property file '" + propFileName + "' not found in the classpath");
+ }
+
+
+ SvcLogicContext ctx = new SvcLogicContext();
+
+ Map<String, String> data = new HashMap<String, String>();
+
+ Enumeration keys = prop.keys();
+ while(keys.hasMoreElements()) {
+ String key = keys.nextElement().toString();
+ String value = prop.getProperty(key);
+ data.put(key, value);
+ }
+
+ QueryStatus response = client.update("vserver", "vserver-id = '59567c27-706e-4f41-953f-b5d3a525812f' AND tenant-id = 'USITUCAB3NJ0101UJZZ01::uCPE-VMS'", data, "aaiTest", ctx);
+
+ assertTrue(response == QueryStatus.SUCCESS);
+ LOG.info("AAIResponse: " + response.toString());
+ }
+ catch (Exception e)
+ {
+ LOG.error("Caught exception", e);
+ fail("Caught exception");
+ }
+ }
+
+// @Test
+ public void R1510Test03RequestVCloudRegionDataRequest()
+ {
+ LOG.info("----------------------- Test: " + new Object(){}.getClass().getEnclosingMethod().getName() + " -----------------------");
+
+ try
+ {
+ SvcLogicContext ctx = new SvcLogicContext();
+// QueryStatus response = client.query("vserver", false, null, "tenant-id = '3220171995171220' AND vserver-id = '4b491df8-cf0e-4f08-88a2-133e82b63432'", "aaiTest", null, ctx);
+// QueryStatus response = client.query("vserver", false, null, "vserver-name = 'bpsx0001vm001bps001'", "aaiTest", null, ctx);
+ QueryStatus response = client.query("cloud-region", false, null,
+ "depth = '0' AND cloud-region.cloud-owner = 'att-aic' AND cloud-region.cloud-region-id = 'mtn6'"
+ , "aaiTest", null, ctx);
+
+ assertTrue(response == QueryStatus.SUCCESS);
+ LOG.info("AAIResponse: " + response.toString());
+ }
+ catch (Exception e)
+ {
+ LOG.error("Caught exception", e);
+ fail("Caught exception");
+ }
+ }
+
+// @Test
+ public void R1510Test03RequestVCloudRegionData1Request()
+ {
+ LOG.info("----------------------- Test: " + new Object(){}.getClass().getEnclosingMethod().getName() + " -----------------------");
+
+ try
+ {
+ List<String> data = new LinkedList<String>();
+ data.add("depth = 0");
+ data.add("cloud-region.cloud-owner = 'att-aic'");
+ data.add("cloud-region.cloud-region-id = 'mtn6'");
+
+
+ SvcLogicContext ctx = new SvcLogicContext();
+ QueryStatus response = client.query("cloud-region", false, null, StringUtils.join(data, " AND ")
+// "depth = '0' AND cloud-region.cloud-owner = 'att-aic' AND cloud-region.cloud-region-id = 'mtn6'"
+ , "aaiTest", null, ctx);
+
+ assertTrue(response == QueryStatus.SUCCESS);
+ LOG.info("AAIResponse: " + response.toString());
+ }
+ catch (Exception e)
+ {
+ LOG.error("Caught exception", e);
+ fail("Caught exception");
+ }
+ }
+
+ @Test
+ public void R1510Test03RequestVCloudRegionData2Request()
+ {
+ LOG.info("----------------------- Test: " + new Object(){}.getClass().getEnclosingMethod().getName() + " -----------------------");
+
+ try
+ {
+ Map<String, String> nameValues = new HashMap<String, String>();
+ nameValues.put("depth","0");
+ nameValues.put("cloud-region.cloud-owner", "att-aic");
+ nameValues.put("cloud-region.cloud-region-id","mtn6");
+
+ AAIRequest request = AAIRequest.createRequest("cloud-region", nameValues);
+
+ for(String key : nameValues.keySet()) {
+ request.addRequestProperty(key, nameValues.get(key).toString());
+ }
+
+ String response = client.query(request);
+ AAIDatum datum = request.jsonStringToObject(response);
+
+// assertTrue(response == QueryStatus.SUCCESS);
+ LOG.info("AAIResponse: " + datum.toString());
+ assertNotNull(nameValues);
+ }
+ catch (Exception e)
+ {
+ LOG.error("Caught exception", e);
+ }
+ }
+}
diff --git a/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/RelationshipRequestTest.java b/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/RelationshipRequestTest.java
new file mode 100644
index 000000000..858c9c599
--- /dev/null
+++ b/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/RelationshipRequestTest.java
@@ -0,0 +1,118 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.aai;
+
+import static org.junit.Assert.assertNotNull;
+
+import java.io.UnsupportedEncodingException;
+import java.net.MalformedURLException;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+import org.onap.ccsdk.sli.adaptors.aai.data.AAIDatum;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class RelationshipRequestTest {
+
+ private static final Logger LOG = LoggerFactory.getLogger(RelationshipRequestTest.class);
+
+ private static AAIRequest request;
+ private static AAIService aaiService;
+
+ @BeforeClass
+ public static void setUp() throws Exception {
+ aaiService = new AAIService(AAIService.class.getResource(AAIService.AAICLIENT_PROPERTIES));
+ Map<String, String> nameValues = new HashMap<>();
+ nameValues.put("generic-vnf.vnf-id", "vnf-001");
+ AAIRequest tmpReq = AAIRequest.createRequest("generic-vnf", nameValues);
+ request = new RelationshipRequest(tmpReq);
+ LOG.info("\nEchoRequestTest.setUp\n");
+ }
+
+ @AfterClass
+ public static void tearDown() throws Exception {
+ request = null;
+ LOG.info("----------------------- EchoRequestTest.tearDown -----------------------");
+ }
+
+ @Test
+ public void runGetRequestUrlTest() {
+ LOG.info("----------------------- Test: " + new Object(){}.getClass().getEnclosingMethod().getName() + " -----------------------");
+
+ URL url;
+ try {
+ url = request.getRequestUrl("GET", null);
+ assertNotNull(url);
+ } catch (UnsupportedEncodingException | MalformedURLException | URISyntaxException exc) {
+ LOG.error("Failed test", exc);
+ }
+
+ }
+
+ @Test
+ public void runToJSONStringTest() {
+ LOG.info("----------------------- Test: " + new Object(){}.getClass().getEnclosingMethod().getName() + " -----------------------");
+
+ try {
+ String json = request.toJSONString();
+ assertNotNull(json);
+ } catch (Exception exc) {
+ LOG.error("Failed test", exc);
+ }
+
+ }
+
+ @Test
+ public void runGetArgsListTest() {
+ LOG.info("----------------------- Test: " + new Object(){}.getClass().getEnclosingMethod().getName() + " -----------------------");
+
+ try {
+ String[] args = request.getArgsList();
+ assertNotNull(args);
+ } catch (Exception exc) {
+ LOG.error("Failed test", exc);
+ }
+
+ }
+
+ @Test
+ public void runGetModelTest() {
+ LOG.info("----------------------- Test: " + new Object(){}.getClass().getEnclosingMethod().getName() + " -----------------------");
+
+ try {
+ Class<? extends AAIDatum> clazz = request.getModelClass();
+ assertNotNull(clazz);
+ } catch (Exception exc) {
+ LOG.error("Failed test", exc);
+ }
+
+ }
+}
diff --git a/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/RequestPathTest.java b/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/RequestPathTest.java
new file mode 100755
index 000000000..5ee35c647
--- /dev/null
+++ b/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/RequestPathTest.java
@@ -0,0 +1,76 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 - 2018 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.aai;
+
+import static org.junit.Assert.assertNotNull;
+
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runners.MethodSorters;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class RequestPathTest {
+
+ private static final Logger LOG = LoggerFactory.getLogger(RequestPathTest.class);
+
+ protected static AAIClient client;
+
+ @BeforeClass
+ public static void setUp() throws Exception {
+ URL url = AAIService.class.getResource(AAIService.AAICLIENT_PROPERTIES);
+ client = new AAIService(url);
+ LOG.info("\nTaicAAIResourceTest.setUp\n");
+ }
+
+ @AfterClass
+ public static void tearDown() throws Exception {
+ client = null;
+ LOG.info("----------------------- AAIResourceTest.tearDown -----------------------");
+ }
+
+ @Test
+ public void getRequestUrl() {
+ try {
+ Map<String, String> nameValues = new HashMap<String, String> ();
+ nameValues.put("generic-vnf.vnf-id","AABBCCDDEEFFGG0123");
+
+ AAIRequest request = AAIRequest.createRequest("service-instances", nameValues);
+ request.addRequestProperty("generic-vnf.vnf-id","AABBCCDDEEFFGG0123");
+
+ URL url = request.getRequestUrl("GET", null);
+ assertNotNull(url);
+ url.getPath();
+ LOG.info("Received response");
+ } catch(Exception exc) {
+ LOG.info("Caught exception", exc);
+ }
+ }
+}
diff --git a/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/data/ErrorResponseTest.java b/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/data/ErrorResponseTest.java
new file mode 100644
index 000000000..6232ae34a
--- /dev/null
+++ b/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/data/ErrorResponseTest.java
@@ -0,0 +1,51 @@
+package org.onap.ccsdk.sli.adaptors.aai.data;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class ErrorResponseTest {
+
+ ErrorResponse _erInstance;
+ protected RequestError _requestError;
+ protected Map<String, Object> _additionalProperties;
+
+ @Before
+ public void setUp() throws Exception {
+ _erInstance = new ErrorResponse();
+ _requestError = mock(RequestError.class);
+ _additionalProperties = new HashMap<String, Object>() {{
+ put("prop1", "propvalue1");
+ put("prop2", "propvalue2");
+ }};
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ _erInstance = null;
+ _requestError = null;
+ _additionalProperties = null;
+ }
+
+ @Test
+ public void testSetRequestError() {
+ _erInstance.setRequestError(_requestError);
+ assertEquals(_erInstance.getRequestError(), _requestError);
+ }
+
+ @Test
+ public void testSetAdditionalProperty() {
+ _erInstance.setAdditionalProperty("prop1", "propvalue1");
+ _erInstance.setAdditionalProperty("prop2", "propvalue2");
+ assertEquals(_erInstance.getAdditionalProperties(), _additionalProperties);
+ }
+
+}
diff --git a/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/data/RequestErrorTest.java b/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/data/RequestErrorTest.java
new file mode 100644
index 000000000..c752c7656
--- /dev/null
+++ b/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/data/RequestErrorTest.java
@@ -0,0 +1,51 @@
+package org.onap.ccsdk.sli.adaptors.aai.data;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class RequestErrorTest {
+
+ RequestError _reInstance;
+ protected ServiceException _serviceException;
+ protected Map<String, Object> _additionalProperties;
+
+ @Before
+ public void setUp() throws Exception {
+ _reInstance = new RequestError();
+ _serviceException = mock(ServiceException.class);
+ _additionalProperties = new HashMap<String, Object>() {{
+ put("prop1", "propvalue1");
+ put("prop2", "propvalue2");
+ }};
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ _reInstance = null;
+ _serviceException = null;
+ _additionalProperties = null;
+ }
+
+ @Test
+ public void testSetServiceException() {
+ _reInstance.setServiceException(_serviceException);
+ assertEquals(_reInstance.getServiceException(), _serviceException);
+ }
+
+ @Test
+ public void testSetAdditionalProperty() {
+ _reInstance.setAdditionalProperty("prop1", "propvalue1");
+ _reInstance.setAdditionalProperty("prop2", "propvalue2");
+ assertEquals(_reInstance.getAdditionalProperties(), _additionalProperties);
+ }
+
+}
diff --git a/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/data/ResponseMessageTest.java b/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/data/ResponseMessageTest.java
new file mode 100644
index 000000000..daf95b02d
--- /dev/null
+++ b/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/data/ResponseMessageTest.java
@@ -0,0 +1,68 @@
+package org.onap.ccsdk.sli.adaptors.aai.data;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class ResponseMessageTest {
+
+ ResponseMessage _rmInstance;
+ protected String _messageId;
+ protected String _text;
+ protected Variables _variables;
+ protected Map<String, Object> _additionalProperties;
+
+ @Before
+ public void setUp() throws Exception {
+ _rmInstance = new ResponseMessage();
+ _messageId = "messageId";
+ _text = "text";
+ _variables = mock(Variables.class);
+ _additionalProperties = new HashMap<String, Object>() {{
+ put("prop1", "propvalue1");
+ put("prop2", "propvalue2");
+ }};
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ _rmInstance = null;
+ _messageId = null;
+ _text = null;
+ _variables = null;
+ _additionalProperties = null;
+ }
+
+ @Test
+ public void testSetMessageId() {
+ _rmInstance.setMessageId(_messageId);
+ assertTrue(_rmInstance.getMessageId().equals(_messageId));
+ }
+
+ @Test
+ public void testSetText() {
+ _rmInstance.setText(_text);
+ assertTrue(_rmInstance.getText().equals(_text));
+ }
+
+ @Test
+ public void testSetVariables() {
+ _rmInstance.setVariables(_variables);
+ assertEquals(_rmInstance.getVariables(), _variables);
+ }
+
+ @Test
+ public void testSetAdditionalProperty() {
+ _rmInstance.setAdditionalProperty("prop1", "propvalue1");
+ _rmInstance.setAdditionalProperty("prop2", "propvalue2");
+ assertEquals(_rmInstance.getAdditionalProperties(), _additionalProperties);
+ }
+
+}
diff --git a/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/data/ResponseMessagesTest.java b/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/data/ResponseMessagesTest.java
new file mode 100644
index 000000000..f21e969dd
--- /dev/null
+++ b/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/data/ResponseMessagesTest.java
@@ -0,0 +1,55 @@
+package org.onap.ccsdk.sli.adaptors.aai.data;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class ResponseMessagesTest {
+
+ ResponseMessages _rmsInstance;
+ protected List<ResponseMessage> _responseMessage;
+ protected Map<String, Object> _additionalProperties;
+
+ @Before
+ public void setUp() throws Exception {
+ _rmsInstance = new ResponseMessages();
+ _responseMessage = new ArrayList<>();
+ ResponseMessage rm1 = mock(ResponseMessage.class);
+ ResponseMessage rm2 = mock(ResponseMessage.class);
+ _responseMessage.add(rm1);
+ _responseMessage.add(rm2);
+ _additionalProperties = new HashMap<String, Object>() {{
+ put("prop1", "propvalue1");
+ put("prop2", "propvalue2");
+ }};
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ _rmsInstance = null;
+ _responseMessage = null;
+ _additionalProperties = null;
+ }
+
+ @Test
+ public void testSetResponseMessage() {
+ _rmsInstance.setResponseMessage(_responseMessage);
+ assertEquals(_rmsInstance.getResponseMessage(), _responseMessage);
+ }
+
+ @Test
+ public void testSetAdditionalProperty() {
+ _rmsInstance.setAdditionalProperty("prop1", "propvalue1");
+ _rmsInstance.setAdditionalProperty("prop2", "propvalue2");
+ assertEquals(_rmsInstance.getAdditionalProperties(), _additionalProperties);
+ }
+
+}
diff --git a/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/data/ServiceExceptionTest.java b/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/data/ServiceExceptionTest.java
new file mode 100644
index 000000000..f44d9b366
--- /dev/null
+++ b/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/data/ServiceExceptionTest.java
@@ -0,0 +1,71 @@
+package org.onap.ccsdk.sli.adaptors.aai.data;
+
+import static org.junit.Assert.*;
+import static org.mockito.Mockito.mock;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class ServiceExceptionTest {
+
+ ServiceException _seInstance;
+ protected String _messageId;
+ protected String _text;
+ protected List<String> _variables;
+ protected Map<String, Object> _additionalProperties;
+
+ @Before
+ public void setUp() throws Exception {
+ _seInstance = new ServiceException();
+ _messageId = "messageId";
+ _text = "text";
+ _variables = new ArrayList<>(Arrays.asList("var1", "var2", "var3"));
+ _additionalProperties = new HashMap<String, Object>() {{
+ put("prop1", "propvalue1");
+ put("prop2", "propvalue2");
+ }};
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ _seInstance = null;
+ _messageId = null;
+ _text = null;
+ _variables = null;
+ _additionalProperties = null;
+ }
+
+ @Test
+ public void testSetMessageId() {
+ _seInstance.setMessageId(_messageId);
+ assertTrue(_seInstance.getMessageId().equals(_messageId));
+ }
+
+ @Test
+ public void testSetText() {
+ _seInstance.setText(_text);
+ assertTrue(_seInstance.getText().equals(_text));
+ }
+
+ @Test
+ public void testSetVariables() {
+ _seInstance.setVariables(_variables);
+ assertEquals(_seInstance.getVariables(), _variables);
+ }
+
+ @Test
+ public void testSetAdditionalProperties() {
+ _seInstance.setAdditionalProperty("prop1", "propvalue1");
+ _seInstance.setAdditionalProperty("prop2", "propvalue2");
+ assertEquals(_seInstance.getAdditionalProperties(), _additionalProperties);
+ }
+
+
+}
diff --git a/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/data/SubInterfaceTest.java b/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/data/SubInterfaceTest.java
new file mode 100644
index 000000000..7975372be
--- /dev/null
+++ b/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/data/SubInterfaceTest.java
@@ -0,0 +1,94 @@
+package org.onap.ccsdk.sli.adaptors.aai.data;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.onap.aai.inventory.v21.RelationshipList;
+import org.onap.aai.inventory.v21.Vlans;
+
+public class SubInterfaceTest {
+
+ SubInterface _siInstance;
+ protected String _interfaceName;
+ protected String _interfaceRole;
+ protected String _resourceVersion;
+ protected Vlans _vlans;
+ protected RelationshipList _relationshipList;
+ protected Map<String, Object> _additionalProperties;
+
+ @Before
+ public void setUp() throws Exception {
+ _siInstance = new SubInterface();
+ _interfaceName = "interfaceName";
+ _interfaceRole = "interfaceRole";
+ _resourceVersion = "resourceVersion";
+ _vlans = mock(Vlans.class);
+ _relationshipList = mock(RelationshipList.class);
+
+ _additionalProperties = new HashMap<String, Object>() {{
+ put("prop1", "propvalue1");
+ put("prop2", "propvalue2");
+ }};
+
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ _siInstance = null;
+ _interfaceName = null;
+ _interfaceRole = null;
+ _resourceVersion = null;
+ _vlans = null;
+ _relationshipList = null;
+ _additionalProperties = null;
+ }
+
+ @Test
+ public void testSetInterfaceName() {
+ _siInstance.setInterfaceName(_interfaceName);
+ assertTrue(_siInstance.getInterfaceName().equals(_interfaceName));
+ }
+
+
+ @Test
+ public void testSetInterfaceRole() {
+ _siInstance.setInterfaceRole(_interfaceRole);
+ assertTrue(_siInstance.getInterfaceRole().equals(_interfaceRole));
+ }
+
+
+ @Test
+ public void testSetResourceVersion() {
+ _siInstance.setResourceVersion(_resourceVersion);
+ assertTrue(_siInstance.getResourceVersion().equals(_resourceVersion));
+ }
+
+
+ @Test
+ public void testSetVlans() {
+ _siInstance.setVlans(_vlans);
+ assertTrue(_siInstance.getVlans().equals(_vlans));
+ }
+
+
+ @Test
+ public void testSetRelationshipList() {
+ _siInstance.setRelationshipList(_relationshipList);
+ assertTrue(_siInstance.getRelationshipList().equals(_relationshipList));
+ }
+
+ @Test
+ public void testSetAdditionalProperties() {
+ _siInstance.setAdditionalProperty("prop1", "propvalue1");
+ _siInstance.setAdditionalProperty("prop2", "propvalue2");
+ assertEquals(_siInstance.getAdditionalProperties(), _additionalProperties);
+ }
+
+}
diff --git a/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/data/VariablesTest.java b/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/data/VariablesTest.java
new file mode 100644
index 000000000..1f72f7e67
--- /dev/null
+++ b/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/data/VariablesTest.java
@@ -0,0 +1,56 @@
+package org.onap.ccsdk.sli.adaptors.aai.data;
+
+import static org.junit.Assert.*;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import static org.junit.Assert.*;
+import static org.mockito.Mockito.mock;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import java.util.ArrayList;
+
+public class VariablesTest {
+ Variables _variablesInstance;
+ protected List<String> _variable;
+ protected Map<String, Object> _additionalProperties;
+
+ public VariablesTest() {
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ _variablesInstance = new Variables();
+ _variable = new ArrayList<>(Arrays.asList("var1", "var2", "var3"));
+ _additionalProperties = new HashMap<String, Object>() {{
+ put("prop1", "propvalue1");
+ put("prop2", "propvalue2");
+ }};
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ _variablesInstance = null;
+ _variable = null;
+ _additionalProperties = null;
+ }
+
+
+ @Test
+ public void testSetVariable() {
+ _variablesInstance.setVariable(_variable);
+ assertEquals(_variablesInstance.getVariable(), _variable);
+ }
+
+ @Test
+ public void testSetAdditionalProperties() {
+ _variablesInstance.setAdditionalProperty("prop1", "propvalue1");
+ _variablesInstance.setAdditionalProperty("prop2", "propvalue2");
+ assertEquals(_variablesInstance.getAdditionalProperties(), _additionalProperties);
+ }
+
+}
diff --git a/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/data/notify/KeyDatumTest.java b/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/data/notify/KeyDatumTest.java
new file mode 100644
index 000000000..2ea915213
--- /dev/null
+++ b/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/data/notify/KeyDatumTest.java
@@ -0,0 +1,38 @@
+package org.onap.ccsdk.sli.adaptors.aai.data.notify;
+
+import static org.junit.Assert.*;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class KeyDatumTest {
+
+ @BeforeClass
+ public static void setUpBeforeClass() throws Exception {
+ }
+
+ @Test
+ public void testSetKeyName() {
+ String testString = "test-value";
+ KeyDatum event = new KeyDatum();
+ event.setKeyName(testString);
+ assertEquals(event.getKeyName(), testString);
+ }
+
+ @Test
+ public void testSetKeyValue() {
+ String testString = "test-value";
+ KeyDatum event = new KeyDatum();
+ event.setKeyValue(testString);
+ assertEquals(event.getKeyValue(), testString);
+ }
+
+ @Test
+ public void testSetAdditionalProperty() {
+ String testString = "test-value";
+ KeyDatum event = new KeyDatum();
+ event.setAdditionalProperty("test-key", testString);
+ assertEquals(event.getAdditionalProperties().get("test-key"), testString);
+ }
+
+}
diff --git a/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/data/notify/NotifyEventTest.java b/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/data/notify/NotifyEventTest.java
new file mode 100644
index 000000000..cb026c001
--- /dev/null
+++ b/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/data/notify/NotifyEventTest.java
@@ -0,0 +1,53 @@
+package org.onap.ccsdk.sli.adaptors.aai.data.notify;
+
+import static org.junit.Assert.*;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class NotifyEventTest {
+
+ @BeforeClass
+ public static void setUpBeforeClass() throws Exception {
+ }
+
+ @Test
+ public void test01() {
+ String testString = "test-value";
+ NotifyEvent event = new NotifyEvent();
+ event.setAdditionalProperty("test-key", testString);
+ assertEquals(event.getAdditionalProperties().get("test-key"), testString);
+ }
+
+ @Test
+ public void test02() {
+ String testString = "test-value";
+ NotifyEvent event = new NotifyEvent();
+ event.setSelflink(testString);
+ assertEquals(event.getSelflink(), testString);
+ }
+
+ @Test
+ public void test03() {
+ String testString = "test-value";
+ NotifyEvent event = new NotifyEvent();
+ event.setEventId(testString);
+ assertEquals(event.getEventId(), testString);
+ }
+
+ @Test
+ public void test04() {
+ String testString = "test-value";
+ NotifyEvent event = new NotifyEvent();
+ event.setEventTrigger(testString);
+ assertEquals(event.getEventTrigger(), testString);
+ }
+
+ @Test
+ public void test05() {
+ String testString = "test-value";
+ NotifyEvent event = new NotifyEvent();
+ event.setNodeType(testString);
+ assertEquals(event.getNodeType(), testString);
+ }
+}
diff --git a/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/query/FormattedQueryRequestDataTest.java b/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/query/FormattedQueryRequestDataTest.java
new file mode 100644
index 000000000..a89dbded6
--- /dev/null
+++ b/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/query/FormattedQueryRequestDataTest.java
@@ -0,0 +1,53 @@
+package org.onap.ccsdk.sli.adaptors.aai.query;
+
+import static org.junit.Assert.*;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.onap.ccsdk.sli.adaptors.aai.data.Variables;
+
+public class FormattedQueryRequestDataTest {
+
+ FormattedQueryRequestData _fqrdInstance;
+ protected List<String> _start;
+ protected String _query;
+
+ @Before
+ public void setUp() throws Exception {
+ _fqrdInstance = new FormattedQueryRequestData();
+ _start = new ArrayList<>(Arrays.asList("start1", "start2", "start3"));
+ _query = "query";
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ _fqrdInstance = null;
+ _start = null;
+ _query = null;
+ }
+
+ @Test
+ public void testSetStart() {
+ _fqrdInstance.setStart(_start);
+ assertEquals(_fqrdInstance.getStart(), _start);
+ }
+
+ @Test
+ public void testSetQuery() {
+ _fqrdInstance.setQuery(_query);
+ assertEquals(_fqrdInstance.getQuery(), _query);
+ }
+
+ @Test
+ public void testToString() {
+ _fqrdInstance.setStart(_start);
+ _fqrdInstance.setQuery(_query);
+ assertNotNull(_fqrdInstance.toString());
+ }
+
+}
diff --git a/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/query/FormattedQueryResultListTest.java b/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/query/FormattedQueryResultListTest.java
new file mode 100644
index 000000000..f26051917
--- /dev/null
+++ b/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/query/FormattedQueryResultListTest.java
@@ -0,0 +1,49 @@
+package org.onap.ccsdk.sli.adaptors.aai.query;
+
+import static org.junit.Assert.*;
+import static org.mockito.Mockito.mock;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import java.util.ArrayList;
+
+public class FormattedQueryResultListTest {
+ FormattedQueryResultList _fqrlInstance;
+ protected List<Result> _results;
+
+ @Before
+ public void setUp() throws Exception {
+ _fqrlInstance = new FormattedQueryResultList();
+ _results = new ArrayList<>();
+ Result r1 = mock(Result.class);
+ Result r2 = mock(Result.class);
+ _results.add(r1);
+ _results.add(r2);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ _fqrlInstance = null;
+ _results = null;
+ }
+
+
+ @Test
+ public void testSetResults() {
+ _fqrlInstance.setResults(_results);
+ assertEquals(_fqrlInstance.getResults(), _results);
+ }
+
+ @Test
+ public void testToString() {
+ _fqrlInstance.setResults(_results);
+ assertTrue(_fqrlInstance.toString() != null);
+ }
+
+}
diff --git a/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/query/InstanceFilterTest.java b/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/query/InstanceFilterTest.java
new file mode 100644
index 000000000..7a81f72cb
--- /dev/null
+++ b/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/query/InstanceFilterTest.java
@@ -0,0 +1,124 @@
+package org.onap.ccsdk.sli.adaptors.aai.query;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.onap.aai.inventory.v21.CloudRegion;
+import org.onap.aai.inventory.v21.GenericVnf;
+import org.onap.aai.inventory.v21.L3Network;
+import org.onap.aai.inventory.v21.LogicalLink;
+import org.onap.aai.inventory.v21.PInterface;
+import org.onap.aai.inventory.v21.Pnf;
+import org.onap.aai.inventory.v21.ServiceInstance;
+import org.onap.aai.inventory.v21.Tenant;
+import org.onap.aai.inventory.v21.Vnf;
+import org.onap.aai.inventory.v21.Vserver;
+
+public class InstanceFilterTest {
+
+ InstanceFilter _ifInstance;
+ protected LogicalLink _logicalLink;
+ protected Pnf _pnf;
+ protected L3Network _l3Network;
+ protected PInterface _pInterface;
+ protected GenericVnf _genericVnf;
+ protected Vserver _vserver;
+ protected Tenant _tenant;
+ protected CloudRegion _cloudRegion;
+ protected ServiceInstance _serviceInstance;
+ protected Vnf _vnfc;
+ protected Map<String, Object> _additionalProperties;
+
+ @Before
+ public void setUp() throws Exception {
+ _ifInstance = new InstanceFilter();
+ LogicalLink _logicalLink = mock(LogicalLink.class);
+ Pnf _pnf = mock(Pnf.class);
+ L3Network _l3Network = mock(L3Network.class);
+ PInterface _pInterface = mock(PInterface.class);
+ GenericVnf _genericVnf = mock(GenericVnf.class);
+ Vserver _vserver = mock(Vserver.class);
+ Tenant _tenant = mock(Tenant.class);
+ CloudRegion _cloudRegion = mock(CloudRegion.class);
+ ServiceInstance _serviceInstance = mock(ServiceInstance.class);
+ // as per class
+ Vnf _vnfc = mock(Vnf.class);
+ _additionalProperties = new HashMap<String, Object>() {{
+ put("prop1", "propvalue1");
+ put("prop2", "propvalue2");
+ }};
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ _ifInstance = null;
+ _additionalProperties = null;
+ }
+
+ @Test
+ public void testSetLogicalLink() {
+ _ifInstance.setLogicalLink(_logicalLink);
+ assertEquals(_ifInstance.getLogicalLink(), _logicalLink);
+ }
+
+ @Test
+ public void testSetPnf() {
+ _ifInstance.setPnf(_pnf);
+ assertEquals(_ifInstance.getPnf(), _pnf);
+ }
+
+ @Test
+ public void testSetL3Network() {
+ _ifInstance.setL3Network(_l3Network);
+ assertEquals(_ifInstance.getL3Network(), _l3Network);
+ }
+
+ @Test
+ public void testSetServiceInstance() {
+ _ifInstance.setServiceInstance(_serviceInstance);
+ assertEquals(_ifInstance.getServiceInstance(), _serviceInstance);
+ }
+
+ @Test
+ public void testSetGenericVnf() {
+ _ifInstance.setGenericVnf(_genericVnf);
+ assertEquals(_ifInstance.getGenericVnf(), _genericVnf);
+ }
+
+ @Test
+ public void testSetVserver() {
+ _ifInstance.setVserver(_vserver);
+ assertEquals(_ifInstance.getVserver(), _vserver);
+ }
+
+ @Test
+ public void testSetTenant() {
+ _ifInstance.setTenant(_tenant);
+ assertEquals(_ifInstance.getTenant(), _tenant);
+ }
+
+ @Test
+ public void testSetCloudRegion() {
+ _ifInstance.setCloudRegion(_cloudRegion);
+ assertEquals(_ifInstance.getCloudRegion(), _cloudRegion);
+ }
+
+ @Test
+ public void testSetVnfc() {
+ _ifInstance.setVnfc(_vnfc);
+ assertEquals(_ifInstance.getVnfc(), _vnfc);
+ }
+
+ @Test
+ public void testSetAdditionalProperty() {
+ _ifInstance.setAdditionalProperty("prop1", "propvalue1");
+ _ifInstance.setAdditionalProperty("prop2", "propvalue2");
+ assertEquals(_ifInstance.getAdditionalProperties(), _additionalProperties);
+ }
+}
diff --git a/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/query/InstanceFiltersTest.java b/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/query/InstanceFiltersTest.java
new file mode 100644
index 000000000..6131e13e0
--- /dev/null
+++ b/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/query/InstanceFiltersTest.java
@@ -0,0 +1,55 @@
+package org.onap.ccsdk.sli.adaptors.aai.query;
+
+import static org.junit.Assert.*;
+import static org.mockito.Mockito.mock;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class InstanceFiltersTest {
+
+ InstanceFilters _ifsInstance;
+ protected List<InstanceFilter> _instanceFilter;
+ protected Map<String, Object> _additionalProperties;
+
+ @Before
+ public void setUp() throws Exception {
+ _ifsInstance = new InstanceFilters();
+ _instanceFilter = new ArrayList<>();
+ InstanceFilter if1 = mock(InstanceFilter.class);
+ InstanceFilter if2 = mock(InstanceFilter.class);
+ _instanceFilter.add(if1);
+ _instanceFilter.add(if2);
+ _additionalProperties = new HashMap<String, Object>() {{
+ put("prop1", "propvalue1");
+ put("prop2", "propvalue2");
+ }};
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ _ifsInstance = null;
+ _instanceFilter = null;
+ _additionalProperties = null;
+ }
+
+ @Test
+ public void testSetInstanceFilter() {
+ _ifsInstance.setInstanceFilter(_instanceFilter);
+ assertEquals(_ifsInstance.getInstanceFilter(), _instanceFilter);
+
+ }
+
+ @Test
+ public void testSetAdditionalProperty() {
+ _ifsInstance.setAdditionalProperty("prop1", "propvalue1");
+ _ifsInstance.setAdditionalProperty("prop2", "propvalue2");
+ }
+
+}
diff --git a/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/query/ResultTest.java b/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/query/ResultTest.java
new file mode 100644
index 000000000..14c17a563
--- /dev/null
+++ b/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/query/ResultTest.java
@@ -0,0 +1,159 @@
+package org.onap.ccsdk.sli.adaptors.aai.query;
+
+import static org.junit.Assert.*;
+import static org.mockito.Mockito.mock;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import org.onap.aai.inventory.v21.CloudRegion;
+import org.onap.aai.inventory.v21.Complex;
+import org.onap.aai.inventory.v21.Configuration;
+import org.onap.aai.inventory.v21.GenericVnf;
+import org.onap.aai.inventory.v21.L3InterfaceIpv4AddressList;
+import org.onap.aai.inventory.v21.L3InterfaceIpv6AddressList;
+import org.onap.aai.inventory.v21.L3Network;
+import org.onap.aai.inventory.v21.LInterface;
+//import org.onap.aai.inventory.v21.OwningEntity;
+import org.onap.aai.inventory.v21.Pserver;
+import org.onap.aai.inventory.v21.ServiceInstance;
+import org.onap.aai.inventory.v21.Vnfc;
+import org.onap.aai.inventory.v21.Vserver;
+
+public class ResultTest {
+
+ Result _rInstance;
+
+ protected CloudRegion _cloudRegion;
+ protected Complex _complex;
+ protected Configuration _configuration;
+ protected GenericVnf _genericVnf;
+ protected L3InterfaceIpv4AddressList _l3InterfaceIpv4AddressList;
+ protected L3InterfaceIpv6AddressList _l3InterfaceIpv6AddressList;
+ protected L3Network _l3Network;
+ protected LInterface _lInterface;
+ protected Pserver _pserver;
+ protected ServiceInstance _serviceInstance;
+ protected Vnfc _vnfc;
+ protected Vserver _vserver;
+
+ protected Map<String, Object> _additionalProperties;
+
+ @Before
+ public void setUp() throws Exception {
+ _rInstance = new Result();
+
+ CloudRegion _cloudRegion = mock(CloudRegion.class);
+ Complex _complex = mock(Complex.class);
+ Configuration _configuration = mock(Configuration.class);
+ L3InterfaceIpv4AddressList _l3InterfaceIpv4AddressList = mock(L3InterfaceIpv4AddressList.class);
+ L3InterfaceIpv6AddressList _l3InterfaceIpv6AddressList = mock(L3InterfaceIpv6AddressList.class);
+ L3Network _l3Network = mock(L3Network.class);
+ LInterface _pInterface = mock(LInterface.class);
+ GenericVnf _genericVnf = mock(GenericVnf.class);
+ Vserver _vserver = mock(Vserver.class);
+ Pserver _pserver = mock(Pserver.class);
+ Vnfc _vnfc = mock(Vnfc.class);
+ ServiceInstance _serviceInstance = mock(ServiceInstance.class);
+
+ _additionalProperties = new HashMap<String, Object>() {{
+ put("prop1", "propvalue1");
+ put("prop2", "propvalue2");
+ }};
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ _rInstance = null;
+ _additionalProperties = null;
+ }
+
+ @Test
+ public void testSetComplex() {
+ _rInstance.setComplex(_complex);
+ assertEquals(_rInstance.getComplex(), _complex);
+ }
+
+ @Test
+ public void testSetConfiguration() {
+ _rInstance.setConfiguration(_configuration);
+ assertEquals(_rInstance.getConfiguration(), _configuration);
+ }
+
+ @Test
+ public void testSetL3InterfaceIpv4AddressList() {
+ _rInstance.setL3InterfaceIpv4AddressList(_l3InterfaceIpv4AddressList);
+ assertEquals(_rInstance.getL3InterfaceIpv4AddressList(), _l3InterfaceIpv4AddressList);
+ }
+
+ @Test
+ public void testSetL3InterfaceIpv6AddressList() {
+ _rInstance.setL3InterfaceIpv6AddressList(_l3InterfaceIpv6AddressList);
+ assertEquals(_rInstance.getL3InterfaceIpv6AddressList(), _l3InterfaceIpv6AddressList);
+ }
+
+ @Test
+ public void testSetL3Network() {
+ _rInstance.setL3Network(_l3Network);
+ assertEquals(_rInstance.getL3Network(), _l3Network);
+ }
+
+ @Test
+ public void testSetServiceInstance() {
+ _rInstance.setServiceInstance(_serviceInstance);
+ assertEquals(_rInstance.getServiceInstance(), _serviceInstance);
+ }
+
+ @Test
+ public void testSetGenericVnf() {
+ _rInstance.setGenericVnf(_genericVnf);
+ assertEquals(_rInstance.getGenericVnf(), _genericVnf);
+ }
+
+ @Test
+ public void testSetVserver() {
+ _rInstance.setVserver(_vserver);
+ assertEquals(_rInstance.getVserver(), _vserver);
+ }
+
+ @Test
+ public void testSetCloudRegion() {
+ _rInstance.setCloudRegion(_cloudRegion);
+ assertEquals(_rInstance.getCloudRegion(), _cloudRegion);
+ }
+
+ @Test
+ public void testSetVnfc() {
+ _rInstance.setVnfc(_vnfc);
+ assertEquals(_rInstance.getVnfc(), _vnfc);
+ }
+
+ @Test
+ public void testSetLInterface() {
+ _rInstance.setLInterface(_lInterface);
+ assertEquals(_rInstance.getLInterface(), _lInterface);
+ }
+
+ @Test
+ public void testSetPserver() {
+ _rInstance.setPserver(_pserver);
+ assertEquals(_rInstance.getPserver(), _pserver);
+ }
+
+ @Test
+ public void testSetAdditionalProperty() {
+ _rInstance.setAdditionalProperty("prop1", "propvalue1");
+ _rInstance.setAdditionalProperty("prop2", "propvalue2");
+ assertEquals(_rInstance.getAdditionalProperties(), _additionalProperties);
+ }
+
+ @Test
+ public void testToString() {
+ assertNotNull(_rInstance.toString());
+ }
+
+}
diff --git a/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/update/ActionDatumTest.java b/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/update/ActionDatumTest.java
new file mode 100644
index 000000000..7b858ea65
--- /dev/null
+++ b/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/update/ActionDatumTest.java
@@ -0,0 +1,58 @@
+package org.onap.ccsdk.sli.adaptors.aai.update;
+
+import static org.junit.Assert.*;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class ActionDatumTest {
+
+ ActionDatum _oInstance;
+ protected Map<String, Object> _additionalProperties;
+ protected String _propertyName;
+ protected String _propertyValue;
+
+ @Before
+ public void setUp() throws Exception {
+ _oInstance = new ActionDatum();
+ _propertyName = "propertyName";
+ _propertyValue = "propertyValue";
+ _additionalProperties = new HashMap<String, Object>() {{
+ put("prop1", "propvalue1");
+ put("prop2", "propvalue2");
+ }};
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ _oInstance = null;
+ _additionalProperties = null;
+ }
+
+ @Test
+ public void testSetPropertyName() {
+ _oInstance.setPropertyName(_propertyName);
+ assertEquals(_oInstance.getPropertyName(), _propertyName);
+ }
+
+ @Test
+ public void testSetPropertyValue() {
+ _oInstance.setPropertyValue(_propertyValue);
+ assertEquals(_oInstance.getPropertyValue(), _propertyValue);
+ }
+
+ @Test
+ public void testSetAdditionalProperty() {
+ _oInstance.setAdditionalProperty("prop1", "propvalue1");
+ _oInstance.setAdditionalProperty("prop2", "propvalue2");
+ assertEquals(_oInstance.getAdditionalProperties(), _additionalProperties);
+ }
+
+}
diff --git a/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/update/ActionTest.java b/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/update/ActionTest.java
new file mode 100644
index 000000000..459396c1c
--- /dev/null
+++ b/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/update/ActionTest.java
@@ -0,0 +1,64 @@
+package org.onap.ccsdk.sli.adaptors.aai.update;
+
+import static org.junit.Assert.*;
+import static org.mockito.Mockito.mock;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.onap.ccsdk.sli.adaptors.aai.query.Result;
+
+public class ActionTest {
+
+ Action _oInstance;
+ protected Map<String, Object> _additionalProperties;
+ protected String _actionType;
+ protected List<ActionDatum> _actionData;
+
+ @Before
+ public void setUp() throws Exception {
+ _oInstance = new Action();
+ _actionType = "actionType";
+ _actionData = new ArrayList<>();
+ ActionDatum a1 = mock(ActionDatum.class);
+ ActionDatum a2 = mock(ActionDatum.class);
+ _actionData.add(a1);
+ _actionData.add(a2);
+ _additionalProperties = new HashMap<String, Object>() {{
+ put("prop1", "propvalue1");
+ put("prop2", "propvalue2");
+ }};
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ _oInstance = null;
+ _actionData = null;
+ _additionalProperties = null;
+ }
+
+ @Test
+ public void testSetActionData() {
+ _oInstance.setActionData(_actionData);
+ assertEquals(_oInstance.getActionData(), _actionData);
+ }
+
+ @Test
+ public void testSetActionType() {
+ _oInstance.setActionType(_actionType);
+ assertEquals(_oInstance.getActionType(), _actionType);
+ }
+
+ @Test
+ public void testSetAdditionalProperty() {
+ _oInstance.setAdditionalProperty("prop1", "propvalue1");
+ _oInstance.setAdditionalProperty("prop2", "propvalue2");
+ assertEquals(_oInstance.getAdditionalProperties(), _additionalProperties);
+ }
+}
diff --git a/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/update/UpdateNodeKeyTest.java b/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/update/UpdateNodeKeyTest.java
new file mode 100644
index 000000000..360a0948f
--- /dev/null
+++ b/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/update/UpdateNodeKeyTest.java
@@ -0,0 +1,53 @@
+package org.onap.ccsdk.sli.adaptors.aai.update;
+
+import static org.junit.Assert.*;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class UpdateNodeKeyTest {
+ UpdateNodeKey _oInstance;
+ protected Map<String, Object> _additionalProperties;
+ protected String _keyName;
+ protected String _keyValue;
+ @Before
+ public void setUp() throws Exception {
+ _oInstance = new UpdateNodeKey();
+ _keyName = "keyName";
+ _keyValue = "keyValue";
+ _additionalProperties = new HashMap<String, Object>() {{
+ put("prop1", "propvalue1");
+ put("prop2", "propvalue2");
+ }};
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ _oInstance = null;
+ _additionalProperties = null;
+ }
+
+ @Test
+ public void testSetKeyName() {
+ _oInstance.setKeyName(_keyName);
+ assertEquals(_oInstance.getKeyName(), _keyName);
+ }
+
+ @Test
+ public void testSetKeyValue() {
+ _oInstance.setKeyName(_keyName);
+ assertEquals(_oInstance.getKeyName(), _keyName);
+ }
+
+ @Test
+ public void testSetAdditionalProperty() {
+ _oInstance.setAdditionalProperty("prop1", "propvalue1");
+ _oInstance.setAdditionalProperty("prop2", "propvalue2");
+ assertEquals(_oInstance.getAdditionalProperties(), _additionalProperties);
+ }
+
+}
diff --git a/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/update/UpdateTest.java b/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/update/UpdateTest.java
new file mode 100644
index 000000000..8f8a06eac
--- /dev/null
+++ b/adaptors/aai-service/provider/src/test/java/org/onap/ccsdk/sli/adaptors/aai/update/UpdateTest.java
@@ -0,0 +1,75 @@
+package org.onap.ccsdk.sli.adaptors.aai.update;
+
+import static org.junit.Assert.*;
+import static org.mockito.Mockito.mock;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class UpdateTest {
+
+ Update _oInstance;
+ protected Map<String, Object> _additionalProperties;
+ protected String _updateNodeType;
+ protected List<UpdateNodeKey> _updateNodeKey;
+ protected List<Action> _action;
+
+ @Before
+ public void setUp() throws Exception {
+ _oInstance = new Update();
+ _updateNodeType = "updateNodeType";
+ _action = new ArrayList<>();
+ Action a1 = mock(Action.class);
+ Action a2 = mock(Action.class);
+ _action.add(a1);
+ _action.add(a2);
+ _updateNodeKey = new ArrayList<>();
+ UpdateNodeKey k1 = mock(UpdateNodeKey.class);
+ UpdateNodeKey k2 = mock(UpdateNodeKey.class);
+ _updateNodeKey.add(k1);
+ _updateNodeKey.add(k2);
+ _additionalProperties = new HashMap<String, Object>() {{
+ put("prop1", "propvalue1");
+ put("prop2", "propvalue2");
+ }};
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ _oInstance = null;
+ _action = null;
+ _additionalProperties = null;
+ }
+
+ @Test
+ public void testSetUpdateNodeType() {
+ _oInstance.setUpdateNodeType(_updateNodeType);
+ assertEquals(_oInstance.getUpdateNodeType(), _updateNodeType);
+ }
+
+ @Test
+ public void testSetAction() {
+ _oInstance.setAction(_action);
+ assertEquals(_oInstance.getAction(), _action);
+ }
+
+ @Test
+ public void testSetUpdateNodeKey() {
+ _oInstance.setUpdateNodeKey(_updateNodeKey);
+ assertEquals(_oInstance.getUpdateNodeKey(), _updateNodeKey);
+ }
+
+
+ @Test
+ public void testSetAdditionalProperty() {
+ _oInstance.setAdditionalProperty("prop1", "propvalue1");
+ _oInstance.setAdditionalProperty("prop2", "propvalue2");
+ assertEquals(_oInstance.getAdditionalProperties(), _additionalProperties);
+ }
+}
diff --git a/adaptors/aai-service/provider/src/test/resources/aaiclient.properties b/adaptors/aai-service/provider/src/test/resources/aaiclient.properties
new file mode 100755
index 000000000..571280b81
--- /dev/null
+++ b/adaptors/aai-service/provider/src/test/resources/aaiclient.properties
@@ -0,0 +1,80 @@
+###
+# ============LICENSE_START=======================================================
+# openECOMP : SDN-C
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights
+# reserved.
+# ================================================================================
+# 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.
+# ============LICENSE_END=========================================================
+###
+
+#
+# Configuration file for A&AI Client
+#
+
+#
+# Certificate keystore and truststore
+#
+org.onap.ccsdk.sli.adaptors.aai.ssl.trust=/opt/onap/ccsdk/data/stores/truststore.onap.client.jks
+org.onap.ccsdk.sli.adaptors.aai.ssl.trust.psswd=adminadmin
+org.onap.ccsdk.sli.adaptors.aai.host.certificate.ignore=true
+
+org.onap.ccsdk.sli.adaptors.aai.client.name=SDNC
+org.onap.ccsdk.sli.adaptors.aai.client.psswd=SDNC
+
+org.onap.ccsdk.sli.adaptors.aai.application=CCSDK
+#
+# Configuration file for A&AI Client
+#
+org.onap.ccsdk.sli.adaptors.aai.uri=https://aai.api.simpledemo.onap.org:8443
+connection.timeout=60000
+read.timeout=60000
+
+# aai version
+org.onap.ccsdk.sli.adaptors.aai.version=/v21/
+
+# query
+org.onap.ccsdk.sli.adaptors.aai.path.query=/aai/v21/search/sdn-zone-query
+org.onap.ccsdk.sli.adaptors.aai.query.nodes=/aai/v21/search/nodes-query?search-node-type={node-type}&filter={entity-identifier}:EQUALS:{entity-name}
+org.onap.ccsdk.sli.adaptors.aai.query.generic=/aai/v21/search/generic-query?key={identifier}:{value}&start-node-type={start-node-type}&include=complex&depth=3
+
+#update
+org.onap.ccsdk.sli.adaptors.aai.update=/aai/v21/actions/update
+
+# UBB Notify
+org.onap.ccsdk.sli.adaptors.aai.path.notify=/aai/v21/actions/notify
+org.onap.ccsdk.sli.adaptors.aai.notify.selflink.fqdn=<%= @ubbUri %>/restconf/config/L3SDN-API:services/layer3-service-list/{service-instance-id}
+org.onap.ccsdk.sli.adaptors.aai.notify.selflink.avpn=<%= @ubbUri %>/restconf/config/L3AVPN-EVC-API:services/service-list/{service-instance-id}/service-data/avpn-logicalchannel-information
+
+# P-Interfaces
+org.onap.ccsdk.sli.adaptors.aai.path.pserver.pinterfaces=/aai/v21/cloud-infrastructure/pservers/pserver/{hostname}/p-interfaces
+org.onap.ccsdk.sli.adaptors.aai.path.pserver.pinterface=/aai/v21/cloud-infrastructure/pservers/pserver/{hostname}/p-interfaces/p-interface/{interface-name}
+
+# VNF IMAGES
+org.onap.ccsdk.sli.adaptors.aai.path.vnf.image.query=/aai/v21/service-design-and-creation/vnf-images/vnf-image?application={application_model}&application-vendor={application_vendor}
+
+# service instance
+org.onap.ccsdk.sli.adaptors.aai.path.svcinst.query=/aai/v21/search/generic-query?key=service-instance.service-instance-id:{svc-instance-id}&start-node-type=service-instance&include=service-instance
+org.onap.ccsdk.sli.adaptors.aai.path.service.instance=/aai/v21/business/customers/customer/{global-customer-id}/service-subscriptions/service-subscription/{service-type}/service-instances/service-instance/{service-instance-id}
+
+# VNF IMAGES QUERY
+org.onap.ccsdk.sli.adaptors.aai.path.vnf.image.query=/aai/v21/service-design-and-creation/vnf-images/vnf-image?application={application_model}&application-vendor={application_vendor}
+
+#
+# Formatting
+#
+org.onap.ccsdk.sli.adaptors.aai.param.format=filter=%s:%s
+org.onap.ccsdk.sli.adaptors.aai.param.vnf_type=vnf-type
+org.onap.ccsdk.sli.adaptors.aai.param.physical.location.id=physical-location-id
+org.onap.ccsdk.sli.adaptors.aai.param.service.type=service-type
diff --git a/adaptors/aai-service/provider/src/test/resources/json/linterfaceJson.txt b/adaptors/aai-service/provider/src/test/resources/json/linterfaceJson.txt
new file mode 100755
index 000000000..22c8db1ee
--- /dev/null
+++ b/adaptors/aai-service/provider/src/test/resources/json/linterfaceJson.txt
@@ -0,0 +1,43 @@
+ {
+ "interface-name": "example-interface-name-val-1600",
+ "interface-role": "example-interface-role-val-1600",
+ "v6-wan-link-ip": "example-v6-wan-link-ip-val-1600",
+ "resource-version": "1450729537",
+ "vlans": {
+ "vlan": [
+ {
+ "vlan-interface": "example-vlan-interface-val-7133",
+ "vlan-id-inner": 1318,
+ "vlan-id-outer": 244,
+ "resource-version": "1450729537",
+ "relationship-list": {
+
+ },
+ "l3-interface-ipv4-address-list": [
+ {
+ "l3-interface-ipv4-address": "example-l3-interface-ipv4-address-val-9533",
+ "l3-interface-ipv4-prefix-length": 3013,
+ "vlan-id-inner": 7150,
+ "vlan-id-outer": 1027,
+ "resource-version": "1450729537",
+ "relationship-list": {
+
+ }
+ }
+ ],
+ "l3-interface-ipv6-address-list": [
+ {
+ "l3-interface-ipv6-address": "example-l3-interface-ipv6-address-val-7149",
+ "l3-interface-ipv6-prefix-length": 4538,
+ "vlan-id-inner": 8271,
+ "vlan-id-outer": 8990,
+ "resource-version": "1450729537",
+ "relationship-list": {
+
+ }
+ }
+ ]
+ }
+ ]
+ }
+ } \ No newline at end of file
diff --git a/adaptors/aai-service/provider/src/test/resources/json/pserverJson.txt b/adaptors/aai-service/provider/src/test/resources/json/pserverJson.txt
new file mode 100755
index 000000000..4b7f97d37
--- /dev/null
+++ b/adaptors/aai-service/provider/src/test/resources/json/pserverJson.txt
@@ -0,0 +1,97 @@
+{
+ "selflink": "https://mtinjvmsdn30.cip.att.com:8443/aai/v4/network/pservers/pserver/chcil129snd",
+ "hostname": "chcil129snd",
+ "ptnii-equip-name": "chcil129snd",
+ "equip-type": "server1",
+ "equip-vendor": "HP",
+ "equip-model": "DL380p-nd",
+ "fqdn": "chcilrsv129.chcil.sbcglobal.net",
+ "ipv4-oam-address": "12.80.1.83",
+ "serial-number": "n02kvcBczBI",
+ "in-maint":false,
+ "resource-version": "1455988020",
+ "purpose": "Gamma-VCE",
+ "relationship-list": {
+ "relationship": [
+ {
+ "related-to": "complex",
+ "related-link": "https://aai.infra.aic.att.net:8443/aai/v5/cloud-infrastructure/complexes/complex/CHCGILCL73W/",
+ "relationship-data": [
+ {
+ "relationship-key": "complex.physical-location-id",
+ "relationship-value": "CHCGILCL73W"
+ }
+ ]
+ }
+ ]
+ },
+ "p-interfaces": {
+ "p-interface": [
+ {
+ "interface-name": "p6p2-6/2",
+ "speed-value": "10000000",
+ "speed-units": "kbps",
+ "resource-version": "1455988020",
+ "relationship-list": {
+ "relationship": [
+ {
+ "related-to": "physical-link",
+ "related-link": "https://aai.infra.aic.att.net:8443/aai/v5/network/physical-links/physical-link/chcil129snd%3Ap6p2-6%2F2%7Cchciltax102%3Axe-1%2F0%2F29/",
+ "relationship-data": [
+ {
+ "relationship-key": "physical-link.link-name",
+ "relationship-value": "chcil129snd:p6p2-6/2|chciltax102:xe-1/0/29"
+ }
+ ]
+ }
+ ]
+ },
+ "l-interfaces": {
+
+ }
+ },
+ {
+ "interface-name": "p6p1-6/1",
+ "speed-value": "10000000",
+ "speed-units": "kbps",
+ "resource-version": "1455988020",
+ "relationship-list": {
+ "relationship": [
+ {
+ "related-to": "physical-link",
+ "related-link": "https://aai.infra.aic.att.net:8443/aai/v5/network/physical-links/physical-link/chcil129snd%3Ap6p1-6%2F1%7Cchciltax101%3Axe-0%2F0%2F29/",
+ "relationship-data": [
+ {
+ "relationship-key": "physical-link.link-name",
+ "relationship-value": "chcil129snd:p6p1-6/1|chciltax101:xe-0/0/29"
+ }
+ ]
+ }
+ ]
+ },
+ "l-interfaces": {
+
+ }
+ },
+ {
+ "interface-name": "em0-0/1",
+ "speed-value": "10000000",
+ "speed-units": "kbps",
+ "resource-version": "1455988020",
+ "relationship-list": {
+ "relationship": [
+ {
+ "related-to": "physical-link",
+ "related-link": "https://aai.infra.aic.att.net:8443/aai/v5/network/physical-links/physical-link/chcil129snd%3Aem0-0%2F1%7Cchciltax101%3Axe-0%2F0%2F59/",
+ "relationship-data": [
+ {
+
+ }
+ ]
+ }
+ ]
+ }
+ }
+ ]
+ }
+} \ No newline at end of file
diff --git a/adaptors/aai-service/provider/src/test/resources/testCommands.txt b/adaptors/aai-service/provider/src/test/resources/testCommands.txt
new file mode 100644
index 000000000..d19b8d306
--- /dev/null
+++ b/adaptors/aai-service/provider/src/test/resources/testCommands.txt
@@ -0,0 +1 @@
+query|generic-vnf|generic-vnf.vnf-id:assign:value:adb28ac0-a260-4b7d-9ce5-adf15733c458 \ No newline at end of file
diff --git a/adaptors/ansible-adapter/.pydevproject b/adaptors/ansible-adapter/.pydevproject
new file mode 100644
index 000000000..d001f0aea
--- /dev/null
+++ b/adaptors/ansible-adapter/.pydevproject
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<?eclipse-pydev version="1.0"?><pydev_project>
+<pydev_property name="org.python.pydev.PYTHON_PROJECT_INTERPRETER">Default</pydev_property>
+<pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python interpreter</pydev_property>
+</pydev_project>
diff --git a/adaptors/ansible-adapter/ansible-adapter-bundle/.gitignore b/adaptors/ansible-adapter/ansible-adapter-bundle/.gitignore
new file mode 100644
index 000000000..255b54097
--- /dev/null
+++ b/adaptors/ansible-adapter/ansible-adapter-bundle/.gitignore
@@ -0,0 +1,25 @@
+# ============LICENSE_START==========================================
+# ONAP : APPC
+# ===================================================================
+# Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the License);
+# you may not use this software 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.
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+# ============LICENSE_END============================================
+/bin/
+/target/
+/target-ide/
+/.settings/
diff --git a/adaptors/ansible-adapter/ansible-adapter-bundle/pom.xml b/adaptors/ansible-adapter/ansible-adapter-bundle/pom.xml
new file mode 100644
index 000000000..605c64421
--- /dev/null
+++ b/adaptors/ansible-adapter/ansible-adapter-bundle/pom.xml
@@ -0,0 +1,131 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- ============LICENSE_START=======================================================
+ ONAP : APPC ================================================================================
+ Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
+ ================================================================================
+ Copyright (C) 2017 Amdocs =============================================================================
+ 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. ECOMP is
+ a trademark and service mark of AT&T Intellectual Property. ============LICENSE_END========================================================= -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>binding-parent</artifactId>
+ <version>2.1.0</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.adaptors</groupId>
+ <artifactId>ansible-adapter-bundle</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>bundle</packaging>
+
+ <name>ccsdk-sli-adaptors :: ansible-adapter :: ${project.artifactId}</name>
+
+ <properties>
+ <ccsdk.sli.adaptors.version>${project.version}</ccsdk.sli.adaptors.version>
+ </properties>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sli-core-artifacts</artifactId>
+ <version>${ccsdk.sli.core.version}</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>com.att.eelf</groupId>
+ <artifactId>eelf-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>commons-codec</groupId>
+ <artifactId>commons-codec</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>commons-logging</groupId>
+ <artifactId>commons-logging</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.httpcomponents</groupId>
+ <artifactId>httpclient</artifactId>
+ </dependency>
+
+
+ <!-- Needed to run test cases -->
+ <dependency>
+ <groupId>org.glassfish.jersey.core</groupId>
+ <artifactId>jersey-common</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.codehaus.jackson</groupId>
+ <artifactId>jackson-jaxrs</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sli-common</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sli-provider</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.core</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>jcl-over-slf4j</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.json</groupId>
+ <artifactId>json</artifactId>
+ </dependency>
+
+
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ </dependency>
+
+
+ </dependencies>
+</project>
diff --git a/adaptors/ansible-adapter/ansible-adapter-bundle/src/main/java/org/onap/ccsdk/sli/adaptors/ansible/AnsibleAdapter.java b/adaptors/ansible-adapter/ansible-adapter-bundle/src/main/java/org/onap/ccsdk/sli/adaptors/ansible/AnsibleAdapter.java
new file mode 100644
index 000000000..e43d3e3c3
--- /dev/null
+++ b/adaptors/ansible-adapter/ansible-adapter-bundle/src/main/java/org/onap/ccsdk/sli/adaptors/ansible/AnsibleAdapter.java
@@ -0,0 +1,55 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : APPC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Copyright (C) 2017 Amdocs
+ * =============================================================================
+ * 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.
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.ansible;
+
+import java.util.Map;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.core.sli.SvcLogicJavaPlugin;
+
+/**
+ * This interface defines the operations that the Ansible adapter exposes.
+ *
+ */
+public interface AnsibleAdapter extends SvcLogicJavaPlugin {
+ /**
+ * Returns the symbolic name of the adapter
+ *
+ * @return The adapter name
+ */
+ String getAdapterName();
+
+ /* Method to post request for execution of Playbook */
+ void reqExec(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException;
+
+ /* Method to get result of a playbook execution request */
+ void reqExecResult(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException;
+
+ /* Method to get log of a playbook execution request */
+ void reqExecLog(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException;
+
+ /* Method to get output of a playbook execution request */
+ void reqExecOutput(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException;
+}
diff --git a/adaptors/ansible-adapter/ansible-adapter-bundle/src/main/java/org/onap/ccsdk/sli/adaptors/ansible/AnsibleAdapterPropertiesProvider.java b/adaptors/ansible-adapter/ansible-adapter-bundle/src/main/java/org/onap/ccsdk/sli/adaptors/ansible/AnsibleAdapterPropertiesProvider.java
new file mode 100755
index 000000000..6d9f4f12c
--- /dev/null
+++ b/adaptors/ansible-adapter/ansible-adapter-bundle/src/main/java/org/onap/ccsdk/sli/adaptors/ansible/AnsibleAdapterPropertiesProvider.java
@@ -0,0 +1,28 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * onap
+ * ================================================================================
+ * Copyright (C) 2016 - 2017 ONAP
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.ansible;
+
+import java.util.Properties;
+
+public interface AnsibleAdapterPropertiesProvider {
+
+ public Properties getProperties();
+}
diff --git a/adaptors/ansible-adapter/ansible-adapter-bundle/src/main/java/org/onap/ccsdk/sli/adaptors/ansible/impl/AnsibleAdapterImpl.java b/adaptors/ansible-adapter/ansible-adapter-bundle/src/main/java/org/onap/ccsdk/sli/adaptors/ansible/impl/AnsibleAdapterImpl.java
new file mode 100644
index 000000000..2361feebd
--- /dev/null
+++ b/adaptors/ansible-adapter/ansible-adapter-bundle/src/main/java/org/onap/ccsdk/sli/adaptors/ansible/impl/AnsibleAdapterImpl.java
@@ -0,0 +1,460 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : APPC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Copyright (C) 2017 Amdocs
+ * =============================================================================
+ * 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.
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.ansible.impl;
+
+import java.util.Map;
+import java.util.Properties;
+import org.apache.commons.lang.StringUtils;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.onap.ccsdk.sli.adaptors.ansible.AnsibleAdapter;
+import org.onap.ccsdk.sli.adaptors.ansible.AnsibleAdapterPropertiesProvider;
+import org.onap.ccsdk.sli.adaptors.ansible.model.AnsibleMessageParser;
+import org.onap.ccsdk.sli.adaptors.ansible.model.AnsibleResult;
+import org.onap.ccsdk.sli.adaptors.ansible.model.AnsibleResultCodes;
+import org.onap.ccsdk.sli.adaptors.ansible.model.AnsibleServerEmulator;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+
+/**
+ * This class implements the {@link AnsibleAdapter} interface. This interface defines the behaviors
+ * that our service provides.
+ */
+public class AnsibleAdapterImpl implements AnsibleAdapter {
+
+
+ /**
+ * The constant used to define the service name in the mapped diagnostic context
+ */
+ @SuppressWarnings("nls")
+ public static final String MDC_SERVICE = "service";
+
+ /**
+ * The constant for the status code for a failed outcome
+ */
+ @SuppressWarnings("nls")
+ public static final String OUTCOME_FAILURE = "failure";
+
+ /**
+ * The constant for the status code for a successful outcome
+ */
+ @SuppressWarnings("nls")
+ public static final String OUTCOME_SUCCESS = "success";
+
+ /**
+ * Adapter Name
+ */
+ private static final String ADAPTER_NAME = "Ansible Adapter";
+ private static final String APPC_EXCEPTION_CAUGHT = "APPCException caught";
+
+ private static final String RESULT_CODE_ATTRIBUTE_NAME = "org.onap.appc.adapter.ansible.result.code";
+ private static final String MESSAGE_ATTRIBUTE_NAME = "org.onap.appc.adapter.ansible.message";
+ private static final String RESULTS_ATTRIBUTE_NAME = "org.onap.appc.adapter.ansible.results";
+ private static final String ID_ATTRIBUTE_NAME = "org.onap.appc.adapter.ansible.Id";
+ private static final String LOG_ATTRIBUTE_NAME = "org.onap.appc.adapter.ansible.log";
+ private static final String OUTPUT_ATTRIBUTE_NAME = "org.onap.appc.adapter.ansible.output";
+
+ private static final String CLIENT_TYPE_PROPERTY_NAME = "org.onap.appc.adapter.ansible.clientType";
+ private static final String TRUSTSTORE_PROPERTY_NAME = "org.onap.appc.adapter.ansible.trustStore";
+ private static final String TRUSTPASSD_PROPERTY_NAME = "org.onap.appc.adapter.ansible.trustStore.trustPasswd";
+
+ private static final String PASSD = "Password";
+
+ /**
+ * The logger to be used
+ */
+ private static final EELFLogger logger = EELFManager.getInstance().getLogger(AnsibleAdapterImpl.class);
+
+
+ /**
+ * Connection object
+ **/
+ private ConnectionBuilder httpClient;
+
+ /**
+ * Ansible API Message Handlers
+ **/
+ private AnsibleMessageParser messageProcessor;
+
+ /**
+ * indicator whether in test mode
+ **/
+ private boolean testMode = false;
+
+ /**
+ * server emulator object to be used if in test mode
+ **/
+ private AnsibleServerEmulator testServer;
+
+ /**
+ * This default constructor is used as a work around because the activator wasn't getting called
+ */
+ public AnsibleAdapterImpl() {
+ initialize(new AnsibleAdapterPropertiesProviderImpl());
+ }
+ public AnsibleAdapterImpl(AnsibleAdapterPropertiesProvider propProvider) {
+ initialize(propProvider);
+ }
+
+ /**
+ * Used for jUnit test and testing interface
+ */
+ public AnsibleAdapterImpl(boolean mode) {
+ testMode = mode;
+ testServer = new AnsibleServerEmulator();
+ messageProcessor = new AnsibleMessageParser();
+ }
+
+ /**
+ * Returns the symbolic name of the adapter
+ *
+ * @return The adapter name
+ * @see org.onap.appc.adapter.rest.AnsibleAdapter#getAdapterName()
+ */
+ @Override
+ public String getAdapterName() {
+ return ADAPTER_NAME;
+ }
+
+ /**
+ * @param rc Method posts info to Context memory in case of an error and throws a
+ * SvcLogicException causing SLI to register this as a failure
+ */
+ @SuppressWarnings("static-method")
+ private void doFailure(SvcLogicContext svcLogic, int code, String message) throws SvcLogicException {
+
+ svcLogic.setStatus(OUTCOME_FAILURE);
+ svcLogic.setAttribute(RESULT_CODE_ATTRIBUTE_NAME, Integer.toString(code));
+ svcLogic.setAttribute(MESSAGE_ATTRIBUTE_NAME, message);
+
+ throw new SvcLogicException("Ansible Adapter Error = " + message);
+ }
+
+ /**
+ * initialize the Ansible adapter based on default and over-ride configuration data
+ */
+ private void initialize(AnsibleAdapterPropertiesProvider propProvider) {
+
+
+ Properties props = propProvider.getProperties();
+
+ // Create the message processor instance
+ messageProcessor = new AnsibleMessageParser();
+
+ // Create the http client instance
+ // type of client is extracted from the property file parameter
+ // org.onap.appc.adapter.ansible.clientType
+ // It can be :
+ // 1. TRUST_ALL (trust all SSL certs). To be used ONLY in dev
+ // 2. TRUST_CERT (trust only those whose certificates have been stored in the trustStore file)
+ // 3. DEFAULT (trust only well known certificates). This is standard behavior to which it will
+ // revert. To be used in PROD
+
+ try {
+ String clientType = props.getProperty(CLIENT_TYPE_PROPERTY_NAME);
+ logger.info("Ansible http client type set to " + clientType);
+
+ if ("TRUST_ALL".equals(clientType)) {
+ logger.info(
+ "Creating http client to trust ALL ssl certificates. WARNING. This should be done only in dev environments");
+ httpClient = new ConnectionBuilder(1);
+ } else if ("TRUST_CERT".equals(clientType)) {
+ // set path to keystore file
+ String trustStoreFile = props.getProperty(TRUSTSTORE_PROPERTY_NAME);
+ String key = props.getProperty(TRUSTPASSD_PROPERTY_NAME);
+ char[] trustStorePasswd = key.toCharArray();
+ logger.info("Creating http client with trustmanager from " + trustStoreFile);
+ httpClient = new ConnectionBuilder(trustStoreFile, trustStorePasswd);
+ } else {
+ logger.info("Creating http client with default behaviour");
+ httpClient = new ConnectionBuilder(0);
+ }
+ } catch (Exception e) {
+ logger.error("Error Initializing Ansible Adapter due to Unknown Exception", e);
+ }
+
+ logger.info("Initialized Ansible Adapter");
+ }
+
+ // Public Method to post request to execute playbook. Posts the following back
+ // to Svc context memory
+ // org.onap.appc.adapter.ansible.req.code : 100 if successful
+ // org.onap.appc.adapter.ansible.req.messge : any message
+ // org.onap.appc.adapter.ansible.req.Id : a unique uuid to reference the request
+ @Override
+ public void reqExec(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException {
+
+ String playbookName = StringUtils.EMPTY;
+ String payload = StringUtils.EMPTY;
+ String agentUrl = StringUtils.EMPTY;
+ String user = StringUtils.EMPTY;
+ String password = StringUtils.EMPTY;
+ String id = StringUtils.EMPTY;
+
+ JSONObject jsonPayload;
+
+ try {
+ // create json object to send request
+ jsonPayload = messageProcessor.reqMessage(params);
+
+ agentUrl = (String) jsonPayload.remove("AgentUrl");
+ user = (String) jsonPayload.remove("User");
+ password = (String) jsonPayload.remove(PASSD);
+ id = jsonPayload.getString("Id");
+ payload = jsonPayload.toString();
+ logger.info("Updated Payload = " + payload);
+ } catch (SvcLogicException e) {
+ logger.error(APPC_EXCEPTION_CAUGHT, e);
+ doFailure(ctx, AnsibleResultCodes.INVALID_PAYLOAD.getValue(),
+ "Error constructing request for execution of playbook due to missing mandatory parameters. Reason = "
+ + e.getMessage());
+ } catch (JSONException e) {
+ logger.error("JSONException caught", e);
+ doFailure(ctx, AnsibleResultCodes.INVALID_PAYLOAD.getValue(),
+ "Error constructing request for execution of playbook due to invalid JSON block. Reason = "
+ + e.getMessage());
+ } catch (NumberFormatException e) {
+ logger.error("NumberFormatException caught", e);
+ doFailure(ctx, AnsibleResultCodes.INVALID_PAYLOAD.getValue(),
+ "Error constructing request for execution of playbook due to invalid parameter values. Reason = "
+ + e.getMessage());
+ }
+
+ int code = -1;
+ String message = StringUtils.EMPTY;
+
+ try {
+ // post the test request
+ logger.info("Posting request = " + payload + " to url = " + agentUrl);
+ AnsibleResult testResult = postExecRequest(agentUrl, payload, user, password);
+
+ // Process if HTTP was successful
+ if (testResult.getStatusCode() == 200) {
+ testResult = messageProcessor.parsePostResponse(testResult.getStatusMessage());
+ } else {
+ doFailure(ctx, testResult.getStatusCode(),
+ "Error posting request. Reason = " + testResult.getStatusMessage());
+ }
+
+ code = testResult.getStatusCode();
+ message = testResult.getStatusMessage();
+
+ // Check status of test request returned by Agent
+ if (code == AnsibleResultCodes.PENDING.getValue()) {
+ logger.info(String.format("Submission of Test %s successful.", playbookName));
+ // test request accepted. We are in asynchronous case
+ } else {
+ doFailure(ctx, code, "Request for execution of playbook rejected. Reason = " + message);
+ }
+ } catch (SvcLogicException e) {
+ logger.error(APPC_EXCEPTION_CAUGHT, e);
+ doFailure(ctx, AnsibleResultCodes.UNKNOWN_EXCEPTION.getValue(),
+ "Exception encountered when posting request for execution of playbook. Reason = " + e.getMessage());
+ }
+
+ ctx.setAttribute(RESULT_CODE_ATTRIBUTE_NAME, Integer.toString(code));
+ ctx.setAttribute(MESSAGE_ATTRIBUTE_NAME, message);
+ ctx.setAttribute(ID_ATTRIBUTE_NAME, id);
+ }
+
+ /**
+ * Public method to query status of a specific request It blocks till the Ansible Server
+ * responds or the session times out (non-Javadoc)
+ *
+ * @see org.onap.ccsdk.sli.adaptors.ansible.AnsibleAdapter#reqExecResult(java.util.Map,
+ * org.onap.ccsdk.sli.core.sli.SvcLogicContext)
+ */
+ @Override
+ public void reqExecResult(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException {
+
+ // Get URI
+ String reqUri = StringUtils.EMPTY;
+
+ try {
+ reqUri = messageProcessor.reqUriResult(params);
+ logger.info("Got uri ", reqUri );
+ } catch (SvcLogicException e) {
+ logger.error(APPC_EXCEPTION_CAUGHT, e);
+ doFailure(ctx, AnsibleResultCodes.INVALID_PAYLOAD.getValue(),
+ "Error constructing request to retrieve result due to missing parameters. Reason = "
+ + e.getMessage());
+ return;
+ } catch (NumberFormatException e) {
+ logger.error("NumberFormatException caught", e);
+ doFailure(ctx, AnsibleResultCodes.INVALID_PAYLOAD.getValue(),
+ "Error constructing request to retrieve result due to invalid parameters value. Reason = "
+ + e.getMessage());
+ return;
+ }
+
+ int code = -1;
+ String message = StringUtils.EMPTY;
+ String results = StringUtils.EMPTY;
+
+ try {
+ // Try to retrieve the test results (modify the URL for that)
+ AnsibleResult testResult = queryServer(reqUri, params.get("User"), params.get(PASSD));
+ code = testResult.getStatusCode();
+ message = testResult.getStatusMessage();
+
+ if (code == 200) {
+ logger.info("Parsing response from Server = " + message);
+ // Valid HTTP. process the Ansible message
+ testResult = messageProcessor.parseGetResponse(message);
+ code = testResult.getStatusCode();
+ message = testResult.getStatusMessage();
+ results = testResult.getResults();
+ }
+
+ logger.info("Request response = " + message);
+ } catch (SvcLogicException e) {
+ logger.error(APPC_EXCEPTION_CAUGHT, e);
+ doFailure(ctx, AnsibleResultCodes.UNKNOWN_EXCEPTION.getValue(),
+ "Exception encountered retrieving result : " + e.getMessage());
+ return;
+ }
+
+ // We were able to get and process the results. Determine if playbook succeeded
+
+ if (code == AnsibleResultCodes.FINAL_SUCCESS.getValue()) {
+ message = String.format("Ansible Request %s finished with Result = %s, Message = %s", params.get("Id"),
+ OUTCOME_SUCCESS, message);
+ logger.info(message);
+ } else {
+ logger.info(String.format("Ansible Request %s finished with Result %s, Message = %s", params.get("Id"),
+ OUTCOME_FAILURE, message));
+ ctx.setAttribute(RESULTS_ATTRIBUTE_NAME, results);
+ doFailure(ctx, code, message);
+ return;
+ }
+
+ ctx.setAttribute(RESULT_CODE_ATTRIBUTE_NAME, Integer.toString(400));
+ ctx.setAttribute(MESSAGE_ATTRIBUTE_NAME, message);
+ ctx.setAttribute(RESULTS_ATTRIBUTE_NAME, results);
+ ctx.setStatus(OUTCOME_SUCCESS);
+ }
+
+ /**
+ * Public method to get logs from playbook execution for a specific request
+ *
+ * It blocks till the Ansible Server responds or the session times out very similar to
+ * reqExecResult logs are returned in the DG context variable org.onap.appc.adapter.ansible.log
+ */
+ @Override
+ public void reqExecLog(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException {
+
+ String reqUri = StringUtils.EMPTY;
+ try {
+ reqUri = messageProcessor.reqUriLog(params);
+ logger.info("Retrieving results from " + reqUri);
+ } catch (Exception e) {
+ logger.error("Exception caught", e);
+ doFailure(ctx, AnsibleResultCodes.INVALID_PAYLOAD.getValue(), e.getMessage());
+ }
+
+ String message = StringUtils.EMPTY;
+ try {
+ // Try to retrieve the test results (modify the url for that)
+ AnsibleResult testResult = queryServer(reqUri, params.get("User"), params.get(PASSD));
+ message = testResult.getStatusMessage();
+ logger.info("Request output = " + message);
+ ctx.setAttribute(LOG_ATTRIBUTE_NAME, message);
+ ctx.setStatus(OUTCOME_SUCCESS);
+ } catch (Exception e) {
+ logger.error("Exception caught", e);
+ doFailure(ctx, AnsibleResultCodes.UNKNOWN_EXCEPTION.getValue(),
+ "Exception encountered retreiving output : " + e.getMessage());
+ }
+ }
+
+ /**
+ * Public method to get output from playbook execution for a specific request
+ *
+ * It blocks till the Ansible Server responds or the session times out very similar to
+ * reqExecResult and output is returned in the DG context variable org.onap.appc.adapter.ansible.output
+ */
+ @Override
+ public void reqExecOutput(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException {
+
+ String reqUri = StringUtils.EMPTY;
+ try {
+ reqUri = messageProcessor.reqUriOutput(params);
+ logger.info("Retrieving results from " + reqUri);
+ } catch (Exception e) {
+ logger.error("Exception caught", e);
+ doFailure(ctx, AnsibleResultCodes.INVALID_PAYLOAD.getValue(), e.getMessage());
+ }
+
+ String message = StringUtils.EMPTY;
+ try {
+ // Try to retrieve the test results (modify the url for that)
+ AnsibleResult testResult = queryServer(reqUri, params.get("User"), params.get(PASSD));
+ message = testResult.getStatusMessage();
+ logger.info("Request output = " + message);
+ ctx.setAttribute(OUTPUT_ATTRIBUTE_NAME, message);
+ ctx.setStatus(OUTCOME_SUCCESS);
+ } catch (Exception e) {
+ logger.error("Exception caught", e);
+ doFailure(ctx, AnsibleResultCodes.UNKNOWN_EXCEPTION.getValue(),
+ "Exception encountered retreiving output : " + e.getMessage());
+ }
+ }
+
+ /**
+ * Method that posts the request
+ */
+ private AnsibleResult postExecRequest(String agentUrl, String payload, String user, String password) {
+
+ AnsibleResult testResult;
+
+ if (!testMode) {
+ httpClient.setHttpContext(user, password);
+ testResult = httpClient.post(agentUrl, payload);
+ } else {
+ testResult = testServer.Post(agentUrl, payload);
+ }
+ return testResult;
+ }
+
+ /**
+ * Method to query Ansible server
+ */
+ private AnsibleResult queryServer(String agentUrl, String user, String password) {
+
+ AnsibleResult testResult;
+
+ logger.info("Querying url = " + agentUrl);
+
+ if (!testMode) {
+ testResult = httpClient.get(agentUrl);
+ } else {
+ testResult = testServer.Get(agentUrl);
+ }
+
+ return testResult;
+ }
+}
diff --git a/adaptors/ansible-adapter/ansible-adapter-bundle/src/main/java/org/onap/ccsdk/sli/adaptors/ansible/impl/AnsibleAdapterPropertiesProviderImpl.java b/adaptors/ansible-adapter/ansible-adapter-bundle/src/main/java/org/onap/ccsdk/sli/adaptors/ansible/impl/AnsibleAdapterPropertiesProviderImpl.java
new file mode 100755
index 000000000..482aaf8e5
--- /dev/null
+++ b/adaptors/ansible-adapter/ansible-adapter-bundle/src/main/java/org/onap/ccsdk/sli/adaptors/ansible/impl/AnsibleAdapterPropertiesProviderImpl.java
@@ -0,0 +1,191 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * onap
+ * ================================================================================
+ * Copyright (C) 2016 - 2017 ONAP
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.ansible.impl;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Optional;
+import java.util.Properties;
+import java.util.Vector;
+import org.onap.ccsdk.sli.adaptors.ansible.AnsibleAdapterPropertiesProvider;
+import org.onap.ccsdk.sli.core.sli.ConfigurationException;
+import org.onap.ccsdk.sli.core.utils.JREFileResolver;
+import org.onap.ccsdk.sli.core.utils.KarafRootFileResolver;
+import org.onap.ccsdk.sli.core.utils.PropertiesFileResolver;
+import org.onap.ccsdk.sli.core.utils.common.CoreDefaultFileResolver;
+import org.onap.ccsdk.sli.core.utils.common.SdncConfigEnvVarFileResolver;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Responsible for determining the properties file to use and instantiating the
+ * <code>SqlResource</code> Service. The priority for properties file
+ * resolution is as follows:
+ *
+ * <ol>
+ * <li>A directory identified by the system environment variable
+ * <code>SDNC_CONFIG_DIR</code></li>
+ * <li>The default directory <code>DEFAULT_DBLIB_PROP_DIR</code></li>
+ * <li>A directory identified by the JRE argument
+ * <code>sql-resource.properties</code></li>
+ * <li>A <code>sql-resource.properties</code> file located in the karaf root
+ * directory</li>
+ * </ol>
+ */
+public class AnsibleAdapterPropertiesProviderImpl implements AnsibleAdapterPropertiesProvider {
+
+ private static final Logger LOG = LoggerFactory.getLogger(AnsibleAdapterPropertiesProviderImpl.class);
+
+ /**
+ * The name of the properties file for database configuration
+ */
+ private static final String ANSIBLEADAPTER_PROP_FILE_NAME = "ansible-adapter.properties";
+
+ /**
+ * A prioritized list of strategies for resolving sql-resource properties files.
+ */
+ private Vector<PropertiesFileResolver> ansibleAdapterPropertiesFileResolvers = new Vector<>();
+
+ /**
+ * The configuration properties for the db connection.
+ */
+ private Properties properties;
+
+ /**
+ * Set up the prioritized list of strategies for resolving dblib properties
+ * files.
+ */
+ public AnsibleAdapterPropertiesProviderImpl() {
+ ansibleAdapterPropertiesFileResolvers
+ .add(new SdncConfigEnvVarFileResolver("Using property file (1) from environment variable"));
+ ansibleAdapterPropertiesFileResolvers.add(new CoreDefaultFileResolver("Using property file (2) from default directory"));
+
+ ansibleAdapterPropertiesFileResolvers.add(
+ new JREFileResolver("Using property file (3) from JRE argument", AnsibleAdapterPropertiesProviderImpl.class));
+ ansibleAdapterPropertiesFileResolvers.add(new KarafRootFileResolver("Using property file (4) from karaf root", this));
+
+ // determines properties file as according to the priority described in the
+ // class header comment
+ final File propertiesFile = determinePropertiesFile(this);
+ if (propertiesFile != null) {
+ try (FileInputStream fileInputStream = new FileInputStream(propertiesFile)) {
+ properties = new Properties();
+ properties.load(fileInputStream);
+ } catch (final IOException e) {
+ LOG.error("Failed to load properties for file: {}", propertiesFile.toString(),
+ new ConfigurationException("Failed to load properties for file: " + propertiesFile.toString(),
+ e));
+ }
+ } else {
+ // Try to read properties as resource
+
+ InputStream propStr = getClass().getResourceAsStream("/" + ANSIBLEADAPTER_PROP_FILE_NAME);
+ if (propStr != null) {
+ properties = new Properties();
+ try {
+ properties.load(propStr);
+ propStr.close();
+ } catch (IOException e) {
+ properties = null;
+ }
+ }
+
+ }
+
+ if (properties == null) {
+ reportFailure("Missing configuration properties resource(3)", new ConfigurationException(
+ "Missing configuration properties resource(3): " + ANSIBLEADAPTER_PROP_FILE_NAME));
+
+ LOG.info("Defaulting org.onap.appc.adapter.ansible.clientType to TRUST_ALL");
+
+ properties = new Properties();
+ properties.setProperty("org.onap.appc.adapter.ansible.clientType", "TRUST_ALL");
+ }
+ }
+
+ /**
+ * Extract svclogic config properties.
+ *
+ * @return the svclogic config properties
+ */
+ public Properties getProperties() {
+ return properties;
+ }
+
+ /**
+ * Reports the method chosen for properties resolution to the
+ * <code>Logger</code>.
+ *
+ * @param message
+ * Some user friendly message
+ * @param fileOptional
+ * The file location of the chosen properties file
+ * @return the file location of the chosen properties file
+ */
+ private static File reportSuccess(final String message, final Optional<File> fileOptional) {
+ if (fileOptional.isPresent()) {
+ final File file = fileOptional.get();
+ LOG.info("{} {}", message, file.getPath());
+ return file;
+ }
+ return null;
+ }
+
+ /**
+ * Reports fatal errors. This is the case in which no properties file could be
+ * found.
+ *
+ * @param message
+ * An appropriate fatal error message
+ * @param configurationException
+ * An exception describing what went wrong during resolution
+ */
+ private static void reportFailure(final String message, final ConfigurationException configurationException) {
+
+ LOG.error("{}", message, configurationException);
+ }
+
+ /**
+ * Determines the sql-resource properties file to use based on the following priority:
+ * <ol>
+ * <li>A directory identified by the system environment variable
+ * <code>SDNC_CONFIG_DIR</code></li>
+ * <li>The default directory <code>DEFAULT_DBLIB_PROP_DIR</code></li>
+ * <li>A directory identified by the JRE argument
+ * <code>sql-resource.properties</code></li>
+ * <li>A <code>sql-resource.properties</code> file located in the karaf root
+ * directory</li>
+ * </ol>
+ */
+ File determinePropertiesFile(final AnsibleAdapterPropertiesProviderImpl resourceProvider) {
+
+ for (final PropertiesFileResolver sliPropertiesFileResolver : ansibleAdapterPropertiesFileResolvers) {
+ final Optional<File> fileOptional = sliPropertiesFileResolver.resolveFile(ANSIBLEADAPTER_PROP_FILE_NAME);
+ if (fileOptional.isPresent()) {
+ return reportSuccess(sliPropertiesFileResolver.getSuccessfulResolutionMessage(), fileOptional);
+ }
+ }
+
+ return null;
+ }
+}
diff --git a/adaptors/ansible-adapter/ansible-adapter-bundle/src/main/java/org/onap/ccsdk/sli/adaptors/ansible/impl/ConnectionBuilder.java b/adaptors/ansible-adapter/ansible-adapter-bundle/src/main/java/org/onap/ccsdk/sli/adaptors/ansible/impl/ConnectionBuilder.java
new file mode 100644
index 000000000..672e0df67
--- /dev/null
+++ b/adaptors/ansible-adapter/ansible-adapter-bundle/src/main/java/org/onap/ccsdk/sli/adaptors/ansible/impl/ConnectionBuilder.java
@@ -0,0 +1,205 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : APPC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Copyright (C) 2017 Amdocs
+ * ================================================================================
+ * Modifications Copyright © 2018 IBM.
+ * =============================================================================
+ * 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.
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.ansible.impl;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.security.KeyManagementException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import javax.net.ssl.SSLContext;
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpResponse;
+import org.apache.http.auth.AuthScope;
+import org.apache.http.auth.UsernamePasswordCredentials;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.client.protocol.HttpClientContext;
+import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
+import org.apache.http.conn.ssl.SSLContexts;
+import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.BasicCredentialsProvider;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.util.EntityUtils;
+import org.onap.ccsdk.sli.adaptors.ansible.model.AnsibleResult;
+import org.onap.ccsdk.sli.adaptors.ansible.model.AnsibleResultCodes;
+import org.onap.ccsdk.sli.core.utils.PathValidator;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+
+/**
+ * Returns a custom http client
+ * - based on options
+ * - can create one with ssl using an X509 certificate that does NOT have a known CA
+ * - create one which trusts ALL SSL certificates
+ * - return default httpclient (which only trusts known CAs from default cacerts file for process) this is the default
+ * option
+ **/
+
+public class ConnectionBuilder {
+
+ private static final EELFLogger logger = EELFManager.getInstance().getLogger(ConnectionBuilder.class);
+
+ private CloseableHttpClient httpClient = null;
+ private HttpClientContext httpContext = new HttpClientContext();
+
+ /**
+ * Constructor that initializes an http client based on certificate
+ **/
+ public ConnectionBuilder(String certFile) throws KeyStoreException, CertificateException, IOException,
+ KeyManagementException, NoSuchAlgorithmException {
+
+ /* Point to the certificate */
+ try(FileInputStream fs = new FileInputStream(certFile)){
+ /* Generate a certificate from the X509 */
+ CertificateFactory cf = CertificateFactory.getInstance("X.509");
+ X509Certificate cert = (X509Certificate) cf.generateCertificate(fs);
+
+ /* Create a keystore object and load the certificate there */
+ KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
+ keystore.load(null, null);
+ keystore.setCertificateEntry("cacert", cert);
+
+ SSLContext sslcontext = SSLContexts.custom().loadTrustMaterial(keystore).build();
+ SSLConnectionSocketFactory factory = new SSLConnectionSocketFactory(sslcontext,
+ SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
+
+ httpClient = HttpClients.custom().setSSLSocketFactory(factory).build();
+ }
+ }
+
+ /**
+ * Constructor which trusts all certificates in a specific java keystore file (assumes a JKS
+ * file)
+ **/
+ public ConnectionBuilder(String trustStoreFile, char[] trustStorePasswd) throws KeyStoreException, IOException,
+ KeyManagementException, NoSuchAlgorithmException, CertificateException {
+
+ if (!PathValidator.isValidFilePath(trustStoreFile)) {
+ throw new IOException("Invalid trust store file path");
+ }
+
+ /* Load the specified trustStore */
+ KeyStore keystore = KeyStore.getInstance("JKS");
+ FileInputStream readStream = new FileInputStream(trustStoreFile);
+ keystore.load(readStream, trustStorePasswd);
+
+ SSLContext sslcontext = SSLContexts.custom().loadTrustMaterial(keystore).build();
+ SSLConnectionSocketFactory factory = new SSLConnectionSocketFactory(sslcontext,
+ SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
+
+ httpClient = HttpClients.custom().setSSLSocketFactory(factory).build();
+ }
+
+ /**
+ * Constructor that trusts ALL SSl certificates (NOTE : ONLY FOR DEV TESTING) if Mode == 1 or
+ * Default if Mode == 0
+ */
+ public ConnectionBuilder(int mode)
+ throws NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
+ if (mode == 1) {
+ SSLContext sslcontext = SSLContexts.custom().loadTrustMaterial(null, new TrustSelfSignedStrategy()).build();
+ SSLConnectionSocketFactory factory = new SSLConnectionSocketFactory(sslcontext,
+ SSLConnectionSocketFactory.BROWSER_COMPATIBLE_HOSTNAME_VERIFIER);
+
+ httpClient = HttpClients.custom().setSSLSocketFactory(factory).build();
+ } else {
+ httpClient = HttpClients.createDefault();
+ }
+ }
+
+ // Use to create an http context with auth headers
+ public void setHttpContext(String user, String myPassword) {
+
+ // Are credential provided ? If so, set the context to be used
+ if (user != null && !user.isEmpty() && myPassword != null && !myPassword.isEmpty()) {
+ UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(user, myPassword);
+ AuthScope authscope = new AuthScope(AuthScope.ANY_HOST, AuthScope.ANY_PORT);
+ BasicCredentialsProvider credsprovider = new BasicCredentialsProvider();
+ credsprovider.setCredentials(authscope, credentials);
+ httpContext.setCredentialsProvider(credsprovider);
+ }
+ }
+
+ // Method posts to the ansible server and writes out response to
+ // Ansible result object
+ public AnsibleResult post(String agentUrl, String payload) {
+
+ AnsibleResult result = new AnsibleResult();
+ try {
+
+ HttpPost postObj = new HttpPost(agentUrl);
+ StringEntity bodyParams = new StringEntity(payload, "UTF-8");
+ postObj.setEntity(bodyParams);
+ postObj.addHeader("Content-type", "application/json");
+
+ HttpResponse response = httpClient.execute(postObj, httpContext);
+
+ HttpEntity entity = response.getEntity();
+ String responseOutput = entity != null ? EntityUtils.toString(entity) : null;
+ int responseCode = response.getStatusLine().getStatusCode();
+ result.setStatusCode(responseCode);
+ result.setStatusMessage(responseOutput);
+ } catch (IOException io) {
+ logger.error("Caught IOException", io);
+ result.setStatusCode(AnsibleResultCodes.IO_EXCEPTION.getValue());
+ result.setStatusMessage(io.getMessage());
+ }
+ return result;
+ }
+
+ // Method gets information from an Ansible server and writes out response to
+ // Ansible result object
+
+ public AnsibleResult get(String agentUrl) {
+
+ AnsibleResult result = new AnsibleResult();
+
+ try {
+ HttpGet getObj = new HttpGet(agentUrl);
+ HttpResponse response = httpClient.execute(getObj, httpContext);
+
+ HttpEntity entity = response.getEntity();
+ String responseOutput = entity != null ? EntityUtils.toString(entity) : null;
+ int responseCode = response.getStatusLine().getStatusCode();
+ result.setStatusCode(responseCode);
+ result.setStatusMessage(responseOutput);
+ } catch (IOException io) {
+ result.setStatusCode(AnsibleResultCodes.IO_EXCEPTION.getValue());
+ result.setStatusMessage(io.getMessage());
+ logger.error("Caught IOException", io);
+ }
+ return result;
+ }
+}
diff --git a/adaptors/ansible-adapter/ansible-adapter-bundle/src/main/java/org/onap/ccsdk/sli/adaptors/ansible/model/AnsibleMessageParser.java b/adaptors/ansible-adapter/ansible-adapter-bundle/src/main/java/org/onap/ccsdk/sli/adaptors/ansible/model/AnsibleMessageParser.java
new file mode 100644
index 000000000..5f6342d94
--- /dev/null
+++ b/adaptors/ansible-adapter/ansible-adapter-bundle/src/main/java/org/onap/ccsdk/sli/adaptors/ansible/model/AnsibleMessageParser.java
@@ -0,0 +1,332 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : APPC
+ * ================================================================================
+ * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Copyright (C) 2017 Amdocs
+ * =============================================================================
+ * Modifications Copyright (C) 2018 IBM.
+ * ================================================================================
+ * 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.
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.ansible.model;
+
+/**
+ * This module implements the APP-C/Ansible Server interface
+ * based on the REST API specifications
+ */
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import com.google.common.base.Strings;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Class that validates and constructs requests sent/received from
+ * Ansible Server
+ */
+public class AnsibleMessageParser {
+
+ private static final String STATUS_MESSAGE_KEY = "StatusMessage";
+ private static final String STATUS_CODE_KEY = "StatusCode";
+
+ private static final String PLAYBOOK_NAME_KEY = "PlaybookName";
+ private static final String AGENT_URL_KEY = "AgentUrl";
+ private static final String PASS_KEY = "Password";
+ private static final String USER_KEY = "User";
+ private static final String ID_KEY = "Id";
+
+ private static final String LOCAL_PARAMETERS_OPT_KEY = "LocalParameters";
+ private static final String FILE_PARAMETERS_OPT_KEY = "FileParameters";
+ private static final String ENV_PARAMETERS_OPT_KEY = "EnvParameters";
+ private static final String NODE_LIST_OPT_KEY = "NodeList";
+ private static final String TIMEOUT_OPT_KEY = "Timeout";
+ private static final String VERSION_OPT_KEY = "Version";
+ private static final String ACTION_OPT_KEY = "Action";
+
+ private String jsonException = "JSON exception";
+ private static final Logger LOGGER = LoggerFactory.getLogger(AnsibleMessageParser.class);
+
+ /**
+ * Accepts a map of strings and
+ * a) validates if all parameters are appropriate (else, throws an exception) and
+ * b) if correct returns a JSON object with appropriate key-value pairs to send to the server.
+ *
+ * Mandatory parameters, that must be in the supplied information to the Ansible Adapter
+ * 1. URL to connect to
+ * 2. credentials for URL (assume username password for now)
+ * 3. Playbook name
+ *
+ */
+ public JSONObject reqMessage(Map<String, String> params) throws SvcLogicException {
+ final String[] mandatoryTestParams = {AGENT_URL_KEY, PLAYBOOK_NAME_KEY, USER_KEY, PASS_KEY};
+ final String[] optionalTestParams = {ENV_PARAMETERS_OPT_KEY, NODE_LIST_OPT_KEY, LOCAL_PARAMETERS_OPT_KEY,
+ TIMEOUT_OPT_KEY, VERSION_OPT_KEY, FILE_PARAMETERS_OPT_KEY, ACTION_OPT_KEY};
+
+ JSONObject jsonPayload = new JSONObject();
+
+ for (String key : mandatoryTestParams) {
+ throwIfMissingMandatoryParam(params, key);
+ jsonPayload.put(key, params.get(key));
+ }
+
+ parseOptionalParams(params, optionalTestParams, jsonPayload);
+
+ // Generate a unique uuid for the test
+ String reqId = UUID.randomUUID().toString();
+ jsonPayload.put(ID_KEY, reqId);
+
+ return jsonPayload;
+ }
+
+ /**
+ * Method that validates that the Map has enough information
+ * to query Ansible server for a result. If so, it returns
+ * the appropriate url, else an empty string.
+ */
+ public String reqUriResult(Map<String, String> params) throws SvcLogicException {
+
+ final String[] mandatoryTestParams = {AGENT_URL_KEY, ID_KEY, USER_KEY, PASS_KEY};
+
+ for (String key : mandatoryTestParams) {
+ throwIfMissingMandatoryParam(params, key);
+ }
+ return params.get(AGENT_URL_KEY) + "?Id=" + params.get(ID_KEY) + "&Type=GetResult";
+ }
+
+ /**
+ * Method that validates that the Map has enough information
+ * to query Ansible server for logs. If so, it populates the appropriate
+ * returns the appropriate url, else an empty string.
+ */
+ public String reqUriLog(Map<String, String> params) throws SvcLogicException {
+
+ final String[] mandatoryTestParams = {AGENT_URL_KEY, ID_KEY, USER_KEY, PASS_KEY};
+
+ for (String mandatoryParam : mandatoryTestParams) {
+ throwIfMissingMandatoryParam(params, mandatoryParam);
+ }
+ return params.get(AGENT_URL_KEY) + "?Id=" + params.get(ID_KEY) + "&Type=GetLog";
+ }
+
+ /**
+ * Method that validates that the Map has enough information
+ * to query Ansible server for an output. If so, it returns
+ * the appropriate url, else an empty string.
+ */
+ public String reqUriOutput(Map<String, String> params) throws SvcLogicException {
+
+ final String[] mandatoryTestParams = {AGENT_URL_KEY, ID_KEY, USER_KEY, PASS_KEY};
+
+ for (String mandatoryParam : mandatoryTestParams) {
+ throwIfMissingMandatoryParam(params, mandatoryParam);
+ }
+ return params.get(AGENT_URL_KEY) + "?Id=" + params.get(ID_KEY) + "&Type=GetOutput";
+ }
+
+ /**
+ * This method parses response from the Ansible Server when we do a post
+ * and returns an AnsibleResult object.
+ */
+ public AnsibleResult parsePostResponse(String input) throws SvcLogicException {
+ AnsibleResult ansibleResult;
+ try {
+ JSONObject postResponse = new JSONObject(input);
+
+ int code = postResponse.getInt(STATUS_CODE_KEY);
+ String msg = postResponse.getString(STATUS_MESSAGE_KEY);
+
+ int initResponseValue = AnsibleResultCodes.INITRESPONSE.getValue();
+ boolean validCode = AnsibleResultCodes.CODE.checkValidCode(initResponseValue, code);
+ if (!validCode) {
+ throw new SvcLogicException("Invalid InitResponse code = " + code + " received. MUST be one of "
+ + AnsibleResultCodes.CODE.getValidCodes(initResponseValue));
+ }
+
+ ansibleResult = new AnsibleResult(code, msg);
+
+ } catch (JSONException e) {
+ LOGGER.error(jsonException, e);
+ ansibleResult = new AnsibleResult(600, "Error parsing response = " + input + ". Error = " + e.getMessage());
+ }
+ return ansibleResult;
+ }
+
+ /**
+ * This method parses response from an Ansible server when we do a GET for a result
+ * and returns an AnsibleResult object.
+ **/
+ public AnsibleResult parseGetResponse(String input) throws SvcLogicException {
+
+ AnsibleResult ansibleResult = new AnsibleResult();
+
+ try {
+ JSONObject postResponse = new JSONObject(input);
+ ansibleResult = parseGetResponseNested(ansibleResult, postResponse);
+ } catch (JSONException e) {
+ LOGGER.error(jsonException, e);
+ ansibleResult = new AnsibleResult(AnsibleResultCodes.INVALID_PAYLOAD.getValue(),
+ "Error parsing response = " + input + ". Error = " + e.getMessage(), "");
+ }
+ return ansibleResult;
+ }
+
+ private AnsibleResult parseGetResponseNested(AnsibleResult ansibleResult, JSONObject postRsp) throws SvcLogicException {
+
+ int codeStatus = postRsp.getInt(STATUS_CODE_KEY);
+ String messageStatus = postRsp.getString(STATUS_MESSAGE_KEY);
+ int finalCode = AnsibleResultCodes.FINAL_SUCCESS.getValue();
+
+ boolean valCode =
+ AnsibleResultCodes.CODE.checkValidCode(AnsibleResultCodes.FINALRESPONSE.getValue(), codeStatus);
+
+ if (!valCode) {
+ throw new SvcLogicException("Invalid FinalResponse code = " + codeStatus + " received. MUST be one of "
+ + AnsibleResultCodes.CODE.getValidCodes(AnsibleResultCodes.FINALRESPONSE.getValue()));
+ }
+
+ ansibleResult.setStatusCode(codeStatus);
+ ansibleResult.setStatusMessage(messageStatus);
+ LOGGER.info("Received response with code = {}, Message = {}", codeStatus, messageStatus);
+
+ if (!postRsp.isNull("Results")) {
+
+ // Results are available. process them
+ // Results is a dictionary of the form
+
+ LOGGER.info("Processing results in response");
+ JSONObject results = postRsp.getJSONObject("Results");
+ LOGGER.info("Get JSON dictionary from Results ..");
+ Iterator<String> hosts = results.keys();
+ LOGGER.info("Iterating through hosts");
+
+ while (hosts.hasNext()) {
+ String host = hosts.next();
+ LOGGER.info("Processing host = {}", host);
+
+ try {
+ JSONObject hostResponse = results.getJSONObject(host);
+ int subCode = hostResponse.getInt(STATUS_CODE_KEY);
+ String message = hostResponse.getString(STATUS_MESSAGE_KEY);
+
+ LOGGER.info("Code = {}, Message = {}", subCode, message);
+
+ if (subCode != 200 || !("SUCCESS").equals(message)) {
+ finalCode = AnsibleResultCodes.REQ_FAILURE.getValue();
+ }
+ } catch (JSONException e) {
+ LOGGER.error(jsonException, e);
+ ansibleResult.setStatusCode(AnsibleResultCodes.INVALID_RESPONSE.getValue());
+ ansibleResult.setStatusMessage(String.format(
+ "Error processing response message = %s from host %s", results.getString(host), host));
+ break;
+ }
+ }
+
+ ansibleResult.setStatusCode(finalCode);
+
+ // We return entire Results object as message
+ ansibleResult.setResults(results.toString());
+
+ } else {
+ ansibleResult.setStatusCode(AnsibleResultCodes.INVALID_RESPONSE.getValue());
+ ansibleResult.setStatusMessage("Results not found in GET for response");
+ }
+ return ansibleResult;
+ }
+
+ private void parseOptionalParams(Map<String, String> params, String[] optionalTestParams, JSONObject jsonPayload) {
+
+ Set<String> optionalParamsSet = new HashSet<>();
+ Collections.addAll(optionalParamsSet, optionalTestParams);
+
+ //@formatter:off
+ params.entrySet()
+ .stream()
+ .filter(entry -> optionalParamsSet.contains(entry.getKey()))
+ .filter(entry -> !Strings.isNullOrEmpty(entry.getValue()))
+ .forEach(entry -> parseOptionalParam(entry, jsonPayload));
+ //@formatter:on
+ }
+
+ private void parseOptionalParam(Map.Entry<String, String> params, JSONObject jsonPayload) {
+ String key = params.getKey();
+ String payload = params.getValue();
+
+ switch (key) {
+ case TIMEOUT_OPT_KEY:
+ int timeout = Integer.parseInt(payload);
+ if (timeout < 0) {
+ throw new NumberFormatException(" : specified negative integer for timeout = " + payload);
+ }
+ jsonPayload.put(key, payload);
+ break;
+
+ case VERSION_OPT_KEY:
+ jsonPayload.put(key, payload);
+ break;
+
+ case LOCAL_PARAMETERS_OPT_KEY:
+ case ENV_PARAMETERS_OPT_KEY:
+ JSONObject paramsJson = new JSONObject(payload);
+ jsonPayload.put(key, paramsJson);
+ break;
+
+ case NODE_LIST_OPT_KEY:
+ JSONArray paramsArray = new JSONArray(payload);
+ jsonPayload.put(key, paramsArray);
+ break;
+
+ case FILE_PARAMETERS_OPT_KEY:
+ jsonPayload.put(key, getFilePayload(payload));
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ /**
+ * Return payload with escaped newlines
+ */
+ private JSONObject getFilePayload(String payload) {
+ String formattedPayload = payload.replace("\n", "\\n").replace("\r", "\\r");
+ return new JSONObject(formattedPayload);
+ }
+
+ private void throwIfMissingMandatoryParam(Map<String, String> params, String key) throws SvcLogicException {
+ if (!params.containsKey(key)) {
+ throw new SvcLogicException(String.format(
+ "Ansible: Mandatory AnsibleAdapter key %s not found in parameters provided by calling agent !",
+ key));
+ }
+ if (Strings.isNullOrEmpty(params.get(key))) {
+ throw new SvcLogicException(String.format(
+ "Ansible: Mandatory AnsibleAdapter key %s not found in parameters provided by calling agent !",
+ key));
+ }
+ }
+}
diff --git a/adaptors/ansible-adapter/ansible-adapter-bundle/src/main/java/org/onap/ccsdk/sli/adaptors/ansible/model/AnsibleResult.java b/adaptors/ansible-adapter/ansible-adapter-bundle/src/main/java/org/onap/ccsdk/sli/adaptors/ansible/model/AnsibleResult.java
new file mode 100644
index 000000000..3d1b3cfab
--- /dev/null
+++ b/adaptors/ansible-adapter/ansible-adapter-bundle/src/main/java/org/onap/ccsdk/sli/adaptors/ansible/model/AnsibleResult.java
@@ -0,0 +1,81 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : APPC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Copyright (C) 2017 Amdocs
+ * =============================================================================
+ * 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.
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.ansible.model;
+
+/**
+ * Simple class to store code and message returned by POST/GET to an Ansible Server
+ */
+public class AnsibleResult {
+
+ private static final String EMPTY_VALUE = "UNKNOWN";
+
+ private int statusCode;
+ private String statusMessage;
+ private String results;
+
+ public AnsibleResult() {
+ this(-1, EMPTY_VALUE, EMPTY_VALUE);
+ }
+
+ public AnsibleResult(int code, String message) {
+ this(code, message, EMPTY_VALUE);
+ }
+
+ public AnsibleResult(int code, String message, String result) {
+ statusCode = code;
+ statusMessage = message;
+ results = result;
+ }
+
+ public void setStatusCode(int code) {
+ this.statusCode = code;
+ }
+
+ public void setStatusMessage(String message) {
+ this.statusMessage = message;
+ }
+
+ public void setResults(String results) {
+ this.results = results;
+ }
+
+ void set(int code, String message, String results) {
+ this.statusCode = code;
+ this.statusMessage = message;
+ this.results = results;
+ }
+
+ public int getStatusCode() {
+ return this.statusCode;
+ }
+
+ public String getStatusMessage() {
+ return this.statusMessage;
+ }
+
+ public String getResults() {
+ return this.results;
+ }
+}
diff --git a/adaptors/ansible-adapter/ansible-adapter-bundle/src/main/java/org/onap/ccsdk/sli/adaptors/ansible/model/AnsibleResultCodes.java b/adaptors/ansible-adapter/ansible-adapter-bundle/src/main/java/org/onap/ccsdk/sli/adaptors/ansible/model/AnsibleResultCodes.java
new file mode 100644
index 000000000..a529e4a0c
--- /dev/null
+++ b/adaptors/ansible-adapter/ansible-adapter-bundle/src/main/java/org/onap/ccsdk/sli/adaptors/ansible/model/AnsibleResultCodes.java
@@ -0,0 +1,93 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : APPC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Copyright (C) 2017 Amdocs
+ * =============================================================================
+ * 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.
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.ansible.model;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * enum of the various codes that APP-C uses to resolve different
+ * status of response from Ansible Server
+ **/
+
+public enum AnsibleResultCodes {
+
+ // @formatter:off
+ SUCCESS(400),
+ KEYSTORE_EXCEPTION(622),
+ CERTIFICATE_ERROR(610),
+ IO_EXCEPTION(611),
+ HOST_UNKNOWN(625),
+ USER_UNAUTHORIZED(613),
+ UNKNOWN_EXCEPTION(699),
+ SSL_EXCEPTION(697),
+ INVALID_PAYLOAD(698),
+ INVALID_RESPONSE(601),
+ PENDING(100),
+ REJECTED(101),
+ FINAL_SUCCESS(200),
+ REQ_FAILURE(401),
+ MESSAGE(1),
+ CODE(0),
+ INITRESPONSE(0),
+ FINALRESPONSE(1);
+ // @formatter:on
+
+ private final Set<Integer> initCodes = new HashSet<>(Arrays.asList(100, 101));
+ private final Set<Integer> finalCodes = new HashSet<>(Arrays.asList(200, 500));
+ private final ArrayList<Set<Integer>> codeSets = new ArrayList<>(Arrays.asList(initCodes, finalCodes));
+ private final Set<String> messageSet = new HashSet<>(Arrays.asList("PENDING", "FINISHED", "TERMINATED"));
+ private final int value;
+
+ AnsibleResultCodes(int value) {
+ this.value = value;
+ };
+
+ public int getValue() {
+ return value;
+ }
+
+ public boolean checkValidCode(int type, int code) {
+ return codeSets.get(type).contains(code);
+ }
+
+ public String getValidCodes(int type) {
+ StringBuilder sb = new StringBuilder("[ ");
+ codeSets.get(type).stream().forEach(s -> sb.append(s).append(","));
+ return sb.append("]").toString();
+ }
+
+ public boolean checkValidMessage(String message) {
+ return messageSet.contains(message);
+ }
+
+ public String getValidMessages() {
+ StringBuilder sb = new StringBuilder("[ ");
+ messageSet.stream().forEach(s -> sb.append(s).append(","));
+ return sb.append("]").toString();
+ }
+}
diff --git a/adaptors/ansible-adapter/ansible-adapter-bundle/src/main/java/org/onap/ccsdk/sli/adaptors/ansible/model/AnsibleServerEmulator.java b/adaptors/ansible-adapter/ansible-adapter-bundle/src/main/java/org/onap/ccsdk/sli/adaptors/ansible/model/AnsibleServerEmulator.java
new file mode 100644
index 000000000..993c70062
--- /dev/null
+++ b/adaptors/ansible-adapter/ansible-adapter-bundle/src/main/java/org/onap/ccsdk/sli/adaptors/ansible/model/AnsibleServerEmulator.java
@@ -0,0 +1,137 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : APPC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Copyright (C) 2017 Amdocs
+ * =============================================================================
+ * 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.
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * ============LICENSE_END=========================================================
+ */
+
+
+
+/*
+ * Class to emulate responses from the Ansible Server that is compliant with the APP-C Ansible Server
+ * Interface. Used for jUnit tests to verify code is working. In tests it can be used
+ * as a replacement for methods from ConnectionBuilder class
+ */
+
+package org.onap.ccsdk.sli.adaptors.ansible.model;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import org.apache.commons.lang.StringUtils;
+import org.json.JSONException;
+import org.json.JSONObject;
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+
+public class AnsibleServerEmulator {
+
+ private final EELFLogger logger = EELFManager.getInstance().getLogger(AnsibleServerEmulator.class);
+
+ private static final String PLAYBOOK_NAME = "PlaybookName";
+ private static final String STATUS_CODE = "StatusCode";
+ private static final String STATUS_MESSAGE = "StatusMessage";
+
+ private String playbookName = "test_playbook.yaml";
+
+ /**
+ * Method that emulates the response from an Ansible Server
+ * when presented with a request to execute a playbook
+ * Returns an ansible object result. The response code is always the http code 200 (i.e connection successful)
+ * payload is json string as would be sent back by Ansible Server
+ **/
+ public AnsibleResult Post(String agentUrl, String payload) {
+ AnsibleResult result = new AnsibleResult();
+
+ try {
+ // Request must be a JSON object
+
+ JSONObject message = new JSONObject(payload);
+ if (message.isNull("Id")) {
+ rejectRequest(result, "Must provide a valid Id");
+ } else if (message.isNull(PLAYBOOK_NAME)) {
+ rejectRequest(result, "Must provide a playbook Name");
+ } else if (!message.getString(PLAYBOOK_NAME).equals(playbookName)) {
+ rejectRequest(result, "Playbook " + message.getString(PLAYBOOK_NAME) + " not found in catalog");
+ } else {
+ acceptRequest(result);
+ }
+ } catch (JSONException e) {
+ logger.error("JSONException caught", e);
+ rejectRequest(result, e.getMessage());
+ }
+ return result;
+ }
+
+ /**
+ * Method to emulate response from an Ansible
+ * Server when presented with a GET request
+ * Returns an ansibl object result. The response code is always the http code 200 (i.e connection successful)
+ * payload is json string as would be sent back by Ansible Server
+ *
+ **/
+ public AnsibleResult Get(String agentUrl) {
+
+ Pattern pattern = Pattern.compile(".*?\\?Id=(.*?)&Type.*");
+ Matcher matcher = pattern.matcher(agentUrl);
+ String id = StringUtils.EMPTY;
+ String vmAddress = "192.168.1.10";
+
+ if (matcher.find()) {
+ id = matcher.group(1);
+ }
+
+ AnsibleResult getResult = new AnsibleResult();
+
+ JSONObject response = new JSONObject();
+ response.put(STATUS_CODE, 200);
+ response.put(STATUS_MESSAGE, "FINISHED");
+
+ JSONObject results = new JSONObject();
+
+ JSONObject vmResults = new JSONObject();
+ vmResults.put(STATUS_CODE, 200);
+ vmResults.put(STATUS_MESSAGE, "SUCCESS");
+ vmResults.put("Id", id);
+ results.put(vmAddress, vmResults);
+
+ response.put("Results", results);
+
+ getResult.setStatusCode(200);
+ getResult.setStatusMessage(response.toString());
+
+ return getResult;
+ }
+
+ private void rejectRequest(AnsibleResult result, String Message) {
+ result.setStatusCode(200);
+ JSONObject response = new JSONObject();
+ response.put(STATUS_CODE, AnsibleResultCodes.REJECTED.getValue());
+ response.put(STATUS_MESSAGE, Message);
+ result.setStatusMessage(response.toString());
+ }
+
+ private void acceptRequest(AnsibleResult result) {
+ result.setStatusCode(200);
+ JSONObject response = new JSONObject();
+ response.put(STATUS_CODE, AnsibleResultCodes.PENDING.getValue());
+ response.put(STATUS_MESSAGE, "PENDING");
+ result.setStatusMessage(response.toString());
+ }
+} \ No newline at end of file
diff --git a/adaptors/ansible-adapter/ansible-adapter-bundle/src/main/resources/OSGI-INF/blueprint/ansible-adapter-blueprint.xml b/adaptors/ansible-adapter/ansible-adapter-bundle/src/main/resources/OSGI-INF/blueprint/ansible-adapter-blueprint.xml
new file mode 100755
index 000000000..d7be01e9d
--- /dev/null
+++ b/adaptors/ansible-adapter/ansible-adapter-bundle/src/main/resources/OSGI-INF/blueprint/ansible-adapter-blueprint.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ============LICENSE_START=======================================================
+ openECOMP : SDN-C
+ ================================================================================
+ Copyright (C) 2017 - 2018 AT&T Intellectual Property. All rights
+ reserved.
+ ================================================================================
+ 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.
+ ============LICENSE_END=========================================================
+ -->
+
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+ xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0"
+ odl:use-default-for-reference-types="true">
+
+ <bean id="propProvider" class="org.onap.ccsdk.sli.adaptors.ansible.impl.AnsibleAdapterPropertiesProviderImpl" />
+
+ <bean id="ansibleAdapterInstance" class="org.onap.ccsdk.sli.adaptors.ansible.impl.AnsibleAdapterImpl">
+ <argument ref="propProvider"/>
+ </bean>
+
+ <service ref="ansibleAdapterInstance">
+ <interfaces>
+ <value>org.onap.ccsdk.sli.adaptors.ansible.AnsibleAdapter</value>
+ </interfaces>
+ </service>
+
+</blueprint>
diff --git a/adaptors/ansible-adapter/ansible-adapter-bundle/src/main/resources/ansible-adapter.properties b/adaptors/ansible-adapter/ansible-adapter-bundle/src/main/resources/ansible-adapter.properties
new file mode 100644
index 000000000..761758bbb
--- /dev/null
+++ b/adaptors/ansible-adapter/ansible-adapter-bundle/src/main/resources/ansible-adapter.properties
@@ -0,0 +1,48 @@
+###
+# ============LICENSE_START=======================================================
+# ONAP : APPC
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+# ================================================================================
+# Copyright (C) 2017 Amdocs
+# =============================================================================
+# 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.
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+# ============LICENSE_END=========================================================
+###
+
+#
+# Default properties for the APP-C TestService Adapter
+#
+# -------------------------------------------------------------------------------------------------
+#
+# Define the name and path of any user-provided configuration (bootstrap) file that can be loaded
+# to supply configuration options
+org.onap.appc.bootstrap.file=appc.properties
+org.onap.appc.bootstrap.path=${user.home},/opt/opendaylight/current/properties
+
+appc.application.name=APPC
+
+#
+# Define the message resource bundle name to be loaded
+org.onap.appc.resources=org.onap/appc/i18n/MessageResources
+#
+# The name of the adapter.
+org.onap.appc.provider.adaptor.name=org.onap.appc.appc_ansible_adapter
+
+
+# Default truststore path and password
+org.onap.appc.adapter.ansible.trustStore=/opt/opendaylight/tls-client/mykeystore.js
+org.onap.appc.adapter.ansible.trustStore.trustPasswd=changeit
+org.onap.appc.adapter.ansible.clientType=TRUST_ALL
diff --git a/adaptors/ansible-adapter/ansible-adapter-bundle/src/main/resources/org/opendaylight/blueprint/ansible-adapter-blueprint.xml b/adaptors/ansible-adapter/ansible-adapter-bundle/src/main/resources/org/opendaylight/blueprint/ansible-adapter-blueprint.xml
new file mode 100755
index 000000000..d7be01e9d
--- /dev/null
+++ b/adaptors/ansible-adapter/ansible-adapter-bundle/src/main/resources/org/opendaylight/blueprint/ansible-adapter-blueprint.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ============LICENSE_START=======================================================
+ openECOMP : SDN-C
+ ================================================================================
+ Copyright (C) 2017 - 2018 AT&T Intellectual Property. All rights
+ reserved.
+ ================================================================================
+ 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.
+ ============LICENSE_END=========================================================
+ -->
+
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+ xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0"
+ odl:use-default-for-reference-types="true">
+
+ <bean id="propProvider" class="org.onap.ccsdk.sli.adaptors.ansible.impl.AnsibleAdapterPropertiesProviderImpl" />
+
+ <bean id="ansibleAdapterInstance" class="org.onap.ccsdk.sli.adaptors.ansible.impl.AnsibleAdapterImpl">
+ <argument ref="propProvider"/>
+ </bean>
+
+ <service ref="ansibleAdapterInstance">
+ <interfaces>
+ <value>org.onap.ccsdk.sli.adaptors.ansible.AnsibleAdapter</value>
+ </interfaces>
+ </service>
+
+</blueprint>
diff --git a/adaptors/ansible-adapter/ansible-adapter-bundle/src/test/java/org/onap/ccsdk/adapter/ansible/impl/TestAnsibleAdapterImpl.java b/adaptors/ansible-adapter/ansible-adapter-bundle/src/test/java/org/onap/ccsdk/adapter/ansible/impl/TestAnsibleAdapterImpl.java
new file mode 100644
index 000000000..4636d2450
--- /dev/null
+++ b/adaptors/ansible-adapter/ansible-adapter-bundle/src/test/java/org/onap/ccsdk/adapter/ansible/impl/TestAnsibleAdapterImpl.java
@@ -0,0 +1,147 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : APPC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Copyright (C) 2017 Amdocs
+ * =============================================================================
+ * 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.
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.adapter.ansible.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.onap.ccsdk.sli.adaptors.ansible.impl.AnsibleAdapterImpl;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+
+
+public class TestAnsibleAdapterImpl {
+
+ private final String PENDING = "100";
+ private final String SUCCESS = "400";
+ private String message = "{\"Results\":{\"192.168.1.10\":{\"Id\":\"101\",\"StatusCode\":200,\"StatusMessage\":\"SUCCESS\"}},\"StatusCode\":200,\"StatusMessage\":\"FINISHED\"}";
+
+ private AnsibleAdapterImpl adapter;
+ private String TestId;
+ private boolean testMode = true;
+ private Map<String, String> params;
+ private SvcLogicContext svcContext;
+
+
+ @Before
+ public void setup() throws IllegalArgumentException {
+ testMode = true;
+ svcContext = new SvcLogicContext();
+ adapter = new AnsibleAdapterImpl(testMode);
+
+ params = new HashMap<>();
+ params.put("AgentUrl", "https://192.168.1.1");
+ params.put("User", "test");
+ params.put("Password", "test");
+ }
+
+ @After
+ public void tearDown() {
+ testMode = false;
+ adapter = null;
+ params = null;
+ svcContext = null;
+ }
+
+ @Test
+ public void reqExec_shouldSetPending() throws IllegalStateException, IllegalArgumentException {
+
+ params.put("PlaybookName", "test_playbook.yaml");
+
+ try {
+ adapter.reqExec(params, svcContext);
+ String status = svcContext.getAttribute("org.onap.appc.adapter.ansible.result.code");
+ TestId = svcContext.getAttribute("org.onap.appc.adapter.ansible.result.Id");
+ System.out.println("Comparing " + PENDING + " and " + status);
+ assertEquals(PENDING, status);
+ } catch (SvcLogicException e) {
+ String status = svcContext.getAttribute("org.onap.appc.adapter.ansible.result.code");
+ fail(e.getMessage() + " Code = " + status);
+ } catch (Exception e) {
+ fail(e.getMessage() + " Unknown exception encountered ");
+ }
+ }
+
+ @Test
+ public void reqExecResult_shouldSetSuccess() throws IllegalStateException, IllegalArgumentException {
+
+ params.put("Id", "100");
+
+ for (String ukey : params.keySet()) {
+ System.out.println(String.format("Ansible Parameter %s = %s", ukey, params.get(ukey)));
+ }
+
+ try {
+ adapter.reqExecResult(params, svcContext);
+ String status = svcContext.getAttribute("org.onap.appc.adapter.ansible.result.code");
+ assertEquals(SUCCESS, status);
+ } catch (SvcLogicException e) {
+ String status = svcContext.getAttribute("org.onap.appc.adapter.ansible.result.code");
+ fail(e.getMessage() + " Code = " + status);
+ } catch (Exception e) {
+ fail(e.getMessage() + " Unknown exception encountered ");
+ }
+ }
+
+ @Test
+ public void reqExecLog_shouldSetMessage() throws IllegalStateException, IllegalArgumentException {
+
+ params.put("Id", "101");
+
+ try {
+ adapter.reqExecLog(params, svcContext);
+ String status = svcContext.getAttribute("org.onap.appc.adapter.ansible.log");
+ assertEquals(message, status);
+ } catch (SvcLogicException e) {
+ String status = svcContext.getAttribute("org.onap.appc.adapter.ansible.log");
+ fail(e.getMessage() + " Code = " + status);
+ } catch (Exception e) {
+ fail(e.getMessage() + " Unknown exception encountered ");
+ }
+ }
+
+ @Test
+ public void reqExecOutput_shouldSetMessage() throws IllegalStateException, IllegalArgumentException {
+
+ params.put("Id", "101");
+
+ try {
+ adapter.reqExecOutput(params, svcContext);
+ String status = svcContext.getAttribute("org.onap.appc.adapter.ansible.output");
+ assertEquals(message, status);
+ } catch (SvcLogicException e) {
+ String status = svcContext.getAttribute("org.onap.appc.adapter.ansible.output");
+ fail(e.getMessage() + " Code = " + status);
+ } catch (Exception e) {
+ fail(e.getMessage() + " Unknown exception encountered ");
+ }
+ }
+}
diff --git a/adaptors/ansible-adapter/ansible-adapter-bundle/src/test/java/org/onap/ccsdk/adapter/ansible/impl/TestAnsibleAdapterPropertiesProviderImpl.java b/adaptors/ansible-adapter/ansible-adapter-bundle/src/test/java/org/onap/ccsdk/adapter/ansible/impl/TestAnsibleAdapterPropertiesProviderImpl.java
new file mode 100644
index 000000000..b3c01e9bd
--- /dev/null
+++ b/adaptors/ansible-adapter/ansible-adapter-bundle/src/test/java/org/onap/ccsdk/adapter/ansible/impl/TestAnsibleAdapterPropertiesProviderImpl.java
@@ -0,0 +1,53 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * onap
+ * ================================================================================
+ * Copyright (C) 2018 Samsung
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.adapter.ansible.impl;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.onap.ccsdk.sli.adaptors.ansible.impl.AnsibleAdapterPropertiesProviderImpl;
+
+import java.util.Properties;
+
+import static org.junit.Assert.assertEquals;
+
+public class TestAnsibleAdapterPropertiesProviderImpl {
+ AnsibleAdapterPropertiesProviderImpl adaptor;
+ @Before
+ public void setup() throws IllegalArgumentException {
+ adaptor = new AnsibleAdapterPropertiesProviderImpl();
+ }
+
+
+ @Test
+ public void testGetProperties() throws IllegalStateException, IllegalArgumentException {
+ Properties prop = adaptor.getProperties();
+
+ System.out.println("All Property params : " + prop);
+ assertEquals("TRUST_ALL", prop.getProperty("org.onap.appc.adapter.ansible.clientType"));
+ assertEquals("org.onap.appc.appc_ansible_adapter", prop.getProperty("org.onap.appc.provider.adaptor.name"));
+ assertEquals("changeit", prop.getProperty("org.onap.appc.adapter.ansible.trustStore.trustPasswd"));
+ assertEquals("${user.home},/opt/opendaylight/current/properties", prop.getProperty("org.onap.appc.bootstrap.path"));
+ assertEquals("APPC", prop.getProperty("appc.application.name"));
+ assertEquals("appc.properties", prop.getProperty("org.onap.appc.bootstrap.file"));
+ assertEquals("org.onap/appc/i18n/MessageResources", prop.getProperty("org.onap.appc.resources"));
+ assertEquals("/opt/opendaylight/tls-client/mykeystore.js", prop.getProperty("org.onap.appc.adapter.ansible.trustStore"));
+ }
+}
diff --git a/adaptors/ansible-adapter/ansible-adapter-bundle/src/test/java/org/onap/ccsdk/adapter/ansible/impl/TestConnectionBuilder.java b/adaptors/ansible-adapter/ansible-adapter-bundle/src/test/java/org/onap/ccsdk/adapter/ansible/impl/TestConnectionBuilder.java
new file mode 100644
index 000000000..c94655f56
--- /dev/null
+++ b/adaptors/ansible-adapter/ansible-adapter-bundle/src/test/java/org/onap/ccsdk/adapter/ansible/impl/TestConnectionBuilder.java
@@ -0,0 +1,155 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * onap
+ * ================================================================================
+ * Copyright (C) 2018 Samsung
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.adapter.ansible.impl;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.onap.ccsdk.sli.adaptors.ansible.impl.ConnectionBuilder;
+import org.onap.ccsdk.sli.adaptors.ansible.model.AnsibleResult;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+
+import javax.net.ssl.SSLException;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.security.KeyManagementException;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateException;
+
+import static org.junit.Assert.assertEquals;
+
+public class TestConnectionBuilder {
+ ConnectionBuilder builder;
+ @Before
+ public void setup()
+ throws SSLException, NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
+ builder = new ConnectionBuilder(1);
+ }
+
+
+ @Test
+ public void testSetHttpContext() throws IllegalStateException, IllegalArgumentException {
+ String user = "testUser";
+ String pass = "testPassword";
+
+ builder.setHttpContext(user, pass);
+ }
+
+ @Test
+ public void testPost() throws IllegalStateException, IllegalArgumentException {
+ String user = "testUser";
+ String pass = "testPassword";
+ String agentUrl = "test/server.com";
+ String payload = "testPayload";
+
+ builder.setHttpContext(user, pass);
+ AnsibleResult result = builder.post(agentUrl, payload);
+
+ assertEquals(611, result.getStatusCode());
+ assertEquals(null, result.getStatusMessage());
+ assertEquals("UNKNOWN", result.getResults());
+ }
+
+ @Test
+ public void testGet() throws IllegalStateException, IllegalArgumentException {
+ String user = "testUser";
+ String pass = "testPassword";
+ String agentUrl = "test/server.com";
+
+ builder.setHttpContext(user, pass);
+ AnsibleResult result = builder.get(agentUrl);
+
+ assertEquals(611, result.getStatusCode());
+ assertEquals(null, result.getStatusMessage());
+ assertEquals("UNKNOWN", result.getResults());
+ }
+
+ @Test
+ public void testGetMode()
+ throws SSLException, NoSuchAlgorithmException, KeyStoreException, KeyManagementException {
+ String user = "testUser";
+ String pass = "testPassword";
+ String agentUrl = "test/server.com";
+
+ builder = new ConnectionBuilder(2);
+ builder.setHttpContext(user, pass);
+ AnsibleResult result = builder.get(agentUrl);
+
+ assertEquals(611, result.getStatusCode());
+ assertEquals(null, result.getStatusMessage());
+ assertEquals("UNKNOWN", result.getResults());
+ }
+
+ @Test (expected = FileNotFoundException.class)
+ public void testGetModeNoCert()
+ throws KeyStoreException, CertificateException, IOException,
+ KeyManagementException, NoSuchAlgorithmException, SvcLogicException {
+ String user = "testUser";
+ String pass = "testPassword";
+ String agentUrl = "test/server.com";
+ String certFile = "testCert";
+
+ builder = new ConnectionBuilder(certFile);
+ builder.setHttpContext(user, pass);
+ AnsibleResult result = builder.get(agentUrl);
+
+ assertEquals(611, result.getStatusCode());
+ assertEquals(null, result.getStatusMessage());
+ assertEquals("UNKNOWN", result.getResults());
+ }
+
+ @Test
+ public void testGetModeCert()
+ throws KeyStoreException, CertificateException, IOException,
+ KeyManagementException, NoSuchAlgorithmException, SvcLogicException {
+ String user = "testUser";
+ String pass = "testPassword";
+ String agentUrl = "test/server.com";
+ String certFile = "src/test/resources/cert";
+
+ builder = new ConnectionBuilder(certFile);
+ builder.setHttpContext(user, pass);
+ AnsibleResult result = builder.get(agentUrl);
+
+ assertEquals(611, result.getStatusCode());
+ assertEquals(null, result.getStatusMessage());
+ assertEquals("UNKNOWN", result.getResults());
+ }
+
+ @Test (expected = IOException.class)
+ public void testGetModeStore()
+ throws KeyStoreException, CertificateException, IOException,
+ KeyManagementException, NoSuchAlgorithmException, SvcLogicException {
+ String user = "testUser";
+ String pass = "testPassword";
+ String agentUrl = "test/server.com";
+ String store = "src/test/resources/cert";
+
+ builder = new ConnectionBuilder(store, new char['t'] );
+ builder.setHttpContext(user, pass);
+ AnsibleResult result = builder.get(agentUrl);
+
+ assertEquals(611, result.getStatusCode());
+ assertEquals(null, result.getStatusMessage());
+ assertEquals("UNKNOWN", result.getResults());
+ }
+
+}
diff --git a/adaptors/ansible-adapter/ansible-adapter-bundle/src/test/java/org/onap/ccsdk/adapter/ansible/model/TestAnsibleAdapter.java b/adaptors/ansible-adapter/ansible-adapter-bundle/src/test/java/org/onap/ccsdk/adapter/ansible/model/TestAnsibleAdapter.java
new file mode 100644
index 000000000..6fc90d012
--- /dev/null
+++ b/adaptors/ansible-adapter/ansible-adapter-bundle/src/test/java/org/onap/ccsdk/adapter/ansible/model/TestAnsibleAdapter.java
@@ -0,0 +1,81 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : APPC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Copyright (C) 2017 Amdocs
+ * =============================================================================
+ * 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.
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.ccsdk.adapter.ansible.model;
+
+import static org.junit.Assert.assertNotNull;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.lang.reflect.*;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.onap.ccsdk.sli.adaptors.ansible.model.AnsibleMessageParser;
+import org.onap.ccsdk.sli.adaptors.ansible.model.AnsibleResult;
+import org.onap.ccsdk.sli.adaptors.ansible.model.AnsibleServerEmulator;
+
+public class TestAnsibleAdapter {
+
+ private Class[] parameterTypes;
+ private AnsibleMessageParser ansibleMessageParser;
+ private Method m;
+ private String name;
+
+ @Test
+ public void callPrivateConstructorsMethodsForCodeCoverage() throws SecurityException, NoSuchMethodException, IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException {
+
+ /* test constructors */
+ Class<?>[] classesOne = {AnsibleMessageParser.class};
+ for(Class<?> clazz : classesOne) {
+ Constructor<?> constructor = clazz.getDeclaredConstructor();
+ name = constructor.getName();
+ constructor.setAccessible(true);
+ assertNotNull(constructor.newInstance());
+ }
+ Class<?>[] classesTwo = {AnsibleServerEmulator.class};
+ for(Class<?> clazz : classesTwo) {
+ Constructor<?> constructor = clazz.getDeclaredConstructor();
+ name = constructor.getName();
+ constructor.setAccessible(true);
+ assertNotNull(constructor.newInstance());
+ }
+ Class<?>[] classesThree = {AnsibleResult.class};
+ for(Class<?> clazz : classesThree) {
+ Constructor<?> constructor = clazz.getDeclaredConstructor();
+ name = constructor.getName();
+ constructor.setAccessible(true);
+ assertNotNull(constructor.newInstance());
+ }
+
+ /* test methods */
+ ansibleMessageParser = new AnsibleMessageParser();
+ parameterTypes = new Class[1];
+ parameterTypes[0] = java.lang.String.class;
+
+ m = ansibleMessageParser.getClass().getDeclaredMethod("getFilePayload", parameterTypes);
+ m.setAccessible(true);
+ assertNotNull(m.invoke(ansibleMessageParser,"{\"test\": test}"));
+
+ }
+}
diff --git a/adaptors/ansible-adapter/ansible-adapter-bundle/src/test/java/org/onap/ccsdk/test/ExecutorHarness.java b/adaptors/ansible-adapter/ansible-adapter-bundle/src/test/java/org/onap/ccsdk/test/ExecutorHarness.java
new file mode 100644
index 000000000..3555d7dfe
--- /dev/null
+++ b/adaptors/ansible-adapter/ansible-adapter-bundle/src/test/java/org/onap/ccsdk/test/ExecutorHarness.java
@@ -0,0 +1,181 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : APPC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Copyright (C) 2017 Amdocs
+ * =============================================================================
+ * 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.
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * ============LICENSE_END=========================================================
+ */
+
+
+package org.onap.ccsdk.test;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicJavaPlugin;
+
+/**
+ * This class is used as a test harness to wrap the call to an executor node.
+ */
+
+public class ExecutorHarness {
+
+ /**
+ * The executor to be tested
+ */
+ private SvcLogicJavaPlugin executor;
+
+ /**
+ * The collection of all exec methods found on the class
+ */
+ private Map<String, Method> methods;
+
+ /**
+ * The field of the class being tested that contains the reference to the logger to be used. This is modified to
+ * point to our interception logger for the test.
+ */
+ private Field contextLogger;
+
+ /**
+ * The interception logger that buffers all messages logged and allows us to look at them as part of the test case.
+ */
+ private InterceptLogger logger;
+
+ /**
+ * Create the harness and initialize it
+ *
+ * @throws SecurityException
+ * If a security manager, s, is present and any of the following conditions is met:
+ * <ul>
+ * <li>invocation of s.checkMemberAccess(this, Member.DECLARED) denies access to the declared field</li>
+ * <li>the caller's class loader is not the same as or an ancestor of the class loader for the current
+ * class and invocation of s.checkPackageAccess() denies access to the package of this class</li>
+ * </ul>
+ * @throws NoSuchFieldException
+ * if a field with the specified name is not found.
+ * @throws IllegalAccessException
+ * if this Field object is enforcing Java language access control and the underlying field is either
+ * inaccessible or final.
+ * @throws IllegalArgumentException
+ * if the specified object is not an instance of the class or interface declaring the underlying field
+ * (or a subclass or implementor thereof), or if an unwrapping conversion fails.
+ */
+ @SuppressWarnings("nls")
+ public ExecutorHarness() throws NoSuchFieldException, SecurityException, IllegalArgumentException,
+ IllegalAccessException {
+ methods = new HashMap<>();
+ new SvcLogicContext();
+
+ Class<?> contextClass = SvcLogicContext.class;
+ contextLogger = contextClass.getDeclaredField("LOG");
+ contextLogger.setAccessible(true);
+ logger = new InterceptLogger();
+ contextLogger.set(null, logger);
+ }
+
+ /**
+ * Convenience constructor
+ *
+ * @param executor
+ * The executor to be tested by the harness
+ * @throws SecurityException
+ * If a security manager, s, is present and any of the following conditions is met:
+ * <ul>
+ * <li>invocation of s.checkMemberAccess(this, Member.DECLARED) denies access to the declared field</li>
+ * <li>the caller's class loader is not the same as or an ancestor of the class loader for the current
+ * class and invocation of s.checkPackageAccess() denies access to the package of this class</li>
+ * </ul>
+ * @throws NoSuchFieldException
+ * if a field with the specified name is not found.
+ * @throws IllegalAccessException
+ * if this Field object is enforcing Java language access control and the underlying field is either
+ * inaccessible or final.
+ * @throws IllegalArgumentException
+ * if the specified object is not an instance of the class or interface declaring the underlying field
+ * (or a subclass or implementor thereof), or if an unwrapping conversion fails.
+ */
+ public ExecutorHarness(SvcLogicJavaPlugin executor) throws NoSuchFieldException, SecurityException,
+ IllegalArgumentException, IllegalAccessException {
+ this();
+ setExecutor(executor);
+ }
+
+ /**
+ * @param executor
+ * The java plugin class to be executed
+ */
+ public void setExecutor(SvcLogicJavaPlugin executor) {
+ this.executor = executor;
+ scanExecutor();
+ }
+
+ /**
+ * @return The java plugin class to be executed
+ */
+ public SvcLogicJavaPlugin getExecutor() {
+ return executor;
+ }
+
+ /**
+ * @return The set of all methods that meet the signature requirements
+ */
+ public List<String> getExecMethodNames() {
+ List<String> names = new ArrayList<>();
+ names.addAll(methods.keySet());
+ return names;
+ }
+
+ /**
+ * Returns an indication if the named method is a valid executor method that could be called from a DG execute node
+ *
+ * @param methodName
+ * The method name to be validated
+ * @return True if the method name meets the signature requirements, false if the method either does not exist or
+ * does not meet the requirements.
+ */
+ public boolean isExecMethod(String methodName) {
+ return methods.containsKey(methodName);
+ }
+
+ /**
+ * This method scans the executor class hierarchy to locate all methods that match the required signature of the
+ * executor and records these methods in a map.
+ */
+ private void scanExecutor() {
+ methods.clear();
+ Class<?> executorClass = executor.getClass();
+ Method[] publicMethods = executorClass.getMethods();
+ for (Method method : publicMethods) {
+ if (method.getReturnType().equals(Void.class)) {
+ Class<?>[] paramTypes = method.getParameterTypes();
+ if (paramTypes.length == 2) {
+ if (Map.class.isAssignableFrom(paramTypes[0])
+ && SvcLogicContext.class.isAssignableFrom(paramTypes[1])) {
+ methods.put(method.getName(), method);
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/adaptors/ansible-adapter/ansible-adapter-bundle/src/test/java/org/onap/ccsdk/test/InterceptLogger.java b/adaptors/ansible-adapter/ansible-adapter-bundle/src/test/java/org/onap/ccsdk/test/InterceptLogger.java
new file mode 100644
index 000000000..92235cb39
--- /dev/null
+++ b/adaptors/ansible-adapter/ansible-adapter-bundle/src/test/java/org/onap/ccsdk/test/InterceptLogger.java
@@ -0,0 +1,454 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : APPC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Copyright (C) 2017 Amdocs
+ * =============================================================================
+ * 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.
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * ============LICENSE_END=========================================================
+ */
+
+
+package org.onap.ccsdk.test;
+
+import java.text.MessageFormat;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.slf4j.Marker;
+
+import ch.qos.logback.classic.Level;
+
+/**
+ * This class is used as an intercept logger that can be used in testing to intercept and record all messages that are
+ * logged, thus allowing a junit test case to examine the log output and make assertions.
+ */
+public class InterceptLogger implements org.slf4j.Logger {
+
+ /**
+ * This inner class represents an intercepted log event
+ */
+ public class LogRecord {
+ private Level level;
+ private String message;
+ private long timestamp;
+ private Throwable t;
+
+ public LogRecord(Level level, String message) {
+ setLevel(level);
+ setTimestamp(System.currentTimeMillis());
+ setMessage(message);
+ }
+
+ public LogRecord(Level level, String message, Throwable t) {
+ this(level, message);
+ setThrowable(t);
+ }
+
+ /**
+ * @return the value of level
+ */
+ public Level getLevel() {
+ return level;
+ }
+
+ /**
+ * @return the value of message
+ */
+ public String getMessage() {
+ return message;
+ }
+
+ /**
+ * @return the value of timestamp
+ */
+ public long getTimestamp() {
+ return timestamp;
+ }
+
+ /**
+ * @param level
+ * the value for level
+ */
+ public void setLevel(Level level) {
+ this.level = level;
+ }
+
+ /**
+ * @param message
+ * the value for message
+ */
+ public void setMessage(String message) {
+ this.message = message;
+ }
+
+ /**
+ * @param timestamp
+ * the value for timestamp
+ */
+ public void setTimestamp(long timestamp) {
+ this.timestamp = timestamp;
+ }
+
+ /**
+ * @return the value of t
+ */
+ public Throwable getThrowable() {
+ return t;
+ }
+
+ /**
+ * @param t
+ * the value for t
+ */
+ public void setThrowable(Throwable t) {
+ this.t = t;
+ }
+
+ }
+
+ /**
+ * The list of all intercepted log events
+ */
+ private List<LogRecord> events;
+
+ /**
+ * Create the intercept logger
+ */
+ public InterceptLogger() {
+ events = new ArrayList<LogRecord>(1000);
+ }
+
+ /**
+ * @return Returns all intercepted log events
+ */
+ public List<LogRecord> getLogRecords() {
+ return events;
+ }
+
+ /**
+ * Clears all log events
+ */
+ public void clear() {
+ events.clear();
+ }
+
+ @Override
+ public void debug(Marker marker, String msg) {
+ debug(msg);
+ }
+
+ @Override
+ public void debug(Marker marker, String format, Object arg) {
+ debug(MessageFormat.format(format, arg));
+ }
+
+ @Override
+ public void debug(Marker marker, String format, Object... arguments) {
+ debug(MessageFormat.format(format, arguments));
+ }
+
+ @Override
+ public void debug(Marker marker, String format, Object arg1, Object arg2) {
+ debug(MessageFormat.format(format, arg1, arg2));
+ }
+
+ @Override
+ public void debug(Marker marker, String msg, Throwable t) {
+ debug(msg, t);
+ }
+
+ @Override
+ public void debug(String msg) {
+ events.add(new LogRecord(Level.DEBUG, msg));
+ }
+
+ @Override
+ public void debug(String format, Object arg) {
+ events.add(new LogRecord(Level.DEBUG, MessageFormat.format(format, arg)));
+ }
+
+ @Override
+ public void debug(String format, Object... arguments) {
+ events.add(new LogRecord(Level.DEBUG, MessageFormat.format(format, arguments)));
+ }
+
+ @Override
+ public void debug(String format, Object arg1, Object arg2) {
+ events.add(new LogRecord(Level.DEBUG, MessageFormat.format(format, arg1, arg2)));
+ }
+
+ @Override
+ public void debug(String msg, Throwable t) {
+ events.add(new LogRecord(Level.DEBUG, msg, t));
+ }
+
+ @Override
+ public void error(Marker marker, String msg) {
+ error(msg);
+ }
+
+ @Override
+ public void error(Marker marker, String format, Object arg) {
+ error(format, arg);
+ }
+
+ @Override
+ public void error(Marker marker, String format, Object... arguments) {
+ error(format, arguments);
+ }
+
+ @Override
+ public void error(Marker marker, String format, Object arg1, Object arg2) {
+ error(format, arg1, arg2);
+ }
+
+ @Override
+ public void error(Marker marker, String msg, Throwable t) {
+ events.add(new LogRecord(Level.ERROR, msg, t));
+ }
+
+ @Override
+ public void error(String msg) {
+ events.add(new LogRecord(Level.ERROR, msg));
+ }
+
+ @Override
+ public void error(String format, Object arg) {
+ events.add(new LogRecord(Level.ERROR, MessageFormat.format(format, arg)));
+ }
+
+ @Override
+ public void error(String format, Object... arguments) {
+ events.add(new LogRecord(Level.ERROR, MessageFormat.format(format, arguments)));
+ }
+
+ @Override
+ public void error(String format, Object arg1, Object arg2) {
+ events.add(new LogRecord(Level.ERROR, MessageFormat.format(format, arg1, arg2)));
+ }
+
+ @Override
+ public void error(String msg, Throwable t) {
+ events.add(new LogRecord(Level.ERROR, msg, t));
+ }
+
+ @Override
+ public String getName() {
+ return null;
+ }
+
+ @Override
+ public void info(Marker marker, String msg) {
+ info(msg);
+ }
+
+ @Override
+ public void info(Marker marker, String format, Object arg) {
+ info(format, arg);
+ }
+
+ @Override
+ public void info(Marker marker, String format, Object... arguments) {
+ info(format, arguments);
+ }
+
+ @Override
+ public void info(Marker marker, String format, Object arg1, Object arg2) {
+ info(format, arg1, arg2);
+ }
+
+ @Override
+ public void info(Marker marker, String msg, Throwable t) {
+ events.add(new LogRecord(Level.INFO, msg, t));
+ }
+
+ @Override
+ public void info(String msg) {
+ events.add(new LogRecord(Level.INFO, msg));
+ }
+
+ @Override
+ public void info(String format, Object arg) {
+ events.add(new LogRecord(Level.INFO, MessageFormat.format(format, arg)));
+ }
+
+ @Override
+ public void info(String format, Object... arguments) {
+ events.add(new LogRecord(Level.INFO, MessageFormat.format(format, arguments)));
+ }
+
+ @Override
+ public void info(String format, Object arg1, Object arg2) {
+ events.add(new LogRecord(Level.INFO, MessageFormat.format(format, arg1, arg2)));
+ }
+
+ @Override
+ public void info(String msg, Throwable t) {
+ events.add(new LogRecord(Level.INFO, msg, t));
+ }
+
+ @Override
+ public boolean isDebugEnabled() {
+ return true;
+ }
+
+ @Override
+ public boolean isDebugEnabled(Marker marker) {
+ return true;
+ }
+
+ @Override
+ public boolean isErrorEnabled() {
+ return true;
+ }
+
+ @Override
+ public boolean isErrorEnabled(Marker marker) {
+ return true;
+ }
+
+ @Override
+ public boolean isInfoEnabled() {
+ return true;
+ }
+
+ @Override
+ public boolean isInfoEnabled(Marker marker) {
+ return true;
+ }
+
+ @Override
+ public boolean isTraceEnabled() {
+ return true;
+ }
+
+ @Override
+ public boolean isTraceEnabled(Marker marker) {
+ return true;
+ }
+
+ @Override
+ public boolean isWarnEnabled() {
+ return true;
+ }
+
+ @Override
+ public boolean isWarnEnabled(Marker marker) {
+ return true;
+ }
+
+ @Override
+ public void trace(Marker marker, String msg) {
+ trace(msg);
+ }
+
+ @Override
+ public void trace(Marker marker, String format, Object arg) {
+ trace(format, arg);
+ }
+
+ @Override
+ public void trace(Marker marker, String format, Object... argArray) {
+ trace(format, argArray);
+ }
+
+ @Override
+ public void trace(Marker marker, String format, Object arg1, Object arg2) {
+ trace(format, arg1, arg2);
+ }
+
+ @Override
+ public void trace(Marker marker, String msg, Throwable t) {
+ trace(msg, t);
+ }
+
+ @Override
+ public void trace(String msg) {
+ events.add(new LogRecord(Level.TRACE, msg));
+ }
+
+ @Override
+ public void trace(String format, Object arg) {
+ events.add(new LogRecord(Level.TRACE, MessageFormat.format(format, arg)));
+ }
+
+ @Override
+ public void trace(String format, Object... arguments) {
+ events.add(new LogRecord(Level.TRACE, MessageFormat.format(format, arguments)));
+ }
+
+ @Override
+ public void trace(String format, Object arg1, Object arg2) {
+ events.add(new LogRecord(Level.TRACE, MessageFormat.format(format, arg1, arg2)));
+ }
+
+ @Override
+ public void trace(String msg, Throwable t) {
+ events.add(new LogRecord(Level.TRACE, msg, t));
+ }
+
+ @Override
+ public void warn(Marker marker, String msg) {
+ warn(msg);
+ }
+
+ @Override
+ public void warn(Marker marker, String format, Object arg) {
+ warn(format, arg);
+ }
+
+ @Override
+ public void warn(Marker marker, String format, Object... arguments) {
+ warn(format, arguments);
+ }
+
+ @Override
+ public void warn(Marker marker, String format, Object arg1, Object arg2) {
+ warn(format, arg1, arg2);
+ }
+
+ @Override
+ public void warn(Marker marker, String msg, Throwable t) {
+ events.add(new LogRecord(Level.WARN, msg, t));
+ }
+
+ @Override
+ public void warn(String msg) {
+ events.add(new LogRecord(Level.WARN, msg));
+ }
+
+ @Override
+ public void warn(String format, Object arg) {
+ events.add(new LogRecord(Level.WARN, MessageFormat.format(format, arg)));
+ }
+
+ @Override
+ public void warn(String format, Object... arguments) {
+ events.add(new LogRecord(Level.WARN, MessageFormat.format(format, arguments)));
+ }
+
+ @Override
+ public void warn(String format, Object arg1, Object arg2) {
+ events.add(new LogRecord(Level.WARN, MessageFormat.format(format, arg1, arg2)));
+ }
+
+ @Override
+ public void warn(String msg, Throwable t) {
+ events.add(new LogRecord(Level.WARN, msg, t));
+ }
+}
diff --git a/adaptors/ansible-adapter/ansible-adapter-bundle/src/test/resources/cert b/adaptors/ansible-adapter/ansible-adapter-bundle/src/test/resources/cert
new file mode 100644
index 000000000..cc2921c4b
--- /dev/null
+++ b/adaptors/ansible-adapter/ansible-adapter-bundle/src/test/resources/cert
@@ -0,0 +1,125 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 1 (0x1)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C=FR, ST=Alsace, L=Strasbourg, O=www.freelan.org, OU=freelan, CN=Freelan Sample Certificate Authority/emailAddress=contact@freelan.org
+ Validity
+ Not Before: Apr 27 10:31:18 2012 GMT
+ Not After : Apr 25 10:31:18 2022 GMT
+ Subject: C=FR, ST=Alsace, O=www.freelan.org, OU=freelan, CN=alice/emailAddress=contact@freelan.org
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ Public-Key: (4096 bit)
+ Modulus:
+ 00:dd:6d:bd:f8:80:fa:d7:de:1b:1f:a7:a3:2e:b2:
+ 02:e2:16:f6:52:0a:3c:bf:a6:42:f8:ca:dc:93:67:
+ 4d:60:c3:4f:8d:c3:8a:00:1b:f1:c4:4b:41:6a:69:
+ d2:69:e5:3f:21:8e:c5:0b:f8:22:37:ad:b6:2c:4b:
+ 55:ff:7a:03:72:bb:9a:d3:ec:96:b9:56:9f:cb:19:
+ 99:c9:32:94:6f:8f:c6:52:06:9f:45:03:df:fd:e8:
+ 97:f6:ea:d6:ba:bb:48:2b:b5:e0:34:61:4d:52:36:
+ 0f:ab:87:52:25:03:cf:87:00:87:13:f2:ca:03:29:
+ 16:9d:90:57:46:b5:f4:0e:ae:17:c8:0a:4d:92:ed:
+ 08:a6:32:23:11:71:fe:f2:2c:44:d7:6c:07:f3:0b:
+ 7b:0c:4b:dd:3b:b4:f7:37:70:9f:51:b6:88:4e:5d:
+ 6a:05:7f:8d:9b:66:7a:ab:80:20:fe:ee:6b:97:c3:
+ 49:7d:78:3b:d5:99:97:03:75:ce:8f:bc:c5:be:9c:
+ 9a:a5:12:19:70:f9:a4:bd:96:27:ed:23:02:a7:c7:
+ 57:c9:71:cf:76:94:a2:21:62:f6:b8:1d:ca:88:ee:
+ 09:ad:46:2f:b7:61:b3:2c:15:13:86:9f:a5:35:26:
+ 5a:67:f4:37:c8:e6:80:01:49:0e:c7:ed:61:d3:cd:
+ bc:e4:f8:be:3f:c9:4e:f8:7d:97:89:ce:12:bc:ca:
+ b5:c6:d2:e0:d9:b3:68:3c:2e:4a:9d:b4:5f:b8:53:
+ ee:50:3d:bf:dd:d4:a2:8a:b6:a0:27:ab:98:0c:b3:
+ b2:58:90:e2:bc:a1:ad:ff:bd:8e:55:31:0f:00:bf:
+ 68:e9:3d:a9:19:9a:f0:6d:0b:a2:14:6a:c6:4c:c6:
+ 4e:bd:63:12:a5:0b:4d:97:eb:42:09:79:53:e2:65:
+ aa:24:34:70:b8:c1:ab:23:80:e7:9c:6c:ed:dc:82:
+ aa:37:04:b8:43:2a:3d:2a:a8:cc:20:fc:27:5d:90:
+ 26:58:f9:b7:14:e2:9e:e2:c1:70:73:97:e9:6b:02:
+ 8e:d3:52:59:7b:00:ec:61:30:f1:56:3f:9c:c1:7c:
+ 05:c5:b1:36:c8:18:85:cf:61:40:1f:07:e8:a7:06:
+ 87:df:9a:77:0b:a9:64:72:03:f6:93:fc:e0:02:59:
+ c1:96:ec:c0:09:42:3e:30:a2:7f:1b:48:2f:fe:e0:
+ 21:8f:53:87:25:0d:cb:ea:49:f5:4a:9b:d0:e3:5f:
+ ee:78:18:e5:ba:71:31:a9:04:98:0f:b1:ad:67:52:
+ a0:f2:e3:9c:ab:6a:fe:58:84:84:dd:07:3d:32:94:
+ 05:16:45:15:96:59:a0:58:6c:18:0e:e3:77:66:c7:
+ b3:f7:99
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints:
+ CA:FALSE
+ Netscape Comment:
+ OpenSSL Generated Certificate
+ X509v3 Subject Key Identifier:
+ 59:5F:C9:13:BA:1B:CC:B9:A8:41:4A:8A:49:79:6A:36:F6:7D:3E:D7
+ X509v3 Authority Key Identifier:
+ keyid:23:6C:2D:3D:3E:29:5D:78:B8:6C:3E:AA:E2:BB:2E:1E:6C:87:F2:53
+
+ Signature Algorithm: sha1WithRSAEncryption
+ 13:e7:02:45:3e:a7:ab:bd:b8:da:e7:ef:74:88:ac:62:d5:dd:
+ 10:56:d5:46:07:ec:fa:6a:80:0c:b9:62:be:aa:08:b4:be:0b:
+ eb:9a:ef:68:b7:69:6f:4d:20:92:9d:18:63:7a:23:f4:48:87:
+ 6a:14:c3:91:98:1b:4e:08:59:3f:91:80:e9:f4:cf:fd:d5:bf:
+ af:4b:e4:bd:78:09:71:ac:d0:81:e5:53:9f:3e:ac:44:3e:9f:
+ f0:bf:5a:c1:70:4e:06:04:ef:dc:e8:77:05:a2:7d:c5:fa:80:
+ 58:0a:c5:10:6d:90:ca:49:26:71:84:39:b7:9a:3e:e9:6f:ae:
+ c5:35:b6:5b:24:8c:c9:ef:41:c3:b1:17:b6:3b:4e:28:89:3c:
+ 7e:87:a8:3a:a5:6d:dc:39:03:20:20:0b:c5:80:a3:79:13:1e:
+ f6:ec:ae:36:df:40:74:34:87:46:93:3b:a3:e0:a4:8c:2f:43:
+ 4c:b2:54:80:71:76:78:d4:ea:12:28:d8:f2:e3:80:55:11:9b:
+ f4:65:dc:53:0e:b4:4c:e0:4c:09:b4:dc:a0:80:5c:e6:b5:3b:
+ 95:d3:69:e4:52:3d:5b:61:86:02:e5:fd:0b:00:3a:fa:b3:45:
+ cc:c9:a3:64:f2:dc:25:59:89:58:0d:9e:6e:28:3a:55:45:50:
+ 5f:88:67:2a:d2:e2:48:cc:8b:de:9a:1b:93:ae:87:e1:f2:90:
+ 50:40:d9:0f:44:31:53:46:ad:62:4e:8d:48:86:19:77:fc:59:
+ 75:91:79:35:59:1d:e3:4e:33:5b:e2:31:d7:ee:52:28:5f:0a:
+ 70:a7:be:bb:1c:03:ca:1a:18:d0:f5:c1:5b:9c:73:04:b6:4a:
+ e8:46:52:58:76:d4:6a:e6:67:1c:0e:dc:13:d0:61:72:a0:92:
+ cb:05:97:47:1c:c1:c9:cf:41:7d:1f:b1:4d:93:6b:53:41:03:
+ 21:2b:93:15:63:08:3e:2c:86:9e:7b:9f:3a:09:05:6a:7d:bb:
+ 1c:a7:b7:af:96:08:cb:5b:df:07:fb:9c:f2:95:11:c0:82:81:
+ f6:1b:bf:5a:1e:58:cd:28:ca:7d:04:eb:aa:e9:29:c4:82:51:
+ 2c:89:61:95:b6:ed:a5:86:7c:7c:48:1d:ec:54:96:47:79:ea:
+ fc:7f:f5:10:43:0a:9b:00:ef:8a:77:2e:f4:36:66:d2:6a:a6:
+ 95:b6:9f:23:3b:12:e2:89:d5:a4:c1:2c:91:4e:cb:94:e8:3f:
+ 22:0e:21:f9:b8:4a:81:5c:4c:63:ae:3d:05:b2:5c:5c:54:a7:
+ 55:8f:98:25:55:c4:a6:90:bc:19:29:b1:14:d4:e2:b0:95:e4:
+ ff:89:71:61:be:8a:16:85
+-----BEGIN CERTIFICATE-----
+MIIGJzCCBA+gAwIBAgIBATANBgkqhkiG9w0BAQUFADCBsjELMAkGA1UEBhMCRlIx
+DzANBgNVBAgMBkFsc2FjZTETMBEGA1UEBwwKU3RyYXNib3VyZzEYMBYGA1UECgwP
+d3d3LmZyZWVsYW4ub3JnMRAwDgYDVQQLDAdmcmVlbGFuMS0wKwYDVQQDDCRGcmVl
+bGFuIFNhbXBsZSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxIjAgBgkqhkiG9w0BCQEW
+E2NvbnRhY3RAZnJlZWxhbi5vcmcwHhcNMTIwNDI3MTAzMTE4WhcNMjIwNDI1MTAz
+MTE4WjB+MQswCQYDVQQGEwJGUjEPMA0GA1UECAwGQWxzYWNlMRgwFgYDVQQKDA93
+d3cuZnJlZWxhbi5vcmcxEDAOBgNVBAsMB2ZyZWVsYW4xDjAMBgNVBAMMBWFsaWNl
+MSIwIAYJKoZIhvcNAQkBFhNjb250YWN0QGZyZWVsYW4ub3JnMIICIjANBgkqhkiG
+9w0BAQEFAAOCAg8AMIICCgKCAgEA3W29+ID6194bH6ejLrIC4hb2Ugo8v6ZC+Mrc
+k2dNYMNPjcOKABvxxEtBamnSaeU/IY7FC/giN622LEtV/3oDcrua0+yWuVafyxmZ
+yTKUb4/GUgafRQPf/eiX9urWurtIK7XgNGFNUjYPq4dSJQPPhwCHE/LKAykWnZBX
+RrX0Dq4XyApNku0IpjIjEXH+8ixE12wH8wt7DEvdO7T3N3CfUbaITl1qBX+Nm2Z6
+q4Ag/u5rl8NJfXg71ZmXA3XOj7zFvpyapRIZcPmkvZYn7SMCp8dXyXHPdpSiIWL2
+uB3KiO4JrUYvt2GzLBUThp+lNSZaZ/Q3yOaAAUkOx+1h08285Pi+P8lO+H2Xic4S
+vMq1xtLg2bNoPC5KnbRfuFPuUD2/3dSiiragJ6uYDLOyWJDivKGt/72OVTEPAL9o
+6T2pGZrwbQuiFGrGTMZOvWMSpQtNl+tCCXlT4mWqJDRwuMGrI4DnnGzt3IKqNwS4
+Qyo9KqjMIPwnXZAmWPm3FOKe4sFwc5fpawKO01JZewDsYTDxVj+cwXwFxbE2yBiF
+z2FAHwfopwaH35p3C6lkcgP2k/zgAlnBluzACUI+MKJ/G0gv/uAhj1OHJQ3L6kn1
+SpvQ41/ueBjlunExqQSYD7GtZ1Kg8uOcq2r+WISE3Qc9MpQFFkUVllmgWGwYDuN3
+Zsez95kCAwEAAaN7MHkwCQYDVR0TBAIwADAsBglghkgBhvhCAQ0EHxYdT3BlblNT
+TCBHZW5lcmF0ZWQgQ2VydGlmaWNhdGUwHQYDVR0OBBYEFFlfyRO6G8y5qEFKikl5
+ajb2fT7XMB8GA1UdIwQYMBaAFCNsLT0+KV14uGw+quK7Lh5sh/JTMA0GCSqGSIb3
+DQEBBQUAA4ICAQAT5wJFPqervbja5+90iKxi1d0QVtVGB+z6aoAMuWK+qgi0vgvr
+mu9ot2lvTSCSnRhjeiP0SIdqFMORmBtOCFk/kYDp9M/91b+vS+S9eAlxrNCB5VOf
+PqxEPp/wv1rBcE4GBO/c6HcFon3F+oBYCsUQbZDKSSZxhDm3mj7pb67FNbZbJIzJ
+70HDsRe2O04oiTx+h6g6pW3cOQMgIAvFgKN5Ex727K4230B0NIdGkzuj4KSML0NM
+slSAcXZ41OoSKNjy44BVEZv0ZdxTDrRM4EwJtNyggFzmtTuV02nkUj1bYYYC5f0L
+ADr6s0XMyaNk8twlWYlYDZ5uKDpVRVBfiGcq0uJIzIvemhuTrofh8pBQQNkPRDFT
+Rq1iTo1Ihhl3/Fl1kXk1WR3jTjNb4jHX7lIoXwpwp767HAPKGhjQ9cFbnHMEtkro
+RlJYdtRq5mccDtwT0GFyoJLLBZdHHMHJz0F9H7FNk2tTQQMhK5MVYwg+LIaee586
+CQVqfbscp7evlgjLW98H+5zylRHAgoH2G79aHljNKMp9BOuq6SnEglEsiWGVtu2l
+hnx8SB3sVJZHeer8f/UQQwqbAO+Kdy70NmbSaqaVtp8jOxLiidWkwSyRTsuU6D8i
+DiH5uEqBXExjrj0FslxcVKdVj5glVcSmkLwZKbEU1OKwleT/iXFhvooWhQ==
+-----END CERTIFICATE-----
diff --git a/adaptors/ansible-adapter/ansible-adapter-bundle/src/test/resources/org/onap/ccsdk/default.properties b/adaptors/ansible-adapter/ansible-adapter-bundle/src/test/resources/org/onap/ccsdk/default.properties
new file mode 100644
index 000000000..2f8fb4585
--- /dev/null
+++ b/adaptors/ansible-adapter/ansible-adapter-bundle/src/test/resources/org/onap/ccsdk/default.properties
@@ -0,0 +1,111 @@
+###
+# ============LICENSE_START=======================================================
+# ONAP : APPC
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+# ================================================================================
+# Copyright (C) 2017 Amdocs
+# =============================================================================
+# 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.
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+# ============LICENSE_END=========================================================
+###
+
+#
+# Default properties for the APP-C Provider Adapter
+#
+# -------------------------------------------------------------------------------------------------
+#
+# Define the name and path of any user-provided configuration (bootstrap) file that can be loaded
+# to supply configuration options
+org.onap.appc.bootstrap.file=appc.properties
+org.onap.appc.bootstrap.path=/opt/onap/appc/data/properties,${user.home},.
+
+appc.application.name=APPC
+
+#
+# Define the message resource bundle name to be loaded
+org.onap.appc.resources=org/onap/appc/i18n/MessageResources
+#
+# The name of the adapter.
+org.onap.appc.provider.adaptor.name=org.onap.appc.appc_provider_adapter
+#
+# Set up the logging environment
+#
+org.onap.appc.logging.file=org/onap/appc/logback.xml
+org.onap.appc.logging.path=${user.home};etc;../etc
+org.onap.appc.logger=org.onap.appc
+org.onap.appc.security.logger=org.onap.appc.security
+#
+# The minimum and maximum provider/tenant context pool sizes. Min=1 means that as soon
+# as the provider/tenant is referenced a Context is opened and added to the pool. Max=0
+# means that the upper bound on the pool is unbounded.
+org.onap.appc.provider.min.pool=1
+org.onap.appc.provider.max.pool=0
+
+#
+# The following properties are used to configure the retry logic for connection to the
+# IaaS provider(s). The retry delay property is the amount of time, in seconds, the
+# application waits between retry attempts. The retry limit is the number of retries
+# that are allowed before the request is failed.
+org.onap.appc.provider.retry.delay = 30
+org.onap.appc.provider.retry.limit = 10
+
+#
+# The trusted hosts list for SSL access when a certificate is not provided.
+#
+provider.trusted.hosts=*
+#
+# The amount of time, in seconds, to wait for a server state change (start->stop, stop->start, etc).
+# If the server does not change state to a valid state within the alloted time, the operation
+# fails.
+org.onap.appc.server.state.change.timeout=300
+#
+# The amount of time to wait, in seconds, between subsequent polls to the OpenStack provider
+# to refresh the status of a resource we are waiting on.
+#
+org.onap.appc.openstack.poll.interval=20
+#
+# The connection information to connect to the provider we are using. These properties
+# are "structured" properties, in that the name is a compound name, where the nodes
+# of the name can be ordered (1, 2, 3, ...). All of the properties with the same ordinal
+# position are defining the same entity. For example, provider1.type and provider1.name
+# are defining the same provider, whereas provider2.name and provider2.type are defining
+# the values for a different provider. Any number of providers can be defined in this
+# way.
+#
+
+# Don't change these 2 right now since they are hard coded in the DG
+#provider1.type=appc
+#provider1.name=appc
+
+#These you can change
+#provider1.identity=appc
+#provider1.tenant1.name=appc
+#provider1.tenant1.userid=appc
+#provider1.tenant1.password=appc
+
+# After a change to the provider make sure to recheck these values with an api call to provider1.identity/tokens
+test.expected-regions=1
+test.expected-endpoints=1
+
+#Your OpenStack IP
+#test.ip=192.168.1.2
+# Your OpenStack Platform's Keystone Port (default is 5000)
+#test.port=5000
+#test.tenantid=abcde12345fghijk6789lmnopq123rst
+#test.vmid=abc12345-1234-5678-890a-abcdefg12345
+# Port 8774 below is default port for OpenStack's Nova API Service
+#test.url=http://192.168.1.2:8774/v2/abcde12345fghijk6789lmnopq123rst/servers/abc12345-1234-5678-890a-abcdefg12345
+
diff --git a/adaptors/ansible-adapter/ansible-adapter-installer/pom.xml b/adaptors/ansible-adapter/ansible-adapter-installer/pom.xml
new file mode 100644
index 000000000..af02a8c5c
--- /dev/null
+++ b/adaptors/ansible-adapter/ansible-adapter-installer/pom.xml
@@ -0,0 +1,151 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ============LICENSE_START=======================================================
+ ONAP : APPC
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ ================================================================================
+ Copyright (C) 2017 Amdocs
+ =============================================================================
+ 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.
+
+ ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ ============LICENSE_END=========================================================
+ -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>odlparent-lite</artifactId>
+ <version>2.1.0</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.adaptors</groupId>
+ <artifactId>ansible-adapter-installer</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>pom</packaging>
+
+ <name>ccsdk-sli-adaptors :: ansible-adapter :: ${project.artifactId}</name>
+
+ <properties>
+ <application.name>ccsdk-ansible-adapter</application.name>
+ <features.boot>${application.name}</features.boot>
+ <features.repositories>mvn:org.onap.ccsdk.sli.adaptors/${features.boot}/${project.version}/xml/features</features.repositories>
+ <include.transitive.dependencies>false</include.transitive.dependencies>
+ </properties>
+
+ <dependencies>
+
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.adaptors</groupId>
+ <artifactId>ansible-adapter-bundle</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>maven-repo-zip</id>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ <phase>package</phase>
+ <configuration>
+ <appendAssemblyId>true</appendAssemblyId>
+ <attach>true</attach>
+ <finalName>stage/${application.name}-${project.version}</finalName>
+ <descriptors>
+ <descriptor>src/assembly/assemble_mvnrepo_zip.xml</descriptor>
+ </descriptors>
+ </configuration>
+ </execution>
+ <execution>
+ <id>installer-zip</id>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ <phase>package</phase>
+ <configuration>
+ <appendAssemblyId>false</appendAssemblyId>
+ <attach>true</attach>
+ <finalName>${application.name}-${project.version}</finalName>
+ <descriptors>
+ <descriptor>src/assembly/assemble_installer_zip.xml</descriptor>
+ </descriptors>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>copy-dependencies</id>
+ <goals>
+ <goal>copy-dependencies</goal>
+ </goals>
+ <phase>prepare-package</phase>
+ <configuration>
+ <transitive>false</transitive>
+ <outputDirectory>${project.build.directory}/assembly/system</outputDirectory>
+ <overWriteReleases>false</overWriteReleases>
+ <overWriteSnapshots>true</overWriteSnapshots>
+ <overWriteIfNewer>true</overWriteIfNewer>
+ <useRepositoryLayout>true</useRepositoryLayout>
+ <addParentPoms>false</addParentPoms>
+ <copyPom>false</copyPom>
+ <includeGroupIds>org.onap.ccsdk.sli.adaptors</includeGroupIds>
+
+ <scope>provided</scope>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <artifactId>maven-resources-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>copy-version</id>
+ <goals>
+ <goal>copy-resources</goal>
+ </goals>
+ <!-- here the phase you need -->
+ <phase>validate</phase>
+ <configuration>
+ <outputDirectory>${basedir}/target/stage</outputDirectory>
+ <resources>
+ <resource>
+ <directory>src/main/resources/scripts</directory>
+ <includes>
+ <include>install-feature.sh</include>
+ </includes>
+ <filtering>true</filtering>
+ </resource>
+ </resources>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/adaptors/ansible-adapter/ansible-adapter-installer/src/assembly/assemble_installer_zip.xml b/adaptors/ansible-adapter/ansible-adapter-installer/src/assembly/assemble_installer_zip.xml
new file mode 100644
index 000000000..322fa76eb
--- /dev/null
+++ b/adaptors/ansible-adapter/ansible-adapter-installer/src/assembly/assemble_installer_zip.xml
@@ -0,0 +1,62 @@
+<!--
+ ============LICENSE_START=======================================================
+ ONAP : APPC
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ ================================================================================
+ Copyright (C) 2017 Amdocs
+ =============================================================================
+ 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.
+
+ ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ ============LICENSE_END=========================================================
+ -->
+
+<!-- Defines how we build the .zip file which is our distribution. -->
+
+<assembly
+ xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
+ <id>adapter</id>
+ <formats>
+ <format>zip</format>
+ </formats>
+
+ <!-- we want "system" and related files right at the root level
+ as this file is suppose to be unzip on top of a karaf
+ distro. -->
+ <includeBaseDirectory>false</includeBaseDirectory>
+
+ <fileSets>
+ <fileSet>
+ <directory>target/stage/</directory>
+ <outputDirectory>${application.name}</outputDirectory>
+ <fileMode>755</fileMode>
+ <includes>
+ <include>*.sh</include>
+ </includes>
+ </fileSet>
+ <fileSet>
+ <directory>target/stage/</directory>
+ <outputDirectory>${application.name}</outputDirectory>
+ <fileMode>644</fileMode>
+ <excludes>
+ <exclude>*.sh</exclude>
+ </excludes>
+ </fileSet>
+ </fileSets>
+
+
+
+</assembly>
diff --git a/adaptors/ansible-adapter/ansible-adapter-installer/src/assembly/assemble_mvnrepo_zip.xml b/adaptors/ansible-adapter/ansible-adapter-installer/src/assembly/assemble_mvnrepo_zip.xml
new file mode 100644
index 000000000..ec65e79e1
--- /dev/null
+++ b/adaptors/ansible-adapter/ansible-adapter-installer/src/assembly/assemble_mvnrepo_zip.xml
@@ -0,0 +1,50 @@
+<!--
+ ============LICENSE_START=======================================================
+ ONAP : APPC
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ ================================================================================
+ Copyright (C) 2017 Amdocs
+ =============================================================================
+ 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.
+
+ ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ ============LICENSE_END=========================================================
+ -->
+
+<!-- Defines how we build the .zip file which is our distribution. -->
+
+<assembly
+ xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
+ <id>repo</id>
+ <formats>
+ <format>zip</format>
+ </formats>
+
+ <!-- we want "system" and related files right at the root level
+ as this file is suppose to be unzip on top of a karaf
+ distro. -->
+ <includeBaseDirectory>false</includeBaseDirectory>
+
+ <fileSets>
+ <fileSet>
+ <directory>target/assembly/</directory>
+ <outputDirectory>.</outputDirectory>
+ <excludes>
+ </excludes>
+ </fileSet>
+ </fileSets>
+
+</assembly>
diff --git a/adaptors/ansible-adapter/ansible-adapter-installer/src/main/resources/scripts/install-feature.sh b/adaptors/ansible-adapter/ansible-adapter-installer/src/main/resources/scripts/install-feature.sh
new file mode 100644
index 000000000..c8214c520
--- /dev/null
+++ b/adaptors/ansible-adapter/ansible-adapter-installer/src/main/resources/scripts/install-feature.sh
@@ -0,0 +1,42 @@
+###
+# ============LICENSE_START=======================================================
+# ONAP : APPC
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+# ================================================================================
+# Copyright (C) 2017 Amdocs
+# =============================================================================
+# 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.
+#
+# ECOMP is a trademark and service mark of AT&T Intellectual Property.
+# ============LICENSE_END=========================================================
+###
+
+#!/bin/bash
+
+ODL_HOME=${ODL_HOME:-/opt/opendaylight/current}
+ODL_KARAF_CLIENT=${ODL_KARAF_CLIENT:-${ODL_HOME}/bin/client}
+INSTALLERDIR=$(dirname $0)
+
+REPOZIP=${INSTALLERDIR}/${features.boot}-${project.version}.zip
+
+if [ -f ${REPOZIP} ]
+then
+ unzip -n -d ${ODL_HOME} ${REPOZIP}
+else
+ echo "ERROR : repo zip ($REPOZIP) not found"
+ exit 1
+fi
+
+${ODL_KARAF_CLIENT} feature:repo-add ${features.repositories}
+${ODL_KARAF_CLIENT} feature:install ${features.boot}
diff --git a/adaptors/ansible-adapter/pom.xml b/adaptors/ansible-adapter/pom.xml
new file mode 100644
index 000000000..3414e7cf3
--- /dev/null
+++ b/adaptors/ansible-adapter/pom.xml
@@ -0,0 +1,191 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ============LICENSE_START=======================================================
+ ONAP : APPC
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ ================================================================================
+ Copyright (C) 2017 Amdocs
+ =============================================================================
+ 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.
+
+ ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ ============LICENSE_END=========================================================
+ -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>odlparent-lite</artifactId>
+ <version>2.1.0</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.adaptors</groupId>
+ <artifactId>ansible-adaptor</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>pom</packaging>
+
+ <name>ccsdk-sli-adaptors :: ansible-adapter</name>
+ <description>Abstractions to interact with Ansible server via REST</description>
+
+ <modules>
+ <module>ansible-adapter-bundle</module>
+ <module>ansible-adapter-installer</module>
+ </modules>
+
+ <dependencyManagement>
+ <dependencies>
+
+ <dependency>
+ <groupId>org.onap.appc</groupId>
+ <artifactId>ansible-adapter-features</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ </dependency>
+
+ <dependency>
+ <groupId>org.onap.appc</groupId>
+ <artifactId>ansible-adapter-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+
+ </dependencies>
+
+
+ </dependencyManagement>
+
+ <pluginRepositories>
+ <!-- Black Duck plugin dependencies -->
+ <pluginRepository>
+ <id>JCenter</id>
+ <name>JCenter Repository</name>
+ <url>http://jcenter.bintray.com</url>
+ </pluginRepository>
+
+ </pluginRepositories>
+
+ <build>
+ <plugins>
+
+ <!-- Black duck plugin Not required for regular builds
+ <plugin> <groupId>com.blackducksoftware.integration</groupId> <artifactId>hub-maven-plugin</artifactId>
+ <version>1.4.0</version> <inherited>false</inherited> <configuration> <hubProjectName>${project.name}</hubProjectName>
+ <outputDirectory>${project.basedir}</outputDirectory> <deployHubBdio>false</deployHubBdio>
+ </configuration> <extensions>true</extensions>
+ <executions>
+ <execution>
+ <id>create-bdio-file</id>
+ <phase>package</phase>
+ <goals>
+ <goal>createHubOutput</goal>
+ </goals>
+ </execution>
+ </executions>
+
+ </plugin>
+ -->
+
+ </plugins>
+ </build>
+
+ <reporting>
+ <plugins>
+ <plugin>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ <configuration>
+ <additionalDependencies>
+ <additionalDependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ <version>${slf4j.version}</version>
+ </additionalDependency>
+ <additionalDependency>
+ <groupId>org.antlr</groupId>
+ <artifactId>antlr4</artifactId>
+ <version>${antlr.version}</version>
+ </additionalDependency>
+ <additionalDependency>
+ <groupId>org.antlr</groupId>
+ <artifactId>antlr4-runtime</artifactId>
+ <version>4.3</version>
+ </additionalDependency>
+ </additionalDependencies>
+ </configuration>
+ <reportSets>
+ <reportSet>
+ <reports>
+ <report>javadoc-no-fork</report>
+ <report>test-javadoc-no-fork</report>
+ </reports>
+ </reportSet>
+ <reportSet>
+ <id>aggregate</id>
+ <reports>
+ <report>aggregate</report>
+ <report>test-aggregate</report>
+ </reports>
+ </reportSet>
+ </reportSets>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jxr-plugin</artifactId>
+ <version>2.3</version>
+ <reportSets>
+ <reportSet>
+ <id>aggregate</id>
+ <reports>
+ <report>aggregate</report>
+ <report>test-aggregate</report>
+ </reports>
+ </reportSet>
+ </reportSets>
+ </plugin>
+
+ <plugin>
+ <artifactId>maven-surefire-plugin</artifactId>
+ </plugin>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-changelog-plugin</artifactId>
+ <version>2.3</version>
+ <reportSets>
+ <reportSet>
+ <id>dual-report</id>
+ <configuration>
+ <type>range</type>
+ <range>30</range>
+ </configuration>
+ <reports>
+ <report>changelog</report>
+ <report>file-activity</report>
+ </reports>
+ </reportSet>
+ </reportSets>
+ </plugin>
+
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>taglist-maven-plugin</artifactId>
+ <version>2.4</version>
+ </plugin>
+ </plugins>
+
+ </reporting>
+</project>
diff --git a/adaptors/artifacts/pom.xml b/adaptors/artifacts/pom.xml
new file mode 100755
index 000000000..452292304
--- /dev/null
+++ b/adaptors/artifacts/pom.xml
@@ -0,0 +1,146 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>parent</artifactId>
+ <version>2.1.0</version>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.adaptors</groupId>
+ <artifactId>sli-adaptors-artifacts</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>pom</packaging>
+
+ <name>ccsdk-sli-adaptors :: sli-adaptors-artifacts</name>
+ <description>CCSDK adaptors components Bill of Materials (BOM)</description>
+ <url>https://wiki.onap.org</url>
+ <organization>
+ <name>ONAP</name>
+ </organization>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.adaptors</groupId>
+ <artifactId>ccsdk-aai-service</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>feature</classifier>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.adaptors</groupId>
+ <artifactId>ccsdk-ansible-adapter</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>feature</classifier>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.adaptors</groupId>
+ <artifactId>ccsdk-mdsal-resource</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>feature</classifier>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.adaptors</groupId>
+ <artifactId>ccsdk-netbox-client</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>feature</classifier>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.adaptors</groupId>
+ <artifactId>ccsdk-resource-management</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>feature</classifier>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.adaptors</groupId>
+ <artifactId>ccsdk-saltstack-adapter</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>feature</classifier>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.adaptors</groupId>
+ <artifactId>ccsdk-sql-resource</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>feature</classifier>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.adaptors</groupId>
+ <artifactId>aai-service-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.adaptors</groupId>
+ <artifactId>aai-service-installer</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.adaptors</groupId>
+ <artifactId>ansible-adapter-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.adaptors</groupId>
+ <artifactId>ansible-adapter-installer</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.adaptors</groupId>
+ <artifactId>mdsal-resource-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.adaptors</groupId>
+ <artifactId>mdsal-resource-installer</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.adaptors</groupId>
+ <artifactId>netbox-client-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.adaptors</groupId>
+ <artifactId>netbox-client-installer</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.adaptors</groupId>
+ <artifactId>resource-assignment-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.adaptors</groupId>
+ <artifactId>resource-assignment-installer</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.adaptors</groupId>
+ <artifactId>saltstack-adapter-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.adaptors</groupId>
+ <artifactId>saltstack-adapter-installer</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.adaptors</groupId>
+ <artifactId>sql-resource-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.adaptors</groupId>
+ <artifactId>sql-resource-installer</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+</project>
diff --git a/adaptors/base/http/installer/pom.xml b/adaptors/base/http/installer/pom.xml
new file mode 100644
index 000000000..980302ac9
--- /dev/null
+++ b/adaptors/base/http/installer/pom.xml
@@ -0,0 +1,127 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>odlparent-lite</artifactId>
+ <version>2.1.0</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.adaptors</groupId>
+ <artifactId>base-http-installer</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>pom</packaging>
+
+ <name>ccsdk-sli-adaptors :: base-http :: ${project.artifactId}</name>
+
+ <properties>
+ <application.name>ccsdk-base-http</application.name>
+ <features.boot>${application.name}</features.boot>
+ <features.repositories>mvn:org.onap.ccsdk.sli.adaptors/${features.boot}/${project.version}/xml/features</features.repositories>
+ <include.transitive.dependencies>false</include.transitive.dependencies>
+ </properties>
+
+ <dependencies>
+
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.adaptors</groupId>
+ <artifactId>base-http-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <version>2.6</version>
+ <executions>
+ <execution>
+ <id>maven-repo-zip</id>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ <phase>package</phase>
+ <configuration>
+ <attach>true</attach>
+ <finalName>stage/${application.name}-${project.version}</finalName>
+ <descriptors>
+ <descriptor>src/assembly/assemble_mvnrepo_zip.xml</descriptor>
+ </descriptors>
+ <appendAssemblyId>true</appendAssemblyId>
+ </configuration>
+ </execution>
+ <execution>
+ <id>installer-zip</id>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ <phase>package</phase>
+ <configuration>
+ <attach>true</attach>
+ <finalName>${application.name}-${project.version}-installer</finalName>
+ <descriptors>
+ <descriptor>src/assembly/assemble_installer_zip.xml</descriptor>
+ </descriptors>
+ <appendAssemblyId>false</appendAssemblyId>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>copy-dependencies</id>
+ <goals>
+ <goal>copy-dependencies</goal>
+ </goals>
+ <phase>prepare-package</phase>
+ <configuration>
+ <transitive>false</transitive>
+ <outputDirectory>${project.build.directory}/assembly/system</outputDirectory>
+ <overWriteReleases>false</overWriteReleases>
+ <overWriteSnapshots>true</overWriteSnapshots>
+ <overWriteIfNewer>true</overWriteIfNewer>
+ <useRepositoryLayout>true</useRepositoryLayout>
+ <addParentPoms>false</addParentPoms>
+ <copyPom>false</copyPom>
+ <includeArtifactIds>ccsdk-base-http,base-http-provider</includeArtifactIds>
+ <scope>provided</scope>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <artifactId>maven-resources-plugin</artifactId>
+ <version>2.6</version>
+ <executions>
+ <execution>
+ <id>copy-version</id>
+ <goals>
+ <goal>copy-resources</goal>
+ </goals><!-- here the phase you need -->
+ <phase>validate</phase>
+ <configuration>
+ <outputDirectory>${basedir}/target/stage</outputDirectory>
+ <resources>
+ <resource>
+ <directory>src/main/resources/scripts</directory>
+ <includes>
+ <include>install-feature.sh</include>
+ </includes>
+ <filtering>true</filtering>
+ </resource>
+ </resources>
+ </configuration>
+ </execution>
+
+ </executions>
+ </plugin>
+
+ </plugins>
+ </build>
+</project>
diff --git a/adaptors/base/http/installer/src/assembly/assemble_installer_zip.xml b/adaptors/base/http/installer/src/assembly/assemble_installer_zip.xml
new file mode 100644
index 000000000..3bed4b5ef
--- /dev/null
+++ b/adaptors/base/http/installer/src/assembly/assemble_installer_zip.xml
@@ -0,0 +1,59 @@
+<!--
+ ============LICENSE_START=======================================================
+ openECOMP : SDN-C
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property. All rights
+ reserved.
+ ================================================================================
+ 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.
+ ============LICENSE_END=========================================================
+ -->
+
+<!-- Defines how we build the .zip file which is our distribution. -->
+
+<assembly
+ xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
+ <id>installer_zip</id>
+ <formats>
+ <format>zip</format>
+ </formats>
+
+ <!-- we want "system" and related files right at the root level
+ as this file is suppose to be unzip on top of a karaf
+ distro. -->
+ <includeBaseDirectory>false</includeBaseDirectory>
+
+ <fileSets>
+ <fileSet>
+ <directory>target/stage/</directory>
+ <outputDirectory>${application.name}</outputDirectory>
+ <fileMode>755</fileMode>
+ <includes>
+ <include>*.sh</include>
+ </includes>
+ </fileSet>
+ <fileSet>
+ <directory>target/stage/</directory>
+ <outputDirectory>${application.name}</outputDirectory>
+ <fileMode>644</fileMode>
+ <excludes>
+ <exclude>*.sh</exclude>
+ </excludes>
+ </fileSet>
+ </fileSets>
+
+
+
+</assembly>
diff --git a/adaptors/base/http/installer/src/assembly/assemble_mvnrepo_zip.xml b/adaptors/base/http/installer/src/assembly/assemble_mvnrepo_zip.xml
new file mode 100644
index 000000000..35e79db18
--- /dev/null
+++ b/adaptors/base/http/installer/src/assembly/assemble_mvnrepo_zip.xml
@@ -0,0 +1,49 @@
+<!--
+ ============LICENSE_START=======================================================
+ openECOMP : SDN-C
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property. All rights
+ reserved.
+ ================================================================================
+ 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.
+ ============LICENSE_END=========================================================
+ -->
+
+<!-- Defines how we build the .zip file which is our distribution. -->
+
+<assembly
+ xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
+ <id>repo</id>
+ <formats>
+ <format>zip</format>
+ </formats>
+
+ <!-- we want "system" and related files right at the root level
+ as this file is suppose to be unzip on top of a karaf
+ distro. -->
+ <includeBaseDirectory>false</includeBaseDirectory>
+
+ <fileSets>
+ <fileSet>
+ <directory>target/assembly/</directory>
+ <outputDirectory>.</outputDirectory>
+ <excludes>
+ </excludes>
+ </fileSet>
+ </fileSets>
+
+
+
+</assembly>
diff --git a/adaptors/base/http/installer/src/main/resources/scripts/install-feature.sh b/adaptors/base/http/installer/src/main/resources/scripts/install-feature.sh
new file mode 100644
index 000000000..6e3d4169d
--- /dev/null
+++ b/adaptors/base/http/installer/src/main/resources/scripts/install-feature.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+
+###
+# ============LICENSE_START=======================================================
+# openECOMP : SDN-C
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights
+# reserved.
+# ================================================================================
+# 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.
+# ============LICENSE_END=========================================================
+###
+
+ODL_HOME=${ODL_HOME:-/opt/opendaylight/current}
+ODL_KARAF_CLIENT=${ODL_KARAF_CLIENT:-${ODL_HOME}/bin/client}
+INSTALLERDIR=$(dirname $0)
+
+REPOZIP=${INSTALLERDIR}/${features.boot}-${project.version}.zip
+
+if [ -f ${REPOZIP} ]
+then
+ unzip -nd ${ODL_HOME} ${REPOZIP}
+else
+ echo "ERROR : repo zip ($REPOZIP) not found"
+ exit 1
+fi
+
+${ODL_KARAF_CLIENT} feature:repo-add ${features.repositories}
+${ODL_KARAF_CLIENT} feature:install ${features.boot}
diff --git a/adaptors/base/http/pom.xml b/adaptors/base/http/pom.xml
new file mode 100644
index 000000000..05840986d
--- /dev/null
+++ b/adaptors/base/http/pom.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>odlparent-lite</artifactId>
+ <version>2.1.0</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.adaptors.base</groupId>
+ <artifactId>http</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>pom</packaging>
+
+ <modules>
+ <module>provider</module>
+ <module>installer</module>
+ </modules>
+</project>
diff --git a/adaptors/base/http/provider/pom.xml b/adaptors/base/http/provider/pom.xml
new file mode 100644
index 000000000..5a3642fd2
--- /dev/null
+++ b/adaptors/base/http/provider/pom.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>binding-parent</artifactId>
+ <version>2.1.0</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.adaptors</groupId>
+ <artifactId>base-http-provider</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>bundle</packaging>
+
+ <dependencies>
+ <dependency>
+ <groupId>javax.ws.rs</groupId>
+ <artifactId>javax.ws.rs-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.core</groupId>
+ <artifactId>jersey-client</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.logging-analytics</groupId>
+ <artifactId>logging-filter-base</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/adaptors/base/http/provider/src/main/java/org/onap/ccsdk/sli/adaptors/base/http/AbstractHttpAdapter.java b/adaptors/base/http/provider/src/main/java/org/onap/ccsdk/sli/adaptors/base/http/AbstractHttpAdapter.java
new file mode 100644
index 000000000..cc6f06a4d
--- /dev/null
+++ b/adaptors/base/http/provider/src/main/java/org/onap/ccsdk/sli/adaptors/base/http/AbstractHttpAdapter.java
@@ -0,0 +1,114 @@
+package org.onap.ccsdk.sli.adaptors.base.http;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.Base64;
+import java.util.Properties;
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.SSLSession;
+import javax.ws.rs.client.ClientBuilder;
+import org.onap.logging.filter.base.MetricLogClientFilter;
+import org.onap.logging.filter.base.PayloadLoggingClientFilter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public abstract class AbstractHttpAdapter {
+ protected static final String SDNC_CONFIG_DIR = "SDNC_CONFIG_DIR";
+ private static final String SDNC_CONFIG_DIR_DEFAULT = "/opt/sdnc/data/properties";
+ protected static final int DEFAULT_HTTP_CONNECT_TIMEOUT_MS = 60000; // 1 minute
+ protected static final int DEFAULT_HTTP_READ_TIMEOUT_MS = 1800000; // 30 minutes
+ protected ClientBuilder clientBuilder;
+
+ private static final Logger logger = LoggerFactory.getLogger(AbstractHttpAdapter.class);
+
+ public AbstractHttpAdapter() {
+ clientBuilder = ClientBuilder.newBuilder();
+ setTimeouts();
+ defaultHostNameVerifier();
+ }
+
+ private void defaultHostNameVerifier() {
+ clientBuilder.hostnameVerifier(new HostnameVerifier() {
+ @Override
+ public boolean verify(String hostname, SSLSession session) {
+ return true;
+ }
+ });
+ }
+
+ protected void enableMetricLogging() {
+ clientBuilder.register(new MetricLogClientFilter());
+ }
+
+ protected void enablePayloadLogging() {
+ clientBuilder.register(new PayloadLoggingClientFilter());
+ }
+
+ private void setTimeouts() {
+ Integer httpReadTimeout = readOptionalInteger("HTTP_READ_TIMEOUT_MS", DEFAULT_HTTP_READ_TIMEOUT_MS);
+ Integer httpConnectTimeout = readOptionalInteger("HTTP_CONNECT_TIMEOUT_MS", DEFAULT_HTTP_CONNECT_TIMEOUT_MS);
+
+ // restore once we migrate to once we migrate to javax.ws.rs-api 2.1
+ // clientBuilder.connectTimeout(30, TimeUnit.SECONDS);
+ // clientBuilder.readTimeout(30, TimeUnit.SECONDS);
+
+ // Setting jersey specific properties is ugly, such behavior should be removed
+ // once we migrate to javax.ws.rs-api 2.1
+ clientBuilder.property("jersey.config.client.readTimeout", httpReadTimeout);
+ clientBuilder.property("jersey.config.client.connectTimeout", httpConnectTimeout);
+ }
+
+ public Properties getProperties(String propertiesFileName) throws FileNotFoundException, IOException {
+ // Check System property, then environment variable then default if null
+ String propDir = System.getProperty(SDNC_CONFIG_DIR);
+ if (propDir == null || propDir.length() < 1) {
+ propDir = System.getenv(SDNC_CONFIG_DIR);
+ }
+ if (propDir == null || propDir.length() < 1) {
+ propDir = SDNC_CONFIG_DIR_DEFAULT;
+ }
+ Properties properties = new Properties();
+ // forward slash is checked to support path src/test/resources on windows machine
+ if (!propDir.endsWith(File.separator) && !propDir.endsWith("/")) {
+ propDir = propDir + File.separator;
+ }
+ String path = propDir + propertiesFileName;
+ properties.load(new FileInputStream(path));
+ logger.trace("Initialized properties from ({}) properties ({})", path, properties);
+ return properties;
+ }
+
+ protected void addBasicAuthCredentials(String username, String password) {
+ String basicAuthValue = getBasicAuthValue(username,password);
+ clientBuilder.register(new BasicAuthFilter(basicAuthValue));
+ }
+
+ protected String getBasicAuthValue(String userName, String password) {
+ String token = userName + ":" + password;
+ try {
+ return "Basic " + Base64.getEncoder().encodeToString(token.getBytes());
+ } catch (Exception e) {
+ logger.error("getBasicAuthValue threw an exception, credentials will be null", e);
+ }
+ return null;
+ }
+
+ public ClientBuilder getClientBuilder() {
+ return clientBuilder;
+ }
+
+ private Integer readOptionalInteger(String propertyName, Integer defaultValue) {
+ String stringValue = System.getProperty(propertyName);
+ if (stringValue != null && stringValue.length() > 0) {
+ try {
+ return Integer.valueOf(stringValue);
+ } catch (NumberFormatException e) {
+ logger.warn("property " + propertyName + " had the value " + stringValue + " that could not be converted to an Integer, default " + defaultValue + " will be used instead", e);
+ }
+ }
+ return defaultValue;
+ }
+
+}
diff --git a/adaptors/base/http/provider/src/main/java/org/onap/ccsdk/sli/adaptors/base/http/BasicAuthFilter.java b/adaptors/base/http/provider/src/main/java/org/onap/ccsdk/sli/adaptors/base/http/BasicAuthFilter.java
new file mode 100644
index 000000000..5d3d463c9
--- /dev/null
+++ b/adaptors/base/http/provider/src/main/java/org/onap/ccsdk/sli/adaptors/base/http/BasicAuthFilter.java
@@ -0,0 +1,22 @@
+package org.onap.ccsdk.sli.adaptors.base.http;
+
+import java.io.IOException;
+
+import javax.ws.rs.client.ClientRequestContext;
+import javax.ws.rs.client.ClientRequestFilter;
+import javax.ws.rs.core.MultivaluedMap;
+
+public class BasicAuthFilter implements ClientRequestFilter {
+ private final String basicAuthValue;
+
+ public BasicAuthFilter(String basicAuthValue) {
+ this.basicAuthValue = basicAuthValue;
+ }
+
+ public void filter(ClientRequestContext requestContext) throws IOException {
+ MultivaluedMap<String, Object> headers = requestContext.getHeaders();
+ headers.add("Authorization", basicAuthValue);
+ }
+
+
+}
diff --git a/adaptors/base/http/provider/src/test/java/org/onap/ccsdk/sli/adaptors/base/http/AbstractHttpAdapterTest.java b/adaptors/base/http/provider/src/test/java/org/onap/ccsdk/sli/adaptors/base/http/AbstractHttpAdapterTest.java
new file mode 100644
index 000000000..d0973d90e
--- /dev/null
+++ b/adaptors/base/http/provider/src/test/java/org/onap/ccsdk/sli/adaptors/base/http/AbstractHttpAdapterTest.java
@@ -0,0 +1,44 @@
+package org.onap.ccsdk.sli.adaptors.base.http;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.util.Properties;
+import java.util.Set;
+
+import javax.ws.rs.client.Client;
+
+import org.junit.Test;
+
+public class AbstractHttpAdapterTest {
+
+ public class TestAdapter extends AbstractHttpAdapter {
+
+ }
+
+ @Test
+ public void checkTimeouts() throws Exception {
+ TestAdapter adapter = new TestAdapter();
+ Client client = adapter.getClientBuilder().build();
+ assertNotNull(client.getConfiguration().getProperty("jersey.config.client.readTimeout"));
+ assertNotNull(client.getConfiguration().getProperty("jersey.config.client.connectTimeout"));
+ }
+
+ @Test
+ public void propertiesTest() throws Exception {
+ System.setProperty(AbstractHttpAdapter.SDNC_CONFIG_DIR, "src/test/resources/");
+ TestAdapter adapter = new TestAdapter();
+ Properties props = adapter.getProperties("testprops.properties");
+ assertNotNull(props);
+ assertEquals("world", props.get("hello"));
+ }
+
+ @Test
+ public void basicAuthFilter() throws Exception {
+ TestAdapter adapter = new TestAdapter();
+ adapter.addBasicAuthCredentials("hello", "world");
+ Set<Object> objs = adapter.getClientBuilder().getConfiguration().getInstances();
+ assertEquals(BasicAuthFilter.class,objs.iterator().next().getClass());
+ }
+
+}
diff --git a/adaptors/base/http/provider/src/test/java/org/onap/ccsdk/sli/adaptors/base/http/BasicAuthFilterTest.java b/adaptors/base/http/provider/src/test/java/org/onap/ccsdk/sli/adaptors/base/http/BasicAuthFilterTest.java
new file mode 100644
index 000000000..d9d552dac
--- /dev/null
+++ b/adaptors/base/http/provider/src/test/java/org/onap/ccsdk/sli/adaptors/base/http/BasicAuthFilterTest.java
@@ -0,0 +1,20 @@
+package org.onap.ccsdk.sli.adaptors.base.http;
+
+import static org.junit.Assert.assertNotNull;
+
+import org.junit.Test;
+
+public class BasicAuthFilterTest {
+
+ @Test
+ public void notNullParameters() throws Exception {
+ BasicAuthFilter myFilter = new BasicAuthFilter("hello");
+ assertNotNull(myFilter);
+ }
+
+ @Test
+ public void nullParameters() throws Exception {
+ BasicAuthFilter myFilter = new BasicAuthFilter(null);
+ assertNotNull(myFilter);
+ }
+}
diff --git a/adaptors/base/http/provider/src/test/resources/testprops.properties b/adaptors/base/http/provider/src/test/resources/testprops.properties
new file mode 100644
index 000000000..3f602680e
--- /dev/null
+++ b/adaptors/base/http/provider/src/test/resources/testprops.properties
@@ -0,0 +1 @@
+hello = world \ No newline at end of file
diff --git a/adaptors/base/pom.xml b/adaptors/base/pom.xml
new file mode 100644
index 000000000..a8e6b9193
--- /dev/null
+++ b/adaptors/base/pom.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>odlparent-lite</artifactId>
+ <version>2.1.0</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.adaptors</groupId>
+ <artifactId>base-parent</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>pom</packaging>
+
+ <modules>
+ <module>http</module>
+ </modules>
+</project>
diff --git a/adaptors/features/ccsdk-aai-service/pom.xml b/adaptors/features/ccsdk-aai-service/pom.xml
new file mode 100644
index 000000000..2870ea50f
--- /dev/null
+++ b/adaptors/features/ccsdk-aai-service/pom.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>single-feature-parent</artifactId>
+ <version>2.1.0</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.adaptors</groupId>
+ <artifactId>ccsdk-aai-service</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>feature</packaging>
+
+ <name>ccsdk-sli-adaptors :: aai-service :: ${project.artifactId}</name>
+
+ <properties>
+ <ccsdk.sli.adaptors.version>${project.version}</ccsdk.sli.adaptors.version>
+ </properties>
+
+ <dependencies>
+
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>ccsdk-sli</artifactId>
+ <version>${ccsdk.sli.core.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>aai-service-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+
+ </dependencies>
+</project>
diff --git a/adaptors/features/ccsdk-ansible-adapter/pom.xml b/adaptors/features/ccsdk-ansible-adapter/pom.xml
new file mode 100644
index 000000000..652a3ee59
--- /dev/null
+++ b/adaptors/features/ccsdk-ansible-adapter/pom.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>single-feature-parent</artifactId>
+ <version>2.1.0</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.adaptors</groupId>
+ <artifactId>ccsdk-ansible-adapter</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>feature</packaging>
+
+ <name>ccsdk-sli-adaptors :: ansible-adapter:: ${project.artifactId}</name>
+
+ <properties>
+ <ccsdk.sli.adaptors.version>${project.version}</ccsdk.sli.adaptors.version>
+ </properties>
+
+ <dependencies>
+
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>ccsdk-sli</artifactId>
+ <version>${ccsdk.sli.core.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>ansible-adapter-bundle</artifactId>
+ <version>${project.version}</version>
+ <exclusions>
+ <exclusion>
+ <artifactId>powermock-api-mockito</artifactId>
+ <groupId>org.powermock</groupId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+
+
+ </dependencies>
+</project>
diff --git a/adaptors/features/ccsdk-base-http/pom.xml b/adaptors/features/ccsdk-base-http/pom.xml
new file mode 100644
index 000000000..4f83f5de1
--- /dev/null
+++ b/adaptors/features/ccsdk-base-http/pom.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>single-feature-parent</artifactId>
+ <version>2.1.0</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.adaptors</groupId>
+ <artifactId>ccsdk-base-http</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>feature</packaging>
+
+ <name>ccsdk-sli-adaptors :: base-http :: ${project.artifactId}</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>base-http-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/adaptors/features/ccsdk-mdsal-resource/pom.xml b/adaptors/features/ccsdk-mdsal-resource/pom.xml
new file mode 100644
index 000000000..fc5b9ae2f
--- /dev/null
+++ b/adaptors/features/ccsdk-mdsal-resource/pom.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>single-feature-parent</artifactId>
+ <version>2.1.0</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.adaptors</groupId>
+ <artifactId>ccsdk-mdsal-resource</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>feature</packaging>
+
+ <name>ccsdk-sli-adaptors :: mdsal-resource :: ${project.artifactId}</name>
+
+ <properties>
+ <ccsdk.sli.adaptors.version>${project.version}</ccsdk.sli.adaptors.version>
+ </properties>
+
+ <dependencies>
+
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>ccsdk-sli</artifactId>
+ <version>${ccsdk.sli.core.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>mdsal-resource-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ </dependencies>
+</project>
diff --git a/adaptors/features/ccsdk-messagerouter-consumer/pom.xml b/adaptors/features/ccsdk-messagerouter-consumer/pom.xml
new file mode 100755
index 000000000..0030d92c8
--- /dev/null
+++ b/adaptors/features/ccsdk-messagerouter-consumer/pom.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>single-feature-parent</artifactId>
+ <version>2.1.0</version>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.adaptors.messagerouter</groupId>
+ <artifactId>ccsdk-messagerouter-consumer</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>feature</packaging>
+
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>consumer.api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>consumer.provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/adaptors/features/ccsdk-messagerouter-publisher/pom.xml b/adaptors/features/ccsdk-messagerouter-publisher/pom.xml
new file mode 100755
index 000000000..fcedcace0
--- /dev/null
+++ b/adaptors/features/ccsdk-messagerouter-publisher/pom.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>single-feature-parent</artifactId>
+ <version>2.1.0</version>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.adaptors.messagerouter</groupId>
+ <artifactId>ccsdk-messagerouter-publisher</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>feature</packaging>
+
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>publisher.api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>publisher.provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/adaptors/features/ccsdk-netbox-client/pom.xml b/adaptors/features/ccsdk-netbox-client/pom.xml
new file mode 100644
index 000000000..cff225740
--- /dev/null
+++ b/adaptors/features/ccsdk-netbox-client/pom.xml
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2018 AT&T, Bell Canada
+
+ 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.
+ -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>single-feature-parent</artifactId>
+ <version>2.1.0</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.adaptors</groupId>
+ <artifactId>ccsdk-netbox-client</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>feature</packaging>
+
+ <name>ccsdk-sli-adaptors :: netbox-client :: ${project.artifactId}</name>
+
+ <properties>
+ <ccsdk.sli.adaptors.version>${project.version}</ccsdk.sli.adaptors.version>
+ </properties>
+
+ <dependencies>
+
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>ccsdk-sli</artifactId>
+ <version>${ccsdk.sli.core.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>ccsdk-dblib</artifactId>
+ <version>${ccsdk.sli.core.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>netbox-client-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/adaptors/features/ccsdk-resource-assignment/pom.xml b/adaptors/features/ccsdk-resource-assignment/pom.xml
new file mode 100644
index 000000000..d73a1acda
--- /dev/null
+++ b/adaptors/features/ccsdk-resource-assignment/pom.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>single-feature-parent</artifactId>
+ <version>2.1.0</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.adaptors</groupId>
+ <artifactId>ccsdk-resource-assignment</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>feature</packaging>
+
+ <name>ccsdk-sli-adaptors :: resource-assignment :: ${project.artifactId}</name>
+
+ <properties>
+ <ccsdk.sli.adaptors.version>${project.version}</ccsdk.sli.adaptors.version>
+ </properties>
+
+ <dependencies>
+
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>ccsdk-sli</artifactId>
+ <version>${ccsdk.sli.core.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>ccsdk-dblib</artifactId>
+ <version>${ccsdk.sli.core.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>resource-assignment-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+
+ </dependencies>
+</project>
diff --git a/adaptors/features/ccsdk-saltstack-adapter/pom.xml b/adaptors/features/ccsdk-saltstack-adapter/pom.xml
new file mode 100644
index 000000000..3ac7fcf14
--- /dev/null
+++ b/adaptors/features/ccsdk-saltstack-adapter/pom.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>single-feature-parent</artifactId>
+ <version>2.1.0</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.adaptors</groupId>
+ <artifactId>ccsdk-saltstack-adapter</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>feature</packaging>
+
+ <name>ccsdk-sli-adaptors :: saltstack-adapter:: ${project.artifactId}</name>
+
+ <properties>
+ <ccsdk.sli.adaptors.version>${project.version}</ccsdk.sli.adaptors.version>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>ccsdk-sli</artifactId>
+ <version>${ccsdk.sli.core.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>saltstack-adapter-provider</artifactId>
+ <version>${project.version}</version>
+
+ <exclusions>
+ <exclusion>
+ <artifactId>powermock-api-mockito</artifactId>
+ <groupId>org.powermock</groupId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/adaptors/features/ccsdk-sli-adaptors-all/pom.xml b/adaptors/features/ccsdk-sli-adaptors-all/pom.xml
new file mode 100644
index 000000000..821f1cb12
--- /dev/null
+++ b/adaptors/features/ccsdk-sli-adaptors-all/pom.xml
@@ -0,0 +1,84 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>single-feature-parent</artifactId>
+ <version>2.1.0</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.adaptors</groupId>
+ <artifactId>ccsdk-sli-adaptors-all</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>feature</packaging>
+
+ <name>ccsdk-sli-adaptors :: features :: ${project.artifactId}</name>
+
+ <properties>
+ <ccsdk.sli.adaptors.version>${project.version}</ccsdk.sli.adaptors.version>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>ccsdk-aai-service</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>ccsdk-ansible-adapter</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ </dependency>
+ <!-- saltstack-adapter needs to be changed to remove dependency on app-c code
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>ccsdk-saltstack-adapter</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ </dependency>
+ -->
+
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>ccsdk-netbox-client</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>ccsdk-mdsal-resource</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>ccsdk-resource-assignment</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>ccsdk-sql-resource</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}.messagerouter</groupId>
+ <artifactId>ccsdk-messagerouter-publisher</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/adaptors/features/ccsdk-sql-resource/pom.xml b/adaptors/features/ccsdk-sql-resource/pom.xml
new file mode 100644
index 000000000..d8ff07047
--- /dev/null
+++ b/adaptors/features/ccsdk-sql-resource/pom.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>single-feature-parent</artifactId>
+ <version>2.1.0</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.adaptors</groupId>
+ <artifactId>ccsdk-sql-resource</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>feature</packaging>
+
+ <name>ccsdk-sli-adaptors :: sql-resource :: ${project.artifactId}</name>
+
+ <properties>
+ <ccsdk.sli.adaptors.version>${project.version}</ccsdk.sli.adaptors.version>
+ </properties>
+
+ <dependencies>
+
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>ccsdk-sli</artifactId>
+ <version>${ccsdk.sli.core.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>ccsdk-dblib</artifactId>
+ <version>${ccsdk.sli.core.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>sql-resource-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ </dependencies>
+</project>
diff --git a/adaptors/features/features-sli-adaptors/pom.xml b/adaptors/features/features-sli-adaptors/pom.xml
new file mode 100644
index 000000000..5e98da302
--- /dev/null
+++ b/adaptors/features/features-sli-adaptors/pom.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>feature-repo-parent</artifactId>
+ <version>2.1.0</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.adaptors</groupId>
+ <artifactId>features-sli-adaptors</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>feature</packaging>
+
+ <name>ccsdk-sli-adaptors :: features :: ${project.artifactId}</name>
+
+ <properties>
+ <ccsdk.sli.adaptors.version>${project.version}</ccsdk.sli.adaptors.version>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>ccsdk-sli-adaptors-all</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ </dependency>
+
+ </dependencies>
+</project>
diff --git a/adaptors/features/installer/pom.xml b/adaptors/features/installer/pom.xml
new file mode 100755
index 000000000..fab35b5f0
--- /dev/null
+++ b/adaptors/features/installer/pom.xml
@@ -0,0 +1,265 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>odlparent-lite</artifactId>
+ <version>2.1.0</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.adaptors</groupId>
+ <artifactId>sliadaptors-features-installer</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>pom</packaging>
+
+ <name>ccsdk-sli-adaptors :: features :: ${project.artifactId}</name>
+
+ <properties>
+ <application.name>ccsdk-sli-adaptors-all</application.name>
+ <features.boot>${application.name}</features.boot>
+ <features.repositories>mvn:org.onap.ccsdk.sli.adaptors/${features.boot}/${project.version}/xml/features</features.repositories>
+ <include.transitive.dependencies>false</include.transitive.dependencies>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.adaptors</groupId>
+ <artifactId>ccsdk-aai-service</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ <exclusions>
+ <exclusion>
+ <groupId>*</groupId>
+ <artifactId>*</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.adaptors</groupId>
+ <artifactId>ccsdk-ansible-adapter</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ <exclusions>
+ <exclusion>
+ <groupId>*</groupId>
+ <artifactId>*</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.adaptors</groupId>
+ <artifactId>ccsdk-base-http</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ <exclusions>
+ <exclusion>
+ <groupId>*</groupId>
+ <artifactId>*</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.adaptors</groupId>
+ <artifactId>ccsdk-mdsal-resource</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ <exclusions>
+ <exclusion>
+ <groupId>*</groupId>
+ <artifactId>*</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.adaptors.messagerouter</groupId>
+ <artifactId>ccsdk-messagerouter-consumer</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ <exclusions>
+ <exclusion>
+ <groupId>*</groupId>
+ <artifactId>*</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.adaptors.messagerouter</groupId>
+ <artifactId>ccsdk-messagerouter-publisher</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ <exclusions>
+ <exclusion>
+ <groupId>*</groupId>
+ <artifactId>*</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.adaptors</groupId>
+ <artifactId>ccsdk-netbox-client</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ <exclusions>
+ <exclusion>
+ <groupId>*</groupId>
+ <artifactId>*</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.adaptors</groupId>
+ <artifactId>ccsdk-resource-assignment</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ <exclusions>
+ <exclusion>
+ <groupId>*</groupId>
+ <artifactId>*</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.adaptors</groupId>
+ <artifactId>ccsdk-saltstack-adapter</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ <exclusions>
+ <exclusion>
+ <groupId>*</groupId>
+ <artifactId>*</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.adaptors</groupId>
+ <artifactId>ccsdk-sql-resource</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ <exclusions>
+ <exclusion>
+ <groupId>*</groupId>
+ <artifactId>*</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.adaptors</groupId>
+ <artifactId>${application.name}</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ <exclusions>
+ <exclusion>
+ <groupId>*</groupId>
+ <artifactId>*</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+
+
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>maven-repo-zip</id>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ <phase>package</phase>
+ <configuration>
+ <attach>true</attach>
+ <finalName>stage/${application.name}-${project.version}</finalName>
+ <descriptors>
+ <descriptor>src/assembly/assemble_mvnrepo_zip.xml</descriptor>
+ </descriptors>
+ <appendAssemblyId>true</appendAssemblyId>
+ </configuration>
+ </execution>
+ <execution>
+ <id>installer-zip</id>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ <phase>package</phase>
+ <configuration>
+ <attach>true</attach>
+ <finalName>${application.name}-${project.version}-installer</finalName>
+ <descriptors>
+ <descriptor>src/assembly/assemble_installer_zip.xml</descriptor>
+ </descriptors>
+ <appendAssemblyId>false</appendAssemblyId>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>copy-dependencies</id>
+ <goals>
+ <goal>copy-dependencies</goal>
+ </goals>
+ <phase>prepare-package</phase>
+ <configuration>
+ <transitive>false</transitive>
+ <outputDirectory>${project.build.directory}/assembly/system</outputDirectory>
+ <overWriteReleases>false</overWriteReleases>
+ <overWriteSnapshots>true</overWriteSnapshots>
+ <overWriteIfNewer>true</overWriteIfNewer>
+ <useRepositoryLayout>true</useRepositoryLayout>
+ <addParentPoms>false</addParentPoms>
+ <copyPom>false</copyPom>
+ <includeGroupIds>org.onap.ccsdk.sli.adaptors</includeGroupIds>
+ <scope>provided</scope>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <artifactId>maven-resources-plugin</artifactId>
+ <version>2.6</version>
+ <executions>
+ <execution>
+ <id>copy-version</id>
+ <goals>
+ <goal>copy-resources</goal>
+ </goals><!-- here the phase you need -->
+ <phase>validate</phase>
+ <configuration>
+ <outputDirectory>${basedir}/target/stage</outputDirectory>
+ <resources>
+ <resource>
+ <directory>src/main/resources/scripts</directory>
+ <includes>
+ <include>install-feature.sh</include>
+ </includes>
+ <filtering>true</filtering>
+ </resource>
+ </resources>
+ </configuration>
+ </execution>
+
+ </executions>
+ </plugin>
+
+ </plugins>
+ </build>
+</project>
diff --git a/adaptors/features/installer/src/assembly/assemble_installer_zip.xml b/adaptors/features/installer/src/assembly/assemble_installer_zip.xml
new file mode 100755
index 000000000..a6a22a9ba
--- /dev/null
+++ b/adaptors/features/installer/src/assembly/assemble_installer_zip.xml
@@ -0,0 +1,39 @@
+<!-- Defines how we build the .zip file which is our distribution. -->
+
+<assembly
+ xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
+ <id>bin</id>
+
+ <formats>
+ <format>zip</format>
+ </formats>
+
+ <!-- we want "system" and related files right at the root level
+ as this file is suppose to be unzip on top of a karaf
+ distro. -->
+ <includeBaseDirectory>false</includeBaseDirectory>
+
+ <fileSets>
+ <fileSet>
+ <directory>target/stage/</directory>
+ <outputDirectory>${application.name}</outputDirectory>
+ <fileMode>755</fileMode>
+ <includes>
+ <include>*.sh</include>
+ </includes>
+ </fileSet>
+ <fileSet>
+ <directory>target/stage/</directory>
+ <outputDirectory>${application.name}</outputDirectory>
+ <fileMode>644</fileMode>
+ <excludes>
+ <exclude>*.sh</exclude>
+ </excludes>
+ </fileSet>
+ </fileSets>
+
+
+
+</assembly>
diff --git a/adaptors/features/installer/src/assembly/assemble_mvnrepo_zip.xml b/adaptors/features/installer/src/assembly/assemble_mvnrepo_zip.xml
new file mode 100755
index 000000000..86b07f1f3
--- /dev/null
+++ b/adaptors/features/installer/src/assembly/assemble_mvnrepo_zip.xml
@@ -0,0 +1,29 @@
+<!-- Defines how we build the .zip file which is our distribution. -->
+
+<assembly
+ xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
+ <id>repo</id>
+
+ <formats>
+ <format>zip</format>
+ </formats>
+
+ <!-- we want "system" and related files right at the root level
+ as this file is suppose to be unzip on top of a karaf
+ distro. -->
+ <includeBaseDirectory>false</includeBaseDirectory>
+
+ <fileSets>
+ <fileSet>
+ <directory>target/assembly/</directory>
+ <outputDirectory>.</outputDirectory>
+ <excludes>
+ </excludes>
+ </fileSet>
+ </fileSets>
+
+
+
+</assembly>
diff --git a/adaptors/features/installer/src/main/resources/scripts/install-feature.sh b/adaptors/features/installer/src/main/resources/scripts/install-feature.sh
new file mode 100644
index 000000000..e16e79a12
--- /dev/null
+++ b/adaptors/features/installer/src/main/resources/scripts/install-feature.sh
@@ -0,0 +1,18 @@
+#!/bin/bash
+
+ODL_HOME=${ODL_HOME:-/opt/opendaylight/current}
+ODL_KARAF_CLIENT=${ODL_KARAF_CLIENT:-${ODL_HOME}/bin/client}
+INSTALLERDIR=$(dirname $0)
+
+REPOZIP=${INSTALLERDIR}/${features.boot}-${project.version}.zip
+
+if [ -f ${REPOZIP} ]
+then
+ unzip -d ${ODL_HOME} ${REPOZIP}
+else
+ echo "ERROR : repo zip ($REPOZIP) not found"
+ exit 1
+fi
+
+${ODL_KARAF_CLIENT} feature:repo-add ${features.repositories}
+${ODL_KARAF_CLIENT} feature:install ${features.boot}
diff --git a/adaptors/features/pom.xml b/adaptors/features/pom.xml
new file mode 100755
index 000000000..e57a639ac
--- /dev/null
+++ b/adaptors/features/pom.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>odlparent-lite</artifactId>
+ <version>2.1.0</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.adaptors</groupId>
+ <artifactId>sliadaptors-feature-aggregator</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>pom</packaging>
+
+ <name>ccsdk-sli-adaptors :: features</name>
+
+ <modules>
+ <module>ccsdk-aai-service</module>
+ <module>ccsdk-ansible-adapter</module>
+ <module>ccsdk-base-http</module>
+ <module>ccsdk-mdsal-resource</module>
+ <module>ccsdk-messagerouter-consumer</module>
+ <module>ccsdk-messagerouter-publisher</module>
+ <module>ccsdk-netbox-client</module>
+ <module>ccsdk-resource-assignment</module>
+ <module>ccsdk-saltstack-adapter</module>
+ <module>ccsdk-sql-resource</module>
+ <module>ccsdk-sli-adaptors-all</module>
+ <module>features-sli-adaptors</module>
+ <module>installer</module>
+ </modules>
+</project>
diff --git a/adaptors/mdsal-resource/.gitignore b/adaptors/mdsal-resource/.gitignore
new file mode 100755
index 000000000..b73caf31e
--- /dev/null
+++ b/adaptors/mdsal-resource/.gitignore
@@ -0,0 +1,34 @@
+#####standard .git ignore entries#####
+
+## IDE Specific Files ##
+org.eclipse.core.resources.prefs
+.classpath
+.project
+.settings
+.idea
+.externalToolBuilders
+maven-eclipse.xml
+workspace
+
+## Compilation Files ##
+*.class
+**/target
+target
+target-ide
+MANIFEST.MF
+
+## Misc Ignores (OS specific etc) ##
+bin/
+dist
+*~
+*.ipr
+*.iml
+*.iws
+classes
+out/
+.DS_STORE
+.metadata
+
+## Folders which contain auto generated source code ##
+yang-gen-config
+yang-gen-sal
diff --git a/adaptors/mdsal-resource/installer/pom.xml b/adaptors/mdsal-resource/installer/pom.xml
new file mode 100755
index 000000000..bb92cbff3
--- /dev/null
+++ b/adaptors/mdsal-resource/installer/pom.xml
@@ -0,0 +1,127 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>odlparent-lite</artifactId>
+ <version>2.1.0</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.adaptors</groupId>
+ <artifactId>mdsal-resource-installer</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>pom</packaging>
+
+ <name>ccsdk-sli-adaptors :: mdsal-resource :: ${project.artifactId}</name>
+
+ <properties>
+ <application.name>ccsdk-mdsal-resource</application.name>
+ <features.boot>${application.name}</features.boot>
+ <features.repositories>mvn:org.onap.ccsdk.sli.adaptors/${features.boot}/${project.version}/xml/features</features.repositories>
+ <include.transitive.dependencies>false</include.transitive.dependencies>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.adaptors</groupId>
+ <artifactId>mdsal-resource-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <version>2.6</version>
+ <executions>
+ <execution>
+ <id>maven-repo-zip</id>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ <phase>package</phase>
+ <configuration>
+ <attach>true</attach>
+ <finalName>stage/${application.name}-${project.version}</finalName>
+ <descriptors>
+ <descriptor>src/assembly/assemble_mvnrepo_zip.xml</descriptor>
+ </descriptors>
+ <appendAssemblyId>true</appendAssemblyId>
+ </configuration>
+ </execution>
+ <execution>
+ <id>installer-zip</id>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ <phase>package</phase>
+ <configuration>
+ <attach>true</attach>
+ <finalName>${application.name}-${project.version}-installer</finalName>
+ <descriptors>
+ <descriptor>src/assembly/assemble_installer_zip.xml</descriptor>
+ </descriptors>
+ <appendAssemblyId>false</appendAssemblyId>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>copy-dependencies</id>
+ <goals>
+ <goal>copy-dependencies</goal>
+ </goals>
+ <phase>prepare-package</phase>
+ <configuration>
+ <transitive>false</transitive>
+ <outputDirectory>${project.build.directory}/assembly/system</outputDirectory>
+ <overWriteReleases>false</overWriteReleases>
+ <overWriteSnapshots>true</overWriteSnapshots>
+ <overWriteIfNewer>true</overWriteIfNewer>
+ <useRepositoryLayout>true</useRepositoryLayout>
+ <addParentPoms>false</addParentPoms>
+ <copyPom>false</copyPom>
+ <includeGroupIds>org.onap.ccsdk.sli.adaptors</includeGroupIds>
+ <scope>provided</scope>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <artifactId>maven-resources-plugin</artifactId>
+ <version>2.6</version>
+ <executions>
+ <execution>
+ <id>copy-version</id>
+ <goals>
+ <goal>copy-resources</goal>
+ </goals><!-- here the phase you need -->
+ <phase>validate</phase>
+ <configuration>
+ <outputDirectory>${basedir}/target/stage</outputDirectory>
+ <resources>
+ <resource>
+ <directory>src/main/resources/scripts</directory>
+ <includes>
+ <include>install-feature.sh</include>
+ </includes>
+ <filtering>true</filtering>
+ </resource>
+ </resources>
+ </configuration>
+ </execution>
+
+ </executions>
+ </plugin>
+
+ </plugins>
+ </build>
+</project>
diff --git a/adaptors/mdsal-resource/installer/src/assembly/assemble_installer_zip.xml b/adaptors/mdsal-resource/installer/src/assembly/assemble_installer_zip.xml
new file mode 100644
index 000000000..b6fd65582
--- /dev/null
+++ b/adaptors/mdsal-resource/installer/src/assembly/assemble_installer_zip.xml
@@ -0,0 +1,59 @@
+<!--
+ ============LICENSE_START=======================================================
+ openECOMP : SDN-C
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property. All rights
+ reserved.
+ ================================================================================
+ 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.
+ ============LICENSE_END=========================================================
+ -->
+
+<!-- Defines how we build the .zip file which is our distribution. -->
+
+<assembly
+ xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
+ <id>installer_zip</id>
+ <formats>
+ <format>zip</format>
+ </formats>
+
+ <!-- we want "system" and related files right at the root level
+ as this file is suppose to be unzip on top of a karaf
+ distro. -->
+ <includeBaseDirectory>false</includeBaseDirectory>
+
+ <fileSets>
+ <fileSet>
+ <directory>target/stage/</directory>
+ <outputDirectory>${application.name}</outputDirectory>
+ <fileMode>755</fileMode>
+ <includes>
+ <include>*.sh</include>
+ </includes>
+ </fileSet>
+ <fileSet>
+ <directory>target/stage/</directory>
+ <outputDirectory>${application.name}</outputDirectory>
+ <fileMode>644</fileMode>
+ <excludes>
+ <exclude>*.sh</exclude>
+ </excludes>
+ </fileSet>
+ </fileSets>
+
+
+
+</assembly>
diff --git a/adaptors/mdsal-resource/installer/src/assembly/assemble_mvnrepo_zip.xml b/adaptors/mdsal-resource/installer/src/assembly/assemble_mvnrepo_zip.xml
new file mode 100644
index 000000000..9cdc78879
--- /dev/null
+++ b/adaptors/mdsal-resource/installer/src/assembly/assemble_mvnrepo_zip.xml
@@ -0,0 +1,49 @@
+<!--
+ ============LICENSE_START=======================================================
+ openECOMP : SDN-C
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property. All rights
+ reserved.
+ ================================================================================
+ 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.
+ ============LICENSE_END=========================================================
+ -->
+
+<!-- Defines how we build the .zip file which is our distribution. -->
+
+<assembly
+ xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
+ <id>repo</id>
+ <formats>
+ <format>zip</format>
+ </formats>
+
+ <!-- we want "system" and related files right at the root level
+ as this file is suppose to be unzip on top of a karaf
+ distro. -->
+ <includeBaseDirectory>false</includeBaseDirectory>
+
+ <fileSets>
+ <fileSet>
+ <directory>target/assembly/</directory>
+ <outputDirectory>.</outputDirectory>
+ <excludes>
+ </excludes>
+ </fileSet>
+ </fileSets>
+
+
+
+</assembly>
diff --git a/adaptors/mdsal-resource/installer/src/main/resources/scripts/install-feature.sh b/adaptors/mdsal-resource/installer/src/main/resources/scripts/install-feature.sh
new file mode 100644
index 000000000..0eab001d5
--- /dev/null
+++ b/adaptors/mdsal-resource/installer/src/main/resources/scripts/install-feature.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+
+###
+# ============LICENSE_START=======================================================
+# openECOMP : SDN-C
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights
+# reserved.
+# ================================================================================
+# 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.
+# ============LICENSE_END=========================================================
+###
+
+ODL_HOME=${ODL_HOME:-/opt/opendaylight/current}
+ODL_KARAF_CLIENT=${ODL_KARAF_CLIENT:-${ODL_HOME}/bin/client}
+INSTALLERDIR=$(dirname $0)
+
+REPOZIP=${INSTALLERDIR}/${features.boot}-${project.version}.zip
+
+if [ -f ${REPOZIP} ]
+then
+ unzip -d ${ODL_HOME} ${REPOZIP}
+else
+ echo "ERROR : repo zip ($REPOZIP) not found"
+ exit 1
+fi
+
+${ODL_KARAF_CLIENT} feature:repo-add ${features.repositories}
+${ODL_KARAF_CLIENT} feature:install ${features.boot}
diff --git a/adaptors/mdsal-resource/pom.xml b/adaptors/mdsal-resource/pom.xml
new file mode 100755
index 000000000..e770e504c
--- /dev/null
+++ b/adaptors/mdsal-resource/pom.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>odlparent-lite</artifactId>
+ <version>2.1.0</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.adaptors</groupId>
+ <artifactId>mdsal-resource</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>pom</packaging>
+
+ <name>ccsdk-sli-adaptors :: mdsal-resource</name>
+ <description>The MD-SAL resource adaptor allows service logic to access persistent data from MD-SAL config and operational trees</description>
+
+ <modules>
+ <module>provider</module>
+ <module>installer</module>
+ </modules>
+</project>
diff --git a/adaptors/mdsal-resource/provider/pom.xml b/adaptors/mdsal-resource/provider/pom.xml
new file mode 100755
index 000000000..255812b55
--- /dev/null
+++ b/adaptors/mdsal-resource/provider/pom.xml
@@ -0,0 +1,81 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>binding-parent</artifactId>
+ <version>2.1.0</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.adaptors</groupId>
+ <artifactId>mdsal-resource-provider</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>bundle</packaging>
+
+ <name>ccsdk-sli-adaptors :: mdsal-resource :: ${project.artifactId}</name>
+ <url>http://maven.apache.org</url>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <ccsdk.sli.adaptors.version>${project.version}</ccsdk.sli.adaptors.version>
+ </properties>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sli-core-artifacts</artifactId>
+ <version>${ccsdk.sli.core.version}</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+ <dependencies>
+
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sli-common</artifactId>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sli-provider</artifactId>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.core</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>jcl-over-slf4j</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>commons-codec</groupId>
+ <artifactId>commons-codec</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.testng</groupId>
+ <artifactId>testng</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/adaptors/mdsal-resource/provider/src/main/java/org/onap/ccsdk/sli/adaptors/resource/mdsal/ConfigResource.java b/adaptors/mdsal-resource/provider/src/main/java/org/onap/ccsdk/sli/adaptors/resource/mdsal/ConfigResource.java
new file mode 100644
index 000000000..e2e9bc230
--- /dev/null
+++ b/adaptors/mdsal-resource/provider/src/main/java/org/onap/ccsdk/sli/adaptors/resource/mdsal/ConfigResource.java
@@ -0,0 +1,153 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.resource.mdsal;
+
+import java.util.Map;
+import java.util.Properties;
+
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.core.sli.SvcLogicResource;
+import org.onap.ccsdk.sli.core.sli.SvcLogicResource.QueryStatus;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.Document;
+
+public class ConfigResource implements SvcLogicResource {
+
+ private static final Logger LOG = LoggerFactory.getLogger(ConfigResource.class);
+
+ private RestService restService;
+
+ public ConfigResource(MdsalResourcePropertiesProvider propProvider) {
+ LOG.info("Loading ConfigResource using property provider");
+ Properties props = propProvider.getProperties();
+
+ String sdncUser = props.getProperty("org.onap.ccsdk.sli.adaptors.resource.mdsal.sdnc-user", "admin");
+ String sdncPasswd = props.getProperty("org.onap.ccsdk.sli.adaptors.resource.mdsal.sdnc-passwd", "admin");
+ String sdncHost = props.getProperty("org.onap.ccsdk.sli.adaptors.resource.mdsal.sdnc-host", "localhost");
+ String sdncProtocol = props.getProperty("org.onap.ccsdk.sli.adaptors.resource.mdsal.sdnc-protocol", "https");
+ String sdncPort = props.getProperty("org.onap.ccsdk.sli.adaptors.resource.mdsal.sdnc-port", "8443");
+
+ restService = new RestService(sdncProtocol, sdncHost, sdncPort, sdncUser, sdncPasswd, "XML", "XML");
+ }
+
+ public ConfigResource(String sdncProtocol, String sdncHost, String sdncPort, String sdncUser, String sdncPasswd)
+ {
+ restService = new RestService(sdncProtocol, sdncHost, sdncPort, sdncUser, sdncPasswd, "XML", "XML");
+ }
+
+ public ConfigResource(RestService restService) {
+ this.restService = restService;
+ }
+
+ @Override
+ public QueryStatus isAvailable(String resource, String key, String prefix, SvcLogicContext ctx) throws SvcLogicException
+ {
+ return(query(resource, false, null, key, prefix, null, null));
+ }
+
+ @Override
+ public QueryStatus exists(String resource, String key, String prefix, SvcLogicContext ctx) throws SvcLogicException
+ {
+ return(query(resource, false, null, key, prefix, null, null));
+ }
+
+ @Override
+ public QueryStatus query(String resource, boolean localOnly, String select, String key, String prefix,
+ String orderBy, SvcLogicContext ctx) throws SvcLogicException {
+ String module = resource;
+ StringBuffer restQuery = new StringBuffer();
+
+ String[] keyParts = key.split("/");
+ for (String keyPart : keyParts) {
+ if (restQuery.length() > 0) {
+ restQuery.append("/");
+ }
+ if (keyPart.startsWith("$")) {
+ restQuery.append(ctx.resolve(keyPart.substring(1)));
+ } else {
+ restQuery.append(keyPart);
+ }
+ }
+
+ String restQueryStr = restQuery.toString();
+ if ((restQueryStr.startsWith("'") && restQueryStr.endsWith("'")) ||
+ (restQueryStr.startsWith("\"") && restQueryStr.endsWith("\""))) {
+ restQueryStr = restQueryStr.substring(1, restQueryStr.length()-1);
+ }
+
+ String urlString = "restconf/config/" + module + ":" + restQueryStr;
+ LOG.info("Querying resource: " + resource + ". At URL: " + urlString);
+
+ Document results = restService.get(urlString);
+ if (results == null) {
+ return(QueryStatus.NOT_FOUND);
+ } else {
+ if (ctx != null) {
+ ctx.mergeDocument(prefix, results);
+ }
+ return(QueryStatus.SUCCESS);
+ }
+ }
+
+ @Override
+ public QueryStatus reserve(String resource, String select, String key, String prefix,
+ SvcLogicContext ctx) throws SvcLogicException {
+ return(QueryStatus.SUCCESS);
+
+ }
+
+ @Override
+ public QueryStatus release(String resource, String key, SvcLogicContext ctx) throws SvcLogicException {
+ return(QueryStatus.SUCCESS);
+ }
+
+ @Override
+ public QueryStatus delete(String arg0, String arg1, SvcLogicContext arg2)
+ throws SvcLogicException {
+ // TODO Auto-generated method stub
+ return(QueryStatus.SUCCESS);
+ }
+
+ @Override
+ public QueryStatus save(String arg0, boolean arg1, boolean localOnly, String arg2,
+ Map<String, String> arg3, String arg4, SvcLogicContext arg5)
+ throws SvcLogicException {
+ // TODO Auto-generated method stub
+ return(QueryStatus.SUCCESS);
+ }
+
+ @Override
+ public QueryStatus notify(String resource, String action, String key,
+ SvcLogicContext ctx) throws SvcLogicException {
+ return(QueryStatus.SUCCESS);
+ }
+
+
+ public QueryStatus update(String resource, String key,
+ Map<String, String> parms, String prefix, SvcLogicContext ctx)
+ throws SvcLogicException {
+ return(QueryStatus.SUCCESS);
+ }
+
+}
diff --git a/adaptors/mdsal-resource/provider/src/main/java/org/onap/ccsdk/sli/adaptors/resource/mdsal/MdsalResourcePropertiesProvider.java b/adaptors/mdsal-resource/provider/src/main/java/org/onap/ccsdk/sli/adaptors/resource/mdsal/MdsalResourcePropertiesProvider.java
new file mode 100755
index 000000000..e433a4c13
--- /dev/null
+++ b/adaptors/mdsal-resource/provider/src/main/java/org/onap/ccsdk/sli/adaptors/resource/mdsal/MdsalResourcePropertiesProvider.java
@@ -0,0 +1,28 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * onap
+ * ================================================================================
+ * Copyright (C) 2016 - 2017 ONAP
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.resource.mdsal;
+
+import java.util.Properties;
+
+public interface MdsalResourcePropertiesProvider {
+
+ public Properties getProperties();
+}
diff --git a/adaptors/mdsal-resource/provider/src/main/java/org/onap/ccsdk/sli/adaptors/resource/mdsal/MdsalResourcePropertiesProviderImpl.java b/adaptors/mdsal-resource/provider/src/main/java/org/onap/ccsdk/sli/adaptors/resource/mdsal/MdsalResourcePropertiesProviderImpl.java
new file mode 100755
index 000000000..e9e006f17
--- /dev/null
+++ b/adaptors/mdsal-resource/provider/src/main/java/org/onap/ccsdk/sli/adaptors/resource/mdsal/MdsalResourcePropertiesProviderImpl.java
@@ -0,0 +1,186 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * onap
+ * ================================================================================
+ * Copyright (C) 2016 - 2017 ONAP
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.resource.mdsal;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Optional;
+import java.util.Properties;
+import java.util.Vector;
+
+import org.onap.ccsdk.sli.core.sli.ConfigurationException;
+import org.onap.ccsdk.sli.core.utils.JREFileResolver;
+import org.onap.ccsdk.sli.core.utils.KarafRootFileResolver;
+import org.onap.ccsdk.sli.core.utils.PropertiesFileResolver;
+import org.onap.ccsdk.sli.core.utils.common.CoreDefaultFileResolver;
+import org.onap.ccsdk.sli.core.utils.common.SdncConfigEnvVarFileResolver;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Responsible for determining the properties file to use and instantiating the
+ * <code>SqlResource</code> Service. The priority for properties file
+ * resolution is as follows:
+ *
+ * <ol>
+ * <li>A directory identified by the system environment variable
+ * <code>SDNC_CONFIG_DIR</code></li>
+ * <li>The default directory <code>DEFAULT_DBLIB_PROP_DIR</code></li>
+ * <li>A directory identified by the JRE argument
+ * <code>sql-resource.properties</code></li>
+ * <li>A <code>sql-resource.properties</code> file located in the karaf root
+ * directory</li>
+ * </ol>
+ */
+public class MdsalResourcePropertiesProviderImpl implements MdsalResourcePropertiesProvider {
+
+ private static final Logger LOG = LoggerFactory.getLogger(MdsalResourcePropertiesProviderImpl.class);
+
+ /**
+ * The name of the properties file for database configuration
+ */
+ private static final String MDSALRESOURCE_PROP_FILE_NAME = "mdsal-resource.properties";
+
+ /**
+ * A prioritized list of strategies for resolving sql-resource properties files.
+ */
+ private Vector<PropertiesFileResolver> mdsalResourcePropertiesFileResolvers = new Vector<>();
+
+ /**
+ * The configuration properties for the db connection.
+ */
+ private Properties properties;
+
+ /**
+ * Set up the prioritized list of strategies for resolving dblib properties
+ * files.
+ */
+ public MdsalResourcePropertiesProviderImpl() {
+ mdsalResourcePropertiesFileResolvers
+ .add(new SdncConfigEnvVarFileResolver("Using property file (1) from environment variable"));
+ mdsalResourcePropertiesFileResolvers.add(new CoreDefaultFileResolver("Using property file (2) from default directory"));
+
+ mdsalResourcePropertiesFileResolvers.add(
+ new JREFileResolver("Using property file (3) from JRE argument", MdsalResourcePropertiesProviderImpl.class));
+ mdsalResourcePropertiesFileResolvers.add(new KarafRootFileResolver("Using property file (4) from karaf root", this));
+
+ // determines properties file as according to the priority described in the
+ // class header comment
+ final File propertiesFile = determinePropertiesFile(this);
+ if (propertiesFile != null) {
+ try (FileInputStream fileInputStream = new FileInputStream(propertiesFile)) {
+ properties = new Properties();
+ properties.load(fileInputStream);
+ } catch (final IOException e) {
+ LOG.error("Failed to load properties for file: {}", propertiesFile.toString(),
+ new ConfigurationException("Failed to load properties for file: " + propertiesFile.toString(),
+ e));
+ }
+ } else {
+ // Try to read properties as resource
+
+ InputStream propStr = getClass().getResourceAsStream("/" + MDSALRESOURCE_PROP_FILE_NAME);
+ if (propStr != null) {
+ properties = new Properties();
+ try {
+ properties.load(propStr);
+ propStr.close();
+ } catch (IOException e) {
+ properties = null;
+ }
+ }
+
+ }
+
+ if (properties == null) {
+ reportFailure("Missing configuration properties resource(3)", new ConfigurationException(
+ "Missing configuration properties resource(3): " + MDSALRESOURCE_PROP_FILE_NAME));
+ }
+ }
+
+ /**
+ * Extract svclogic config properties.
+ *
+ * @return the svclogic config properties
+ */
+ public Properties getProperties() {
+ return properties;
+ }
+
+ /**
+ * Reports the method chosen for properties resolution to the
+ * <code>Logger</code>.
+ *
+ * @param message
+ * Some user friendly message
+ * @param fileOptional
+ * The file location of the chosen properties file
+ * @return the file location of the chosen properties file
+ */
+ private static File reportSuccess(final String message, final Optional<File> fileOptional) {
+ if (fileOptional.isPresent()) {
+ final File file = fileOptional.get();
+ LOG.info("{} {}", message, file.getPath());
+ return file;
+ }
+ return null;
+ }
+
+ /**
+ * Reports fatal errors. This is the case in which no properties file could be
+ * found.
+ *
+ * @param message
+ * An appropriate fatal error message
+ * @param configurationException
+ * An exception describing what went wrong during resolution
+ */
+ private static void reportFailure(final String message, final ConfigurationException configurationException) {
+
+ LOG.error("{}", message, configurationException);
+ }
+
+ /**
+ * Determines the sql-resource properties file to use based on the following priority:
+ * <ol>
+ * <li>A directory identified by the system environment variable
+ * <code>SDNC_CONFIG_DIR</code></li>
+ * <li>The default directory <code>DEFAULT_DBLIB_PROP_DIR</code></li>
+ * <li>A directory identified by the JRE argument
+ * <code>mdsal-resource.properties</code></li>
+ * <li>A <code>sql-resource.properties</code> file located in the karaf root
+ * directory</li>
+ * </ol>
+ */
+ File determinePropertiesFile(final MdsalResourcePropertiesProviderImpl resourceProvider) {
+
+ for (final PropertiesFileResolver sliPropertiesFileResolver : mdsalResourcePropertiesFileResolvers) {
+ final Optional<File> fileOptional = sliPropertiesFileResolver.resolveFile(MDSALRESOURCE_PROP_FILE_NAME);
+ if (fileOptional.isPresent()) {
+ return reportSuccess(sliPropertiesFileResolver.getSuccessfulResolutionMessage(), fileOptional);
+ }
+ }
+
+ return null;
+ }
+}
diff --git a/adaptors/mdsal-resource/provider/src/main/java/org/onap/ccsdk/sli/adaptors/resource/mdsal/OperationalResource.java b/adaptors/mdsal-resource/provider/src/main/java/org/onap/ccsdk/sli/adaptors/resource/mdsal/OperationalResource.java
new file mode 100644
index 000000000..320878126
--- /dev/null
+++ b/adaptors/mdsal-resource/provider/src/main/java/org/onap/ccsdk/sli/adaptors/resource/mdsal/OperationalResource.java
@@ -0,0 +1,147 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.resource.mdsal;
+
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.core.sli.SvcLogicResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.Document;
+
+import java.util.Map;
+import java.util.Properties;
+
+public class OperationalResource implements SvcLogicResource {
+
+ private static final Logger LOG = LoggerFactory.getLogger(OperationalResource.class);
+
+ private RestService restService;
+
+ public OperationalResource(MdsalResourcePropertiesProvider propProvider) {
+ Properties props = propProvider.getProperties();
+
+ String sdncUser = props.getProperty("org.onap.ccsdk.sli.adaptors.resource.mdsal.sdnc-user", "admin");
+ String sdncPasswd = props.getProperty("org.onap.ccsdk.sli.adaptors.resource.mdsal.sdnc-passwd", "admin");
+ String sdncHost = props.getProperty("org.onap.ccsdk.sli.adaptors.resource.mdsal.sdnc-host", "localhost");
+ String sdncProtocol = props.getProperty("org.onap.ccsdk.sli.adaptors.resource.mdsal.sdnc-protocol", "https");
+ String sdncPort = props.getProperty("org.onap.ccsdk.sli.adaptors.resource.mdsal.sdnc-port", "8443");
+
+ restService = new RestService(sdncProtocol, sdncHost, sdncPort, sdncUser, sdncPasswd, "XML", "XML");
+ }
+
+ public OperationalResource(String sdncProtocol, String sdncHost, String sdncPort, String sdncUser, String sdncPasswd) {
+ restService = new RestService(sdncProtocol, sdncHost, sdncPort, sdncUser, sdncPasswd, "XML", "XML");
+ }
+
+ public OperationalResource(RestService restService) {
+ this.restService = restService;
+ }
+
+ @Override
+ public QueryStatus isAvailable(String resource, String key, String prefix, SvcLogicContext ctx) throws SvcLogicException {
+ return (query(resource, false, null, key, prefix, null, null));
+ }
+
+ @Override
+ public QueryStatus exists(String resource, String key, String prefix, SvcLogicContext ctx) throws SvcLogicException {
+ return (query(resource, false, null, key, prefix, null, null));
+ }
+
+ @Override
+ public QueryStatus query(String resource, boolean localOnly, String select, String key, String prefix,
+ String orderBy, SvcLogicContext ctx) throws SvcLogicException {
+ String module = resource;
+ StringBuffer restQuery = new StringBuffer();
+
+ String[] keyParts = key.split("/");
+ for (String keyPart : keyParts) {
+ if (restQuery.length() > 0) {
+ restQuery.append("/");
+ }
+ if (keyPart.startsWith("$")) {
+ restQuery.append(ctx.resolve(keyPart.substring(1)));
+ } else {
+ restQuery.append(keyPart);
+ }
+ }
+
+ String restQueryStr = restQuery.toString();
+ if ((restQueryStr.startsWith("'") && restQueryStr.endsWith("'")) ||
+ (restQueryStr.startsWith("\"") && restQueryStr.endsWith("\""))) {
+ restQueryStr = restQueryStr.substring(1, restQueryStr.length() - 1);
+ }
+
+ String urlString = "restconf/operational/" + module + ":" + restQueryStr;
+ LOG.info("Querying resource: " + resource + ". At URL: " + urlString);
+
+ Document results = restService.get(urlString);
+
+ if (results == null) {
+ return (QueryStatus.NOT_FOUND);
+ } else {
+ if (ctx != null) {
+ ctx.mergeDocument(prefix, results);
+ }
+ return (QueryStatus.SUCCESS);
+ }
+ }
+
+ @Override
+ public QueryStatus reserve(String resource, String select, String key, String prefix,
+ SvcLogicContext ctx) throws SvcLogicException {
+ return (QueryStatus.SUCCESS);
+ }
+
+ @Override
+ public QueryStatus release(String resource, String key, SvcLogicContext ctx) throws SvcLogicException {
+ return (QueryStatus.SUCCESS);
+ }
+
+ @Override
+ public QueryStatus delete(String arg0, String arg1, SvcLogicContext arg2)
+ throws SvcLogicException {
+ // TODO Auto-generated method stub
+ return (QueryStatus.SUCCESS);
+ }
+
+ @Override
+ public QueryStatus save(String arg0, boolean arg1, boolean localOnly, String arg2,
+ Map<String, String> arg3, String arg4, SvcLogicContext arg5)
+ throws SvcLogicException {
+ // TODO Auto-generated method stub
+ return (QueryStatus.SUCCESS);
+ }
+
+ @Override
+ public QueryStatus notify(String resource, String action, String key,
+ SvcLogicContext ctx) throws SvcLogicException {
+ return (QueryStatus.SUCCESS);
+ }
+
+ public QueryStatus update(String resource, String key,
+ Map<String, String> parms, String prefix, SvcLogicContext ctx)
+ throws SvcLogicException {
+ return (QueryStatus.SUCCESS);
+ }
+
+}
diff --git a/adaptors/mdsal-resource/provider/src/main/java/org/onap/ccsdk/sli/adaptors/resource/mdsal/RestService.java b/adaptors/mdsal-resource/provider/src/main/java/org/onap/ccsdk/sli/adaptors/resource/mdsal/RestService.java
new file mode 100644
index 000000000..ebddc24ae
--- /dev/null
+++ b/adaptors/mdsal-resource/provider/src/main/java/org/onap/ccsdk/sli/adaptors/resource/mdsal/RestService.java
@@ -0,0 +1,184 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.resource.mdsal;
+
+import org.apache.commons.codec.binary.Base64;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.Document;
+
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.HttpsURLConnection;
+import javax.xml.XMLConstants;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import java.io.*;
+import java.net.Authenticator;
+import java.net.HttpURLConnection;
+import java.net.PasswordAuthentication;
+import java.net.URL;
+
+public class RestService {
+
+ private static final Logger LOG = LoggerFactory.getLogger(ConfigResource.class);
+ private String user;
+ private String passwd;
+ private String contentType;
+ private String accept;
+ private String protocol;
+ private String host;
+ private String port;
+
+ public RestService(String protocol, String host, String port, String user, String passwd, String accept, String contentType) {
+ this.protocol = protocol;
+ this.host = host;
+ this.port = port;
+ this.user = user;
+ this.passwd = passwd;
+ this.accept = accept;
+ this.contentType = contentType;
+ }
+
+ private HttpURLConnection getRestConnection(String urlString, String method) throws IOException {
+ URL sdncUrl = new URL(urlString);
+ Authenticator.setDefault(new SdncAuthenticator(user, passwd));
+
+ String authStr = user + ":" + passwd;
+ String encodedAuthStr = new String(Base64.encodeBase64(authStr.getBytes()));
+
+ HttpURLConnection conn = (HttpURLConnection) sdncUrl.openConnection();
+ conn.addRequestProperty("Authentication", "Basic " + encodedAuthStr);
+ conn.setRequestMethod(method);
+ conn.setDoInput(true);
+ conn.setDoOutput(true);
+ conn.setUseCaches(false);
+
+ //Setting Accept header (doesn't dependent on Msg Body if present or not)
+ if ("XML".equalsIgnoreCase(accept)) {
+ conn.setRequestProperty("Accept", "application/xml");
+ } else {
+ conn.setRequestProperty("Accept", "application/json");
+ }
+
+ return (conn);
+ }
+
+ private Document send(String urlString, byte[] msgBytes, String method) {
+ Document response = null;
+ String fullUrl = protocol + "://" + host + ":" + port + "/" + urlString;
+ LOG.info("Sending REST {} to {}", method, fullUrl);
+
+ try {
+ HttpURLConnection conn = getRestConnection(fullUrl, method);
+ if (conn instanceof HttpsURLConnection) {
+ HostnameVerifier hostnameVerifier = (hostname, session) -> true;
+ ((HttpsURLConnection) conn).setHostnameVerifier(hostnameVerifier);
+ }
+
+ // Write message
+ if (msgBytes != null) {
+ LOG.info("Message body:\n{}", msgBytes);
+ conn.setRequestProperty("Content-Length", "" + msgBytes.length);
+
+ // Setting Content-Type header only if Msg Body is present
+ if ("XML".equalsIgnoreCase(contentType)) {
+ conn.setRequestProperty("Content-Type", "application/xml");
+ } else {
+ conn.setRequestProperty("Content-Type", "application/json");
+ }
+
+ DataOutputStream outStr = new DataOutputStream(conn.getOutputStream());
+ outStr.write(msgBytes);
+ outStr.close();
+ } else {
+ conn.setRequestProperty("Content-Length", "0");
+ }
+
+ // Read response
+ LOG.info("Response: {} {}", conn.getResponseCode(), conn.getResponseMessage());
+
+ BufferedReader respRdr;
+ if (conn.getResponseCode() < 300) {
+ respRdr = new BufferedReader(new InputStreamReader(conn.getInputStream()));
+ } else {
+ respRdr = new BufferedReader(new InputStreamReader(conn.getErrorStream()));
+ }
+
+ StringBuffer respBuff = new StringBuffer();
+ String respLn;
+ while ((respLn = respRdr.readLine()) != null) {
+ respBuff.append(respLn + "\n");
+ }
+ respRdr.close();
+
+ String respString = respBuff.toString();
+ LOG.info("Response body :\n{}", respString);
+
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ dbf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
+ dbf.setFeature("http://xml.org/sax/features/external-general-entities", false);
+ dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
+ DocumentBuilder db = dbf.newDocumentBuilder();
+
+ response = db.parse(new ByteArrayInputStream(respString.getBytes()));
+
+ } catch (Exception e) {
+ LOG.error("Caught exception executing REST command", e);
+ }
+
+ return (response);
+ }
+
+ public Document get(String urlString) {
+ return (send(urlString, null, "GET"));
+ }
+
+ public Document delete(String urlString) {
+ return (send(urlString, null, "DELETE"));
+ }
+
+ public Document post(String urlString, byte[] msgBytes) {
+ return (send(urlString, msgBytes, "POST"));
+ }
+
+ public Document put(String urlString, byte[] msgBytes) {
+ return (send(urlString, msgBytes, "PUT"));
+ }
+
+
+ private class SdncAuthenticator extends Authenticator {
+ private String user;
+ private String passwd;
+
+ SdncAuthenticator(String user, String passwd) {
+ this.user = user;
+ this.passwd = passwd;
+ }
+
+ @Override
+ protected PasswordAuthentication getPasswordAuthentication() {
+ return new PasswordAuthentication(user, passwd.toCharArray());
+ }
+
+ }
+
+}
diff --git a/adaptors/mdsal-resource/provider/src/main/resources/IPV4_ADDRESS_POOL.csv b/adaptors/mdsal-resource/provider/src/main/resources/IPV4_ADDRESS_POOL.csv
new file mode 100755
index 000000000..30ce117bc
--- /dev/null
+++ b/adaptors/mdsal-resource/provider/src/main/resources/IPV4_ADDRESS_POOL.csv
@@ -0,0 +1,9 @@
+"192.168.1.2","OAM","AVAILABLE"
+"192.168.1.3","OAM","AVAILABLE"
+"192.168.1.4","OAM","AVAILABLE"
+"192.168.1.5","OAM","AVAILABLE"
+"192.168.1.6","OAM","AVAILABLE"
+"192.168.1.7","OAM","AVAILABLE"
+"192.168.1.8","OAM","AVAILABLE"
+"192.168.1.9","OAM","AVAILABLE"
+"192.168.1.10","OAM","AVAILABLE"
diff --git a/adaptors/mdsal-resource/provider/src/main/resources/OSGI-INF/blueprint/mdsal-resource-blueprint.xml b/adaptors/mdsal-resource/provider/src/main/resources/OSGI-INF/blueprint/mdsal-resource-blueprint.xml
new file mode 100755
index 000000000..9c691263c
--- /dev/null
+++ b/adaptors/mdsal-resource/provider/src/main/resources/OSGI-INF/blueprint/mdsal-resource-blueprint.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ============LICENSE_START=======================================================
+ openECOMP : SDN-C
+ ================================================================================
+ Copyright (C) 2017 - 2018 AT&T Intellectual Property. All rights
+ reserved.
+ ================================================================================
+ 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.
+ ============LICENSE_END=========================================================
+ -->
+
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+ xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0"
+ odl:use-default-for-reference-types="true">
+
+ <bean id="propProvider" class="org.onap.ccsdk.sli.adaptors.resource.mdsal.MdsalResourcePropertiesProviderImpl" />
+
+
+ <bean id="configResourceInstance" class="org.onap.ccsdk.sli.adaptors.resource.mdsal.ConfigResource">
+ <argument ref="propProvider"/>
+ </bean>
+
+ <bean id="operResourceInstance" class="org.onap.ccsdk.sli.adaptors.resource.mdsal.OperationalResource">
+ <argument ref="propProvider"/>
+ </bean>
+
+ <service ref="configResourceInstance">
+ <interfaces>
+ <value>org.onap.ccsdk.sli.adaptors.resource.mdsal.ConfigResource</value>
+ </interfaces>
+ </service>
+
+ <service ref="operResourceInstance">
+ <interfaces>
+ <value>org.onap.ccsdk.sli.adaptors.resource.mdsal.OperationalResource</value>
+ </interfaces>
+ </service>
+</blueprint>
diff --git a/adaptors/mdsal-resource/provider/src/main/resources/VLAN_ID_POOL.csv b/adaptors/mdsal-resource/provider/src/main/resources/VLAN_ID_POOL.csv
new file mode 100755
index 000000000..6c4b0f775
--- /dev/null
+++ b/adaptors/mdsal-resource/provider/src/main/resources/VLAN_ID_POOL.csv
@@ -0,0 +1,22 @@
+"1100","IPAG","AVAILABLE",NULL
+"1101","IPAG","AVAILABLE",NULL
+"1102","IPAG","AVAILABLE",NULL
+"1103","IPAG","AVAILABLE",NULL
+"1104","IPAG","AVAILABLE",NULL
+"1105","IPAG","AVAILABLE",NULL
+"1106","IPAG","AVAILABLE",NULL
+"1107","IPAG","AVAILABLE",NULL
+"1108","IPAG","AVAILABLE",NULL
+"1109","IPAG","AVAILABLE",NULL
+"1110","IPAG","AVAILABLE",NULL
+"1200","VPE","AVAILABLE",NULL
+"1201","VPE","AVAILABLE",NULL
+"1202","VPE","AVAILABLE",NULL
+"1203","VPE","AVAILABLE",NULL
+"1204","VPE","AVAILABLE",NULL
+"1205","VPE","AVAILABLE",NULL
+"1206","VPE","AVAILABLE",NULL
+"1207","VPE","AVAILABLE",NULL
+"1208","VPE","AVAILABLE",NULL
+"1209","VPE","AVAILABLE",NULL
+"1210","VPE","AVAILABLE",NULL
diff --git a/adaptors/mdsal-resource/provider/src/main/resources/crtables.sql b/adaptors/mdsal-resource/provider/src/main/resources/crtables.sql
new file mode 100644
index 000000000..5ee75f4e4
--- /dev/null
+++ b/adaptors/mdsal-resource/provider/src/main/resources/crtables.sql
@@ -0,0 +1,70 @@
+---
+-- ============LICENSE_START=======================================================
+-- openECOMP : SDN-C
+-- ================================================================================
+-- Copyright (C) 2017 AT&T Intellectual Property. All rights
+-- reserved.
+-- ================================================================================
+-- 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.
+-- ============LICENSE_END=========================================================
+---
+
+CREATE TABLE sdnctl.VNF (
+vnf_id varchar(80) NOT NULL,
+vnf_name varchar(80) NOT NULL,
+vnf_type varchar(10) NOT NULL,
+orchestration_status varchar(20),
+heat_stack_id varchar(80),
+mso_catalog_key varchar(80),
+availability_zone varchar(80),
+aic_site_id varchar(80),
+oam_ipv4_address varchar(20),
+CONSTRAINT P_VNF PRIMARY KEY(vnf_id));
+
+CREATE TABLE sdnctl.VNF_NETWORK_CONNECTION (
+connection_uuid varchar(80) NOT NULL,
+vnf_id varchar(80) NOT NULL,
+connection_id varchar(80),
+connection_type varchar(20),
+neutron_network_id varchar(80),
+neutron_network_name varchar(80),
+orchestration_status varchar(20),
+switch_id varchar(40),
+heat_stack_id varchar(80),
+mso_catalog_key varchar(80),
+provider_network varchar(80),
+port_group_id varchar(80),
+port_group_name varchar(80),
+CONSTRAINT P_NETWORK_CONNECTION PRIMARY KEY(connection_uuid));
+
+CREATE TABLE sdnctl.VNF_NETWORK_CONNECTION_VLAN (
+vlan_uuid varchar(80) NOT NULL,
+vlan_id numeric(4) NOT NULL,
+vlan_type varchar(5) NOT NULL,
+connection_uuid varchar(80),
+CONSTRAINT P_VNF_NETWORK_CONNECTION_VLAN PRIMARY KEY(vlan_uuid));
+
+CREATE TABLE sdnctl.VLAN_ID_POOL (
+vlan_id numeric(4) NOT NULL,
+universe varchar(40) NOT NULL,
+status varchar(40) NOT NULL,
+vlan_uuid varchar(80),
+CONSTRAINT P_VLAN_ID_POOL PRIMARY KEY(vlan_id,universe));
+
+CREATE TABLE sdnctl.IPV4_ADDRESS_POOL (
+ipv4_addr varchar(20) NOT NULL,
+universe varchar(40) NOT NULL,
+status varchar(40) NOT NULL,
+CONSTRAINT P_IPV4_ADDRESS_POOL PRIMARY KEY(ipv4_addr, universe));
+
+
diff --git a/adaptors/mdsal-resource/provider/src/main/resources/mdsal-resource.properties b/adaptors/mdsal-resource/provider/src/main/resources/mdsal-resource.properties
new file mode 100644
index 000000000..47c8ebf77
--- /dev/null
+++ b/adaptors/mdsal-resource/provider/src/main/resources/mdsal-resource.properties
@@ -0,0 +1,27 @@
+###
+# ============LICENSE_START=======================================================
+# openECOMP : SDN-C
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights
+# reserved.
+# ================================================================================
+# 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.
+# ============LICENSE_END=========================================================
+###
+
+org.onap.ccsdk.sli.adaptors.resource.mdsal.sdnc-user=admin
+org.onap.ccsdk.sli.adaptors.resource.mdsal.sdnc-passwd=Kp8bJ4SXszM0WXlhak3eHlcse2gAw84vaoGGmJvUy2U
+org.onap.ccsdk.sli.adaptors.resource.mdsal.sdnc-host=localhost
+org.onap.ccsdk.sli.adaptors.resource.mdsal.sdnc-protocol=http
+org.onap.ccsdk.sli.adaptors.resource.mdsal.sdnc-port=8181
+
diff --git a/adaptors/mdsal-resource/provider/src/main/resources/org/opendaylight/blueprint/mdsal-resource-blueprint.xml b/adaptors/mdsal-resource/provider/src/main/resources/org/opendaylight/blueprint/mdsal-resource-blueprint.xml
new file mode 100755
index 000000000..9c691263c
--- /dev/null
+++ b/adaptors/mdsal-resource/provider/src/main/resources/org/opendaylight/blueprint/mdsal-resource-blueprint.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ============LICENSE_START=======================================================
+ openECOMP : SDN-C
+ ================================================================================
+ Copyright (C) 2017 - 2018 AT&T Intellectual Property. All rights
+ reserved.
+ ================================================================================
+ 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.
+ ============LICENSE_END=========================================================
+ -->
+
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+ xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0"
+ odl:use-default-for-reference-types="true">
+
+ <bean id="propProvider" class="org.onap.ccsdk.sli.adaptors.resource.mdsal.MdsalResourcePropertiesProviderImpl" />
+
+
+ <bean id="configResourceInstance" class="org.onap.ccsdk.sli.adaptors.resource.mdsal.ConfigResource">
+ <argument ref="propProvider"/>
+ </bean>
+
+ <bean id="operResourceInstance" class="org.onap.ccsdk.sli.adaptors.resource.mdsal.OperationalResource">
+ <argument ref="propProvider"/>
+ </bean>
+
+ <service ref="configResourceInstance">
+ <interfaces>
+ <value>org.onap.ccsdk.sli.adaptors.resource.mdsal.ConfigResource</value>
+ </interfaces>
+ </service>
+
+ <service ref="operResourceInstance">
+ <interfaces>
+ <value>org.onap.ccsdk.sli.adaptors.resource.mdsal.OperationalResource</value>
+ </interfaces>
+ </service>
+</blueprint>
diff --git a/adaptors/mdsal-resource/provider/src/main/resources/svclogic.properties b/adaptors/mdsal-resource/provider/src/main/resources/svclogic.properties
new file mode 100644
index 000000000..0abadc5c8
--- /dev/null
+++ b/adaptors/mdsal-resource/provider/src/main/resources/svclogic.properties
@@ -0,0 +1,26 @@
+###
+# ============LICENSE_START=======================================================
+# openECOMP : SDN-C
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights
+# reserved.
+# ================================================================================
+# 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.
+# ============LICENSE_END=========================================================
+###
+
+org.onap.ccsdk.sli.adaptors.dbtype = jdbc
+org.onap.ccsdk.sli.adaptors.jdbc.url = jdbc:mysql://dbhost:3306/sdnctl
+org.onap.ccsdk.sli.adaptors.jdbc.database = sdnctl
+org.onap.ccsdk.sli.adaptors.jdbc.user = sdnctl
+org.onap.ccsdk.sli.adaptors.jdbc.password = gamma
diff --git a/adaptors/mdsal-resource/provider/src/test/java/org/onap/ccsdk/sli/adaptors/resource/mdsal/ConfigResourceTest.java b/adaptors/mdsal-resource/provider/src/test/java/org/onap/ccsdk/sli/adaptors/resource/mdsal/ConfigResourceTest.java
new file mode 100644
index 000000000..f5b0bcf0c
--- /dev/null
+++ b/adaptors/mdsal-resource/provider/src/test/java/org/onap/ccsdk/sli/adaptors/resource/mdsal/ConfigResourceTest.java
@@ -0,0 +1,43 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.resource.mdsal;
+
+import org.junit.Test;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.core.sli.SvcLogicResource.QueryStatus;
+
+import static org.junit.Assert.assertEquals;
+
+public class ConfigResourceTest {
+ ConfigResource configResource = new ConfigResource("http", "local",
+ "10001", "admin",
+ "password");
+
+ @Test
+ public void isAvailableNegativeTest() throws SvcLogicException {
+ SvcLogicContext ctx = new SvcLogicContext();
+ assertEquals(QueryStatus.NOT_FOUND, configResource.isAvailable
+ ("xyz", "key", "prefix", ctx));
+ }
+}
+
diff --git a/adaptors/mdsal-resource/provider/src/test/java/org/onap/ccsdk/sli/adaptors/resource/mdsal/TestConfigResource.java b/adaptors/mdsal-resource/provider/src/test/java/org/onap/ccsdk/sli/adaptors/resource/mdsal/TestConfigResource.java
new file mode 100644
index 000000000..80563b96b
--- /dev/null
+++ b/adaptors/mdsal-resource/provider/src/test/java/org/onap/ccsdk/sli/adaptors/resource/mdsal/TestConfigResource.java
@@ -0,0 +1,31 @@
+package org.onap.ccsdk.sli.adaptors.resource.mdsal;
+
+import junit.framework.TestCase;
+
+import static org.mockito.Mockito.mock;
+
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import static org.junit.Assert.assertNotNull;
+
+public class TestConfigResource extends TestCase {
+
+ public void test() throws Exception {
+
+ RestService restService = mock(RestService.class);
+ SvcLogicContext ctx = new SvcLogicContext();
+
+ ConfigResource res = new ConfigResource(restService);
+
+ res.delete("my-resource", null, ctx);
+ res.notify("my-resource", "action", "key", ctx);
+ res.query("my-resource", false, "my-select", "mykey", "pfx", null, ctx);
+ res.release("my-resource", "mykey", ctx);
+ res.reserve("my-resource", "my-select", "mykey", "pfx", ctx);
+ res.exists("my-resource", "mykey", "pfx", ctx);
+ res.isAvailable("my-resource", "mykey", "pfx", ctx);
+ res.save("resource", false, false, null, null, null, ctx);
+ res.update("my-resource", "mykey", null, "pfx", ctx);
+ assertNotNull(res);
+ }
+
+}
diff --git a/adaptors/mdsal-resource/provider/src/test/java/org/onap/ccsdk/sli/adaptors/resource/mdsal/TestMdsalResourcePropertiesProviderImpl.java b/adaptors/mdsal-resource/provider/src/test/java/org/onap/ccsdk/sli/adaptors/resource/mdsal/TestMdsalResourcePropertiesProviderImpl.java
new file mode 100644
index 000000000..7f05d1e5f
--- /dev/null
+++ b/adaptors/mdsal-resource/provider/src/test/java/org/onap/ccsdk/sli/adaptors/resource/mdsal/TestMdsalResourcePropertiesProviderImpl.java
@@ -0,0 +1,64 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2018 Samsung. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.resource.mdsal;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.Properties;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+public class TestMdsalResourcePropertiesProviderImpl {
+
+ MdsalResourcePropertiesProviderImpl mdsal;
+
+ @Before
+ public void setup() {
+ mdsal = new MdsalResourcePropertiesProviderImpl();
+ }
+
+
+ @Test
+ public void testGetProperties() {
+ Properties prop = mdsal.getProperties();
+
+ System.out.println("All Default Properties : " + prop);
+
+ assertEquals("localhost",prop.getProperty("org.onap.ccsdk.sli.adaptors.resource.mdsal.sdnc-host"));
+ assertEquals("Kp8bJ4SXszM0WXlhak3eHlcse2gAw84vaoGGmJvUy2U",prop.getProperty("org.onap.ccsdk.sli.adaptors.resource.mdsal.sdnc-passwd"));
+ assertEquals("http",prop.getProperty("org.onap.ccsdk.sli.adaptors.resource.mdsal.sdnc-protocol"));
+ assertEquals("8181",prop.getProperty("org.onap.ccsdk.sli.adaptors.resource.mdsal.sdnc-port"));
+ assertEquals("admin",prop.getProperty("org.onap.ccsdk.sli.adaptors.resource.mdsal.sdnc-user"));
+ }
+
+
+ @Test
+ public void testGetPropertie() throws IllegalStateException, IllegalArgumentException {
+ MdsalResourcePropertiesProviderImpl test = new MdsalResourcePropertiesProviderImpl();
+
+ mdsal.determinePropertiesFile(test);
+ assertNotNull(test);
+
+ }
+}
diff --git a/adaptors/mdsal-resource/provider/src/test/java/org/onap/ccsdk/sli/adaptors/resource/mdsal/TestOperationalResource.java b/adaptors/mdsal-resource/provider/src/test/java/org/onap/ccsdk/sli/adaptors/resource/mdsal/TestOperationalResource.java
new file mode 100644
index 000000000..2e9798df1
--- /dev/null
+++ b/adaptors/mdsal-resource/provider/src/test/java/org/onap/ccsdk/sli/adaptors/resource/mdsal/TestOperationalResource.java
@@ -0,0 +1,31 @@
+package org.onap.ccsdk.sli.adaptors.resource.mdsal;
+
+import static org.mockito.Mockito.mock;
+
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+
+import junit.framework.TestCase;
+import static org.junit.Assert.assertNotNull;
+
+public class TestOperationalResource extends TestCase {
+
+
+ public void test() throws Exception {
+
+ RestService restService = mock(RestService.class);
+ SvcLogicContext ctx = new SvcLogicContext();
+
+ OperationalResource res = new OperationalResource(restService);
+
+ res.delete("my-resource", null, ctx);
+ res.notify("my-resource", "action", "key", ctx);
+ res.query("my-resource", false, "my-select", "mykey", "pfx", null, ctx);
+ res.release("my-resource", "mykey", ctx);
+ res.reserve("my-resource", "my-select", "mykey", "pfx", ctx);
+ res.exists("my-resource", "mykey", "pfx", ctx);
+ res.isAvailable("my-resource", "mykey", "pfx", ctx);
+ res.save("resource", false, false, null, null, null, ctx);
+ res.update("my-resource", "mykey", null, "pfx", ctx);
+ assertNotNull(restService);
+ }
+}
diff --git a/adaptors/message-router/README.md b/adaptors/message-router/README.md
new file mode 100755
index 000000000..32848252b
--- /dev/null
+++ b/adaptors/message-router/README.md
@@ -0,0 +1,7 @@
+# CCSDK Message Router Extension
+
+This maven module builds re-usable code that interacts with message router
+
+## High level modules
+- **publisher** used for sending messages to a dmaap message router topic
+- **consumer** not yet created, this will be used for pulling messages from a dmaap message router topic
diff --git a/adaptors/message-router/consumer/README.md b/adaptors/message-router/consumer/README.md
new file mode 100755
index 000000000..9d01256a7
--- /dev/null
+++ b/adaptors/message-router/consumer/README.md
@@ -0,0 +1,7 @@
+# Consumer
+
+## Modules
+- api - exports the consumer interface for clients and providers to import
+- features - used for managing the feature repository for consumer
+- installer - provides a simple install script
+- provider - provides an implementation of the consumer api \ No newline at end of file
diff --git a/adaptors/message-router/consumer/api/pom.xml b/adaptors/message-router/consumer/api/pom.xml
new file mode 100755
index 000000000..e77eb9793
--- /dev/null
+++ b/adaptors/message-router/consumer/api/pom.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.sli.adaptors.messagerouter</groupId>
+ <artifactId>consumer.aggregate</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>consumer.api</artifactId>
+ <packaging>bundle</packaging>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <configuration>
+ <instructions>
+ <Export-Package>org.onap.ccsdk.sli.adaptors.messagerouter.consumer.api</Export-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/adaptors/message-router/consumer/api/src/main/java/org/onap/ccsdk/sli/adaptors/messagerouter/consumer/api/ConsumerApi.java b/adaptors/message-router/consumer/api/src/main/java/org/onap/ccsdk/sli/adaptors/messagerouter/consumer/api/ConsumerApi.java
new file mode 100755
index 000000000..41deade85
--- /dev/null
+++ b/adaptors/message-router/consumer/api/src/main/java/org/onap/ccsdk/sli/adaptors/messagerouter/consumer/api/ConsumerApi.java
@@ -0,0 +1,6 @@
+package org.onap.ccsdk.sli.adaptors.messagerouter.consumer.api;
+
+public interface ConsumerApi extends AutoCloseable {
+ //registers a handler to handle a specific topic, should be called only once per client
+ public void registerHandler(String topic, RequestHandler requestHandler);
+}
diff --git a/adaptors/message-router/consumer/api/src/main/java/org/onap/ccsdk/sli/adaptors/messagerouter/consumer/api/PollingConsumer.java b/adaptors/message-router/consumer/api/src/main/java/org/onap/ccsdk/sli/adaptors/messagerouter/consumer/api/PollingConsumer.java
new file mode 100755
index 000000000..29fc1c764
--- /dev/null
+++ b/adaptors/message-router/consumer/api/src/main/java/org/onap/ccsdk/sli/adaptors/messagerouter/consumer/api/PollingConsumer.java
@@ -0,0 +1,7 @@
+package org.onap.ccsdk.sli.adaptors.messagerouter.consumer.api;
+
+public interface PollingConsumer extends ConsumerApi {
+
+ // Starts polling message router for messages, won't stop until close it called
+ void start();
+}
diff --git a/adaptors/message-router/consumer/api/src/main/java/org/onap/ccsdk/sli/adaptors/messagerouter/consumer/api/PullingConsumer.java b/adaptors/message-router/consumer/api/src/main/java/org/onap/ccsdk/sli/adaptors/messagerouter/consumer/api/PullingConsumer.java
new file mode 100755
index 000000000..1187aaceb
--- /dev/null
+++ b/adaptors/message-router/consumer/api/src/main/java/org/onap/ccsdk/sli/adaptors/messagerouter/consumer/api/PullingConsumer.java
@@ -0,0 +1,7 @@
+package org.onap.ccsdk.sli.adaptors.messagerouter.consumer.api;
+
+public interface PullingConsumer extends ConsumerApi {
+
+ //Pulls a single batch of messages
+ void pull();
+}
diff --git a/adaptors/message-router/consumer/api/src/main/java/org/onap/ccsdk/sli/adaptors/messagerouter/consumer/api/RequestHandler.java b/adaptors/message-router/consumer/api/src/main/java/org/onap/ccsdk/sli/adaptors/messagerouter/consumer/api/RequestHandler.java
new file mode 100755
index 000000000..07a117843
--- /dev/null
+++ b/adaptors/message-router/consumer/api/src/main/java/org/onap/ccsdk/sli/adaptors/messagerouter/consumer/api/RequestHandler.java
@@ -0,0 +1,5 @@
+package org.onap.ccsdk.sli.adaptors.messagerouter.consumer.api;
+
+public interface RequestHandler {
+ public void handleRequest(String topic, String requestBody);
+}
diff --git a/adaptors/message-router/consumer/installer/pom.xml b/adaptors/message-router/consumer/installer/pom.xml
new file mode 100755
index 000000000..2b8eb688e
--- /dev/null
+++ b/adaptors/message-router/consumer/installer/pom.xml
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.sli.adaptors.messagerouter</groupId>
+ <artifactId>consumer.aggregate</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.adaptors.messagerouter</groupId>
+ <artifactId>consumer.installer</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>pom</packaging>
+
+ <properties>
+ <application.name>messagerouter-consumer</application.name>
+ <features.boot>messagerouter-consumer</features.boot>
+ <features.repositories>mvn:${project.groupId}/consumer.features/${project.version}/xml/features</features.repositories>
+ <include.transitive.dependencies>false</include.transitive.dependencies>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>consumer.api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>consumer.provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <version>2.6</version>
+ <executions>
+ <execution>
+ <id>maven-repo-zip</id>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ <phase>package</phase>
+ <configuration>
+ <attach>true</attach>
+ <finalName>stage/${application.name}-${project.version}</finalName>
+ <descriptors>
+ <descriptor>src/assembly/assemble_mvnrepo_zip.xml</descriptor>
+ </descriptors>
+ <appendAssemblyId>true</appendAssemblyId>
+ </configuration>
+ </execution>
+ <execution>
+ <id>installer-zip</id>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ <phase>package</phase>
+ <configuration>
+ <attach>true</attach>
+ <finalName>${application.name}-${project.version}-installer</finalName>
+ <descriptors>
+ <descriptor>src/assembly/assemble_installer_zip.xml</descriptor>
+ </descriptors>
+ <appendAssemblyId>false</appendAssemblyId>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>copy-dependencies</id>
+ <goals>
+ <goal>copy-dependencies</goal>
+ </goals>
+ <phase>prepare-package</phase>
+ <configuration>
+ <transitive>false</transitive>
+ <outputDirectory>${project.build.directory}/assembly/system</outputDirectory>
+ <overWriteReleases>false</overWriteReleases>
+ <overWriteSnapshots>true</overWriteSnapshots>
+ <overWriteIfNewer>true</overWriteIfNewer>
+ <useRepositoryLayout>true</useRepositoryLayout>
+ <addParentPoms>false</addParentPoms>
+ <copyPom>false</copyPom>
+ <includeGroupIds>${project.groupId}</includeGroupIds>
+ <scope>provided</scope>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <artifactId>maven-resources-plugin</artifactId>
+ <version>2.6</version>
+ <executions>
+ <execution>
+ <id>copy-version</id>
+ <goals>
+ <goal>copy-resources</goal>
+ </goals><!-- here the phase you need -->
+ <phase>validate</phase>
+ <configuration>
+ <outputDirectory>${basedir}/target/stage</outputDirectory>
+ <resources>
+ <resource>
+ <directory>src/main/resources/scripts</directory>
+ <includes>
+ <include>install-feature.sh</include>
+ </includes>
+ <filtering>true</filtering>
+ </resource>
+ </resources>
+ </configuration>
+ </execution>
+
+ </executions>
+ </plugin>
+
+ </plugins>
+ </build>
+</project>
diff --git a/adaptors/message-router/consumer/installer/src/assembly/assemble_installer_zip.xml b/adaptors/message-router/consumer/installer/src/assembly/assemble_installer_zip.xml
new file mode 100755
index 000000000..c6169a879
--- /dev/null
+++ b/adaptors/message-router/consumer/installer/src/assembly/assemble_installer_zip.xml
@@ -0,0 +1,59 @@
+<!--
+ ============LICENSE_START=======================================================
+ openECOMP : SDN-C
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property. All rights
+ reserved.
+ ================================================================================
+ 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.
+ ============LICENSE_END=========================================================
+ -->
+
+<!-- Defines how we build the .zip file which is our distribution. -->
+
+<assembly
+ xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
+ <id>installer_zip</id>
+ <formats>
+ <format>zip</format>
+ </formats>
+
+ <!-- we want "system" and related files right at the root level
+ as this file is suppose to be unzip on top of a karaf
+ distro. -->
+ <includeBaseDirectory>false</includeBaseDirectory>
+
+ <fileSets>
+ <fileSet>
+ <directory>target/stage/</directory>
+ <outputDirectory>${application.name}</outputDirectory>
+ <fileMode>755</fileMode>
+ <includes>
+ <include>*.sh</include>
+ </includes>
+ </fileSet>
+ <fileSet>
+ <directory>target/stage/</directory>
+ <outputDirectory>${application.name}</outputDirectory>
+ <fileMode>644</fileMode>
+ <excludes>
+ <exclude>*.sh</exclude>
+ </excludes>
+ </fileSet>
+ </fileSets>
+
+
+
+</assembly> \ No newline at end of file
diff --git a/adaptors/message-router/consumer/installer/src/assembly/assemble_mvnrepo_zip.xml b/adaptors/message-router/consumer/installer/src/assembly/assemble_mvnrepo_zip.xml
new file mode 100755
index 000000000..409c66224
--- /dev/null
+++ b/adaptors/message-router/consumer/installer/src/assembly/assemble_mvnrepo_zip.xml
@@ -0,0 +1,47 @@
+<!--
+ ============LICENSE_START=======================================================
+ openECOMP : SDN-C
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property. All rights
+ reserved.
+ ================================================================================
+ 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.
+ ============LICENSE_END=========================================================
+ -->
+
+<!-- Defines how we build the .zip file which is our distribution. -->
+
+<assembly
+ xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
+ <id>repo</id>
+ <formats>
+ <format>zip</format>
+ </formats>
+
+ <!-- we want "system" and related files right at the root level
+ as this file is suppose to be unzip on top of a karaf
+ distro. -->
+ <includeBaseDirectory>false</includeBaseDirectory>
+
+ <fileSets>
+ <fileSet>
+ <directory>target/assembly/</directory>
+ <outputDirectory>.</outputDirectory>
+ <excludes>
+ </excludes>
+ </fileSet>
+ </fileSets>
+
+</assembly> \ No newline at end of file
diff --git a/adaptors/message-router/consumer/installer/src/main/resources/scripts/install-feature.sh b/adaptors/message-router/consumer/installer/src/main/resources/scripts/install-feature.sh
new file mode 100755
index 000000000..6f2518f64
--- /dev/null
+++ b/adaptors/message-router/consumer/installer/src/main/resources/scripts/install-feature.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+
+###
+# ============LICENSE_START=======================================================
+# openECOMP : SDN-C
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights
+# reserved.
+# ================================================================================
+# 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.
+# ============LICENSE_END=========================================================
+###
+
+ODL_HOME=${ODL_HOME:-/opt/opendaylight/current}
+ODL_KARAF_CLIENT=${ODL_KARAF_CLIENT:-${ODL_HOME}/bin/client}
+INSTALLERDIR=$(dirname $0)
+
+REPOZIP=${INSTALLERDIR}/${features.boot}-${project.version}-repo.zip
+
+if [ -f ${REPOZIP} ]
+then
+ unzip -d ${ODL_HOME} ${REPOZIP}
+else
+ echo "ERROR : repo zip ($REPOZIP) not found"
+ exit 1
+fi
+
+${ODL_KARAF_CLIENT} feature:repo-add ${features.repositories}
+${ODL_KARAF_CLIENT} feature:install ${features.boot} \ No newline at end of file
diff --git a/adaptors/message-router/consumer/pom.xml b/adaptors/message-router/consumer/pom.xml
new file mode 100755
index 000000000..cad1bbba0
--- /dev/null
+++ b/adaptors/message-router/consumer/pom.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.sli.adaptors.messagerouter</groupId>
+ <artifactId>messagerouter-root</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>consumer.aggregate</artifactId>
+ <packaging>pom</packaging>
+
+ <modules>
+ <module>api</module>
+ <module>provider</module>
+ <module>installer</module>
+ </modules>
+</project>
diff --git a/adaptors/message-router/consumer/provider/pom.xml b/adaptors/message-router/consumer/provider/pom.xml
new file mode 100755
index 000000000..d3e568c40
--- /dev/null
+++ b/adaptors/message-router/consumer/provider/pom.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.sli.adaptors.messagerouter</groupId>
+ <artifactId>consumer.aggregate</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>consumer.provider</artifactId>
+ <packaging>bundle</packaging>
+
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>consumer.api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.google.code.gson</groupId>
+ <artifactId>gson</artifactId>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <configuration>
+ <instructions>
+ <Export-Package>${project.groupId}.consumer.provider.impl</Export-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/adaptors/message-router/consumer/provider/src/main/java/org/onap/ccsdk/sli/adaptors/messagerouter/consumer/provider/impl/AbstractBaseConsumer.java b/adaptors/message-router/consumer/provider/src/main/java/org/onap/ccsdk/sli/adaptors/messagerouter/consumer/provider/impl/AbstractBaseConsumer.java
new file mode 100755
index 000000000..8937f7b91
--- /dev/null
+++ b/adaptors/message-router/consumer/provider/src/main/java/org/onap/ccsdk/sli/adaptors/messagerouter/consumer/provider/impl/AbstractBaseConsumer.java
@@ -0,0 +1,207 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 - 2018 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.messagerouter.consumer.provider.impl;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Base64;
+
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.SSLSession;
+
+import org.onap.ccsdk.sli.adaptors.messagerouter.consumer.api.ConsumerApi;
+import org.onap.ccsdk.sli.adaptors.messagerouter.consumer.api.RequestHandler;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonParseException;
+
+/*
+ * java.net based client to build message router consumers
+ */
+public abstract class AbstractBaseConsumer implements ConsumerApi {
+ private static final Logger LOG = LoggerFactory.getLogger(AbstractBaseConsumer.class);
+ private static final String REQUEST_METHOD = "GET";
+
+ private final String host;
+ private final Integer connectTimeout;
+ private final Integer readTimeout;
+ private final String group;
+ private final String id;
+ private final String filter;
+ private final Integer limit;
+ private final Integer timeoutQueryParamValue;
+ private final String authorizationString;
+
+ protected RequestHandler requestHandler;
+ protected URL url;
+ protected String topic;
+
+ public AbstractBaseConsumer(String username, String password, String host, String authentication, Integer connectTimeout, Integer readTimeout, String group, String id, String filter, Integer limit, Integer timeoutQueryParamValue) {
+ this.host = host;
+ this.connectTimeout = connectTimeout;
+ this.readTimeout = readTimeout;
+ this.group = group;
+ this.id = id;
+ this.filter = filter;
+ this.limit = limit;
+ this.timeoutQueryParamValue = timeoutQueryParamValue;
+
+ if ("basic".equals(authentication)) {
+ if (username != null && password != null && username.length() > 0 && password.length() > 0) {
+ authorizationString = buildAuthorizationString(username, password);
+ } else {
+ throw new IllegalStateException("Authentication is set to basic but username or password is missing");
+ }
+ } else if ("noauth".equals(authentication)) {
+ authorizationString = null;
+ } else {
+ throw new IllegalStateException("Unknown authentication method: " + authentication);
+ }
+ }
+
+ protected void poll() {
+ String responseBody = performHttpOperation();
+ if (responseBody != null && !responseBody.startsWith("[]")) {
+ LOG.info("New message was fetched from MessageRouter.");
+ LOG.trace("Fetched message is\n{}", responseBody);
+ try {
+ String[] requests = new Gson().fromJson(responseBody, String[].class);
+ if (requests != null) {
+ for (String request : requests) {
+ if (request != null) {
+ requestHandler.handleRequest(topic,request);
+ }
+ }
+ } else {
+ LOG.warn("Deserialization of received message results in null array.", responseBody);
+ }
+ } catch (JsonParseException e) {
+ LOG.warn("Received message has bad format. Expected format is JSON.");
+ }
+ } else {
+ LOG.trace("No new message was fetched from MessageRouter.");
+ }
+ }
+
+ private String buildlUrlString(String topic) {
+ StringBuilder sb = new StringBuilder();
+ sb.append(host + "/events/" + topic + "/" + group + "/" + id);
+ sb.append("?timeout=" + timeoutQueryParamValue);
+
+ if (limit != null) {
+ sb.append("&limit=" + limit);
+ }
+ if (filter != null) {
+ sb.append("&filter=" + filter);
+ }
+ return sb.toString();
+ }
+
+ private String performHttpOperation() {
+ HttpURLConnection httpUrlConnection = null;
+ try {
+ httpUrlConnection = buildHttpURLConnection(url);
+ httpUrlConnection.setRequestMethod(REQUEST_METHOD);
+ httpUrlConnection.connect();
+ int status = httpUrlConnection.getResponseCode();
+ if (status < 300) {
+ return readFromStream(httpUrlConnection.getInputStream());
+ } else {
+ String response = readFromStream(httpUrlConnection.getErrorStream());
+ LOG.warn("Fetching message from MessageRouter on url {} failed with http status {}. Error message is\n{}.", url, status, response);
+ }
+ } catch (Exception e) {
+ LOG.warn("Exception was thrown during fetching message from MessageRouter on url {}.", url, e);
+ } finally {
+ if (httpUrlConnection != null) {
+ httpUrlConnection.disconnect();
+ }
+ }
+ return null;
+ }
+
+ private String buildAuthorizationString(String userName, String password) {
+ String basicAuthString = userName + ":" + password;
+ basicAuthString = Base64.getEncoder().encodeToString(basicAuthString.getBytes());
+ return "Basic " + basicAuthString;
+ }
+
+ protected HttpURLConnection buildHttpURLConnection(URL url) throws IOException {
+ HttpURLConnection httpUrlConnection = (HttpURLConnection) url.openConnection();
+ if (authorizationString != null) {
+ httpUrlConnection.setRequestProperty("Authorization", authorizationString);
+ }
+ httpUrlConnection.setRequestProperty("Accept", "application/json");
+ httpUrlConnection.setUseCaches(false);
+ httpUrlConnection.setConnectTimeout(connectTimeout);
+ httpUrlConnection.setReadTimeout(readTimeout);
+
+ // ignore hostname errors when dealing with HTTPS connections
+ if (httpUrlConnection instanceof HttpsURLConnection) {
+ HttpsURLConnection conn = (HttpsURLConnection) httpUrlConnection;
+ conn.setHostnameVerifier(new HostnameVerifier() {
+ @Override
+ public boolean verify(String arg0, SSLSession arg1) {
+ return true;
+ }
+ });
+ }
+ return httpUrlConnection;
+ }
+
+ protected String readFromStream(InputStream stream) throws IOException {
+ BufferedReader br = new BufferedReader(new InputStreamReader(stream));
+ StringBuilder sb = new StringBuilder();
+ String line;
+ while ((line = br.readLine()) != null) {
+ sb.append(line);
+ sb.append("\n");
+ }
+ br.close();
+ return sb.toString();
+ }
+
+ @Override
+ public void registerHandler(String topic, RequestHandler requestHandler) {
+ this.topic = topic;
+ try {
+ this.url = new URL(buildlUrlString(topic));
+ } catch (MalformedURLException e) {
+ LOG.error("Topic " + topic + " resulted in MalformedURLException", e);
+ }
+ this.requestHandler = requestHandler;
+ }
+
+ @Override
+ public void close() throws Exception {
+ //BaseConsumer doesn't spawn any threads
+ }
+
+}
diff --git a/adaptors/message-router/consumer/provider/src/main/java/org/onap/ccsdk/sli/adaptors/messagerouter/consumer/provider/impl/ConsumerFactory.java b/adaptors/message-router/consumer/provider/src/main/java/org/onap/ccsdk/sli/adaptors/messagerouter/consumer/provider/impl/ConsumerFactory.java
new file mode 100755
index 000000000..1aa02c70a
--- /dev/null
+++ b/adaptors/message-router/consumer/provider/src/main/java/org/onap/ccsdk/sli/adaptors/messagerouter/consumer/provider/impl/ConsumerFactory.java
@@ -0,0 +1,202 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights
+ * reserved.
+ *
+ * Modifications Copyright (C) 2019 IBM.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.ccsdk.sli.adaptors.messagerouter.consumer.provider.impl;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+import java.util.Properties;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ConsumerFactory {
+ private static final Logger LOG = LoggerFactory.getLogger(ConsumerFactory.class);
+
+ // Default values to minimize required configuration
+ private static final int DEFAULT_FETCH_PAUSE = 5000;
+ private static final int DEFAULT_CONNECT_TIMEOUT = 30000;
+ private static final int DEFAULT_READ_TIMEOUT = 180000;
+ private static final int DEFAULT_LIMIT = 5; // Limits the number of messages pulled in a single GET request
+ private static final int DEFAULT_TIMEOUT_QUERY_PARAM_VALUE = 15000;
+ private static final String DEFAULT_AUTH_METHOD = "basic";
+
+ // Required properties
+ protected final String username;
+ protected final String password;
+ protected final String host;
+ private final String group;
+ private final String id;
+
+ // Optional properties
+ protected Integer connectTimeout;
+ protected Integer readTimeout;
+ private Integer fetchPause;
+ private Integer limit;
+ private Integer timeoutQueryParamValue;
+ private String filter;
+ protected String auth;
+
+ public ConsumerFactory(Properties properties) {
+ // Required properties
+ username = properties.getProperty("username");
+ password = properties.getProperty("password");
+ host = properties.getProperty("host");
+ auth = properties.getProperty("auth");
+ group = properties.getProperty("group");
+ id = properties.getProperty("id");
+
+ // Optional properties
+ connectTimeout = readOptionalInteger(properties, "connectTimeoutSeconds");
+ readTimeout = readOptionalInteger(properties, "readTimeoutMinutes");
+ fetchPause = readOptionalInteger(properties, "fetchPause");
+ limit = readOptionalInteger(properties, "limit");
+ timeoutQueryParamValue = readOptionalInteger(properties, "timeout");
+ processFilter(properties.getProperty("filter"));
+
+ setDefaults();
+ }
+
+ public ConsumerFactory(String username, String password, String host, String group, String id, Integer connectTimeout, Integer readTimeout) {
+ this.username = username;
+ this.password = password;
+ this.host = host;
+ this.group = group;
+ this.id = id;
+ setDefaults();
+ }
+
+
+ public String getAuth() {
+ return auth;
+ }
+
+ public void setAuth(String auth) {
+ this.auth = auth;
+ }
+
+ public Integer getConnectTimeout() {
+ return connectTimeout;
+ }
+
+ public void setConnectTimeout(Integer connectTimeout) {
+ this.connectTimeout = connectTimeout;
+ }
+
+ public Integer getReadTimeout() {
+ return readTimeout;
+ }
+
+ public void setReadTimeout(Integer readTimeout) {
+ this.readTimeout = readTimeout;
+ }
+
+ public Integer getFetchPause() {
+ return fetchPause;
+ }
+
+ public void setFetchPause(Integer fetchPause) {
+ this.fetchPause = fetchPause;
+ }
+
+ public Integer getLimit() {
+ return limit;
+ }
+
+ public void setLimit(Integer limit) {
+ this.limit = limit;
+ }
+
+ public Integer getTimeoutQueryParamValue() {
+ return timeoutQueryParamValue;
+ }
+
+ public void setTimeoutQueryParamValue(Integer timeoutQueryParamValue) {
+ this.timeoutQueryParamValue = timeoutQueryParamValue;
+ }
+
+ public String getFilter() {
+ return filter;
+ }
+
+ public void setFilter(String filter) {
+ processFilter(filter);
+ }
+
+ private Integer readOptionalInteger(Properties properties, String propertyName) {
+ String stringValue = properties.getProperty(propertyName);
+ if (stringValue != null && stringValue.length() > 0) {
+ try {
+ return Integer.valueOf(stringValue);
+ } catch (NumberFormatException e) {
+ LOG.error("property " + propertyName + " had the value " + stringValue + " that could not be converted to an Integer", e);
+ }
+ }
+ return null;
+ }
+
+ public PollingConsumerImpl createPollingClient() {
+ return new PollingConsumerImpl(username, password, host, auth, connectTimeout, readTimeout, fetchPause, group, id, filter, limit, timeoutQueryParamValue);
+ }
+
+ public PullingConsumerImpl createPullingClient() {
+ return new PullingConsumerImpl(username, password, host, auth, connectTimeout, readTimeout, group, id, filter, limit, timeoutQueryParamValue);
+ }
+
+ private void processFilter(String filterString) {
+ if (filterString != null) {
+ if (filterString.length() > 0) {
+ try {
+ filter = URLEncoder.encode(filterString, StandardCharsets.UTF_8.name());
+ } catch (UnsupportedEncodingException e) {
+ LOG.warn("Couldn't encode filter string. Filter will be ignored.", e);
+ filter = null;
+ }
+ } else {
+ filter = null;
+ }
+ }
+ }
+
+ private void setDefaults() {
+ if (connectTimeout == null) {
+ connectTimeout = DEFAULT_CONNECT_TIMEOUT;
+ }
+ if (readTimeout == null) {
+ readTimeout = DEFAULT_READ_TIMEOUT;
+ }
+ if (fetchPause == null) {
+ fetchPause = DEFAULT_FETCH_PAUSE;
+ }
+ if (limit == null) {
+ limit = DEFAULT_LIMIT;
+ }
+ if (timeoutQueryParamValue == null) {
+ timeoutQueryParamValue = DEFAULT_TIMEOUT_QUERY_PARAM_VALUE;
+ }
+ if (auth == null) {
+ auth = DEFAULT_AUTH_METHOD;
+ }
+ }
+
+}
diff --git a/adaptors/message-router/consumer/provider/src/main/java/org/onap/ccsdk/sli/adaptors/messagerouter/consumer/provider/impl/PollingConsumerImpl.java b/adaptors/message-router/consumer/provider/src/main/java/org/onap/ccsdk/sli/adaptors/messagerouter/consumer/provider/impl/PollingConsumerImpl.java
new file mode 100644
index 000000000..263e94ca9
--- /dev/null
+++ b/adaptors/message-router/consumer/provider/src/main/java/org/onap/ccsdk/sli/adaptors/messagerouter/consumer/provider/impl/PollingConsumerImpl.java
@@ -0,0 +1,100 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 - 2018 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.messagerouter.consumer.provider.impl;
+
+import org.onap.ccsdk.sli.adaptors.messagerouter.consumer.api.PollingConsumer;
+import org.onap.ccsdk.sli.adaptors.messagerouter.consumer.api.RequestHandler;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/*
+ * java.net based client to build message router consumers
+ */
+public class PollingConsumerImpl implements PollingConsumer {
+
+ //RunnableConsumer is a private inner class so run cannot be called from other code
+ private class RunnableConsumer extends AbstractBaseConsumer implements Runnable, PollingConsumer {
+ private final Logger LOG = LoggerFactory.getLogger(PollingConsumerImpl.class);
+ private volatile Thread t;
+ private final Integer fetchPause;
+
+ public RunnableConsumer(String username, String password, String host, String authentication, Integer connectTimeout, Integer readTimeout, Integer fetchPause, String group, String id, String filter, Integer limit, Integer timeoutQueryParamValue) {
+ super(username, password, host, authentication, connectTimeout, readTimeout, group, id, filter, limit, timeoutQueryParamValue);
+ this.fetchPause = fetchPause;
+ }
+
+ public void start() {
+ t = new Thread(this);
+ t.start();
+ LOG.info("ConsumerImpl started. Fetch period is {} ms.", fetchPause);
+ }
+
+ public void stop() {
+ t = null;
+ LOG.info("ConsumerImpl stopped.");
+ }
+
+ @Override
+ public void run() {
+ if (this.url != null) {
+ Thread thisThread = Thread.currentThread();
+ while (t == thisThread) {
+ poll();
+ try {
+ LOG.trace("Next fetch from MessageRouter url {} after {} milliseconds.", url, fetchPause);
+ Thread.sleep(fetchPause);
+ } catch (InterruptedException e) {
+ LOG.warn("Thread sleep was interrupted.", e);
+ }
+ }
+ } else {
+ LOG.error("URL is null, can't listen for messages");
+ }
+ }
+
+ @Override
+ public void close() throws Exception {
+ stop();
+ }
+ }
+
+ private RunnableConsumer c;
+
+ public PollingConsumerImpl(String username, String password, String host, String authentication, Integer connectTimeout, Integer readTimeout, Integer fetchPause, String group, String id, String filter, Integer limit, Integer timeoutQueryParamValue) {
+ c = new RunnableConsumer(username, password, host, authentication, connectTimeout, readTimeout, fetchPause, group, id, filter, limit, timeoutQueryParamValue);
+ }
+
+ @Override
+ public void start() {
+ c.start();
+ }
+
+ @Override
+ public void registerHandler(String topic, RequestHandler requestHandler) {
+ c.registerHandler(topic, requestHandler);
+ }
+
+ @Override
+ public void close() throws Exception {
+ c.close();
+ }
+}
diff --git a/adaptors/message-router/consumer/provider/src/main/java/org/onap/ccsdk/sli/adaptors/messagerouter/consumer/provider/impl/PullingConsumerImpl.java b/adaptors/message-router/consumer/provider/src/main/java/org/onap/ccsdk/sli/adaptors/messagerouter/consumer/provider/impl/PullingConsumerImpl.java
new file mode 100755
index 000000000..e5a5bc4d8
--- /dev/null
+++ b/adaptors/message-router/consumer/provider/src/main/java/org/onap/ccsdk/sli/adaptors/messagerouter/consumer/provider/impl/PullingConsumerImpl.java
@@ -0,0 +1,39 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 - 2019 AT&T Intellectual Property. All rights
+ * reserved.
+ *
+ * Modifications Copyright (C) 2019 IBM.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.ccsdk.sli.adaptors.messagerouter.consumer.provider.impl;
+
+import org.onap.ccsdk.sli.adaptors.messagerouter.consumer.api.PullingConsumer;
+
+
+public class PullingConsumerImpl extends AbstractBaseConsumer implements PullingConsumer {
+
+ public PullingConsumerImpl(String username, String password, String host, String authentication, Integer connectTimeout, Integer readTimeout, String group, String id, String filter, Integer limit, Integer timeoutQueryParamValue) {
+ super(username, password, host, authentication, connectTimeout, readTimeout, group, id, filter, limit, timeoutQueryParamValue);
+ }
+
+ @Override
+ public void pull() {
+ this.poll();
+ }
+
+}
diff --git a/adaptors/message-router/consumer/provider/src/test/java/org/onap/ccsdk/sli/adaptors/messagerouter/consumer/provider/impl/AbstractBaseConsumerTest.java b/adaptors/message-router/consumer/provider/src/test/java/org/onap/ccsdk/sli/adaptors/messagerouter/consumer/provider/impl/AbstractBaseConsumerTest.java
new file mode 100644
index 000000000..75873385b
--- /dev/null
+++ b/adaptors/message-router/consumer/provider/src/test/java/org/onap/ccsdk/sli/adaptors/messagerouter/consumer/provider/impl/AbstractBaseConsumerTest.java
@@ -0,0 +1,91 @@
+package org.onap.ccsdk.sli.adaptors.messagerouter.consumer.provider.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.net.HttpURLConnection;
+import java.net.URL;
+
+import org.junit.Test;
+import org.onap.ccsdk.sli.adaptors.messagerouter.consumer.api.RequestHandler;
+
+public class AbstractBaseConsumerTest {
+ private class DummyConsumer extends AbstractBaseConsumer {
+
+ public DummyConsumer(String username, String password, String host, String authentication, Integer connectTimeout, Integer readTimeout, String group, String id, String filter, Integer limit, Integer timeoutQueryParamValue) {
+ super(username, password, host, authentication, connectTimeout, readTimeout, group, id, filter, limit, timeoutQueryParamValue);
+ }
+
+ }
+
+ public DummyConsumer getAuthDummy() {
+ String username = "deadpool";
+ String password = "notSECURE";
+ String host = "http://localhost:7001";
+ String group = "myCluster";
+ String id = "node1";
+ Integer connectTimeout = 10000;
+ Integer readTimeout = 20000;
+ String authentication = "basic";
+ String filter = null;
+ Integer limit = 3;
+ Integer timeoutQueryParamValue = 5000;
+ return new DummyConsumer(username, password, host, authentication, connectTimeout, readTimeout, group, id, filter, limit, timeoutQueryParamValue);
+ }
+
+ @Test
+ public void createDummyWithAuth() {
+ assertNotNull(getAuthDummy());
+ }
+
+ @Test
+ public void createDummyNohAuth() {
+ String username = null;
+ String password = null;
+ String host = "http://localhost:7001";
+ String group = "myCluster";
+ String id = "node1";
+ Integer connectTimeout = 10000;
+ Integer readTimeout = 20000;
+ String authentication = "noauth";
+ String filter = null;
+ Integer limit = 3;
+ Integer timeoutQueryParamValue = 5000;
+ assertNotNull(new DummyConsumer(username, password, host, authentication, connectTimeout, readTimeout, group, id, filter, limit, timeoutQueryParamValue));
+ }
+
+ @Test
+ public void callClose() throws Exception {
+ DummyConsumer dummy = getAuthDummy();
+ dummy.close();
+ assertNotNull(dummy);
+ }
+
+ @Test
+ public void registerDummyHandler() throws Exception {
+ DummyConsumer dummy = getAuthDummy();
+ String topic = "politics";
+ RequestHandler requestHandler = new RequestHandler() {
+
+ @Override
+ public void handleRequest(String topic, String requestBody) {
+ // TODO Auto-generated method stub
+
+ };
+
+ };
+ dummy.registerHandler(topic, requestHandler);
+ assertEquals(new URL("http://localhost:7001/events/politics/myCluster/node1?timeout=5000&limit=3"), dummy.url);
+ assertEquals(topic, dummy.topic);
+
+ }
+
+ @Test
+ public void buildURL() throws Exception {
+ DummyConsumer dummy = getAuthDummy();
+ HttpURLConnection connection = dummy.buildHttpURLConnection(new URL("http://localhost:7001/events/politics/myCluster/node1?timeout=5000&limit=3"));
+ assertNotNull(connection);
+ assertEquals("application/json", connection.getRequestProperty("Accept"));
+ }
+
+}
diff --git a/adaptors/message-router/consumer/provider/src/test/java/org/onap/ccsdk/sli/adaptors/messagerouter/consumer/provider/impl/ConsumerFactoryTest.java b/adaptors/message-router/consumer/provider/src/test/java/org/onap/ccsdk/sli/adaptors/messagerouter/consumer/provider/impl/ConsumerFactoryTest.java
new file mode 100644
index 000000000..d1018a014
--- /dev/null
+++ b/adaptors/message-router/consumer/provider/src/test/java/org/onap/ccsdk/sli/adaptors/messagerouter/consumer/provider/impl/ConsumerFactoryTest.java
@@ -0,0 +1,164 @@
+package org.onap.ccsdk.sli.adaptors.messagerouter.consumer.provider.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.util.Properties;
+
+import org.junit.Test;
+
+public class ConsumerFactoryTest {
+
+ @Test
+ public void testFactoryClientCreation() throws Exception {
+ Properties props = new Properties();
+ String userName = "deadpool";
+ String password = "notSECURE";
+ String host = "http://localhost:7001";
+ String group = "myCluster";
+ String id = "node1";
+ Integer connectTimeout = 10000;
+ Integer readTimeout = 20000;
+ props.put("username", userName);
+ props.put("password", password);
+ props.put("host", host);
+ props.put("group", group);
+
+ ConsumerFactory factory = new ConsumerFactory(userName, password, host, group, id, connectTimeout, readTimeout);
+ assertNotNull(factory.createPollingClient());
+ assertNotNull(factory.createPullingClient());
+ }
+
+ @Test
+ public void testFactoryDefaults() throws Exception {
+ Properties props = new Properties();
+ String userName = "deadpool";
+ String password = "notSECURE";
+ String host = "http://localhost:7001";
+ String group = "myCluster";
+ String id = "node1";
+ Integer connectTimeout = 10000;
+ Integer readTimeout = 20000;
+ props.put("username", userName);
+ props.put("password", password);
+ props.put("host", host);
+ props.put("group", group);
+
+ ConsumerFactory factory = new ConsumerFactory(userName, password, host, group, id, connectTimeout, readTimeout);
+
+ assertNotNull(factory.getAuth());
+ assertNotNull(factory.getConnectTimeout());
+ assertNotNull(factory.getReadTimeout());
+ assertNotNull(factory.getFetchPause());
+ assertNotNull(factory.getLimit());
+ assertNotNull(factory.getTimeoutQueryParamValue());
+ }
+
+ @Test
+ public void testFactoryDefaultsWithProps() {
+ Properties props = new Properties();
+ String userName = "deadpool";
+ String password = "notSECURE";
+ String host = "http://localhost:7001";
+ String auth = "basic";
+ String group = "myCluster";
+ props.put("username", userName);
+ props.put("password", password);
+ props.put("host", host);
+ props.put("group", group);
+
+ ConsumerFactory factory = new ConsumerFactory(props);
+
+ assertNotNull(factory.getAuth());
+ assertNotNull(factory.getConnectTimeout());
+ assertNotNull(factory.getReadTimeout());
+ assertNotNull(factory.getFetchPause());
+ assertNotNull(factory.getLimit());
+ assertNotNull(factory.getTimeoutQueryParamValue());
+ }
+
+ @Test
+ public void testFactoryOverrides() throws Exception {
+ Properties props = new Properties();
+ String userName = "deadpool";
+ String password = "notSECURE";
+ String host = "http://localhost:7001";
+ String group = "myCluster";
+ props.put("username", userName);
+ props.put("password", password);
+ props.put("host", host);
+ props.put("group", group);
+
+ String connectTimeout = "200";
+ String readTimeout = "300";
+ String fetchPause = "1000";
+ String auth = "noauth";
+ String timeoutQueryParamValue = "50";
+ String limit = "2";
+ props.put("connectTimeoutSeconds", connectTimeout);
+ props.put("readTimeoutMinutes", readTimeout);
+ props.put("fetchPause", fetchPause);
+ props.put("auth", auth);
+ props.put("timeout", timeoutQueryParamValue);
+ props.put("limit", limit);
+
+ ConsumerFactory factory = new ConsumerFactory(props);
+
+ assertEquals(auth, factory.getAuth());
+ assertEquals(Integer.valueOf(connectTimeout), factory.getConnectTimeout());
+ assertEquals(Integer.valueOf(readTimeout), factory.getReadTimeout());
+ assertEquals(Integer.valueOf(fetchPause), factory.getFetchPause());
+ assertEquals(Integer.valueOf(limit), factory.getLimit());
+ assertEquals(Integer.valueOf(timeoutQueryParamValue), factory.getTimeoutQueryParamValue());
+ }
+
+ @Test
+ public void testManualOverrides() {
+ Properties props = new Properties();
+ String userName = "deadpool";
+ String password = "notSECURE";
+ String host = "http://localhost:7001";
+ String auth = "basic";
+ String group = "myCluster";
+ props.put("username", userName);
+ props.put("password", password);
+ props.put("host", host);
+ props.put("group", group);
+
+ ConsumerFactory factory = new ConsumerFactory(props);
+
+ assertNotNull(factory.getAuth());
+ assertNotNull(factory.getConnectTimeout());
+ assertNotNull(factory.getReadTimeout());
+ assertNotNull(factory.getFetchPause());
+ assertNotNull(factory.getLimit());
+ assertNotNull(factory.getTimeoutQueryParamValue());
+ String newAuth = "noauth";
+ factory.setAuth(newAuth);
+ assertEquals(newAuth, factory.getAuth());
+
+ Integer connectTimeout = 1;
+ factory.setConnectTimeout(connectTimeout);
+ assertEquals(connectTimeout, factory.getConnectTimeout());
+
+ Integer fetchPause = 5;
+ factory.setFetchPause(fetchPause);
+ assertEquals(fetchPause, factory.getFetchPause());
+
+ factory.setFilter("\"filter\":{\n" + "\"class\":\"And\",\n" + "\"filters\":\n" + "[\n" + "{ \"class\":\"Equals\", \"foo\":\"abc\" },\n" + "{ \"class\":\"Assigned\", \"field\":\"bar\" }\n" + "]\n" + "}");
+ assertNotNull(factory.getFilter());
+
+ Integer limit = 3;
+ factory.setLimit(limit);
+ assertEquals(limit, factory.getLimit());
+
+ Integer readTimeout = 2;
+ factory.setReadTimeout(readTimeout);
+ assertEquals(readTimeout, factory.getReadTimeout());
+
+ Integer timeoutQueryParamValue = 47;
+ factory.setTimeoutQueryParamValue(timeoutQueryParamValue);
+ assertEquals(timeoutQueryParamValue, factory.getTimeoutQueryParamValue());
+ }
+
+}
diff --git a/adaptors/message-router/pom.xml b/adaptors/message-router/pom.xml
new file mode 100755
index 000000000..63d267d2a
--- /dev/null
+++ b/adaptors/message-router/pom.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>binding-parent</artifactId>
+ <version>2.1.0</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.adaptors.messagerouter</groupId>
+ <artifactId>messagerouter-root</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>pom</packaging>
+
+ <modules>
+ <module>publisher</module>
+ <module>consumer</module>
+ </modules>
+
+ <build>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <extensions>true</extensions>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+</project>
diff --git a/adaptors/message-router/publisher/README.md b/adaptors/message-router/publisher/README.md
new file mode 100755
index 000000000..58c1bf470
--- /dev/null
+++ b/adaptors/message-router/publisher/README.md
@@ -0,0 +1,8 @@
+# Publisher
+
+## Modules
+- api - exports the publisher interface for clients and providers to import
+- features - used for managing the feature repository for publisher
+- installer - provides a simple install script
+- provider - provides an implementation of the publisher api, this implementation assumes the controller has a single identity for publishing to DMAAP message router
+- sample.client - a dummy client that posts a simple message to a configured topic during its initialization
diff --git a/adaptors/message-router/publisher/api/pom.xml b/adaptors/message-router/publisher/api/pom.xml
new file mode 100755
index 000000000..7831284cf
--- /dev/null
+++ b/adaptors/message-router/publisher/api/pom.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.sli.adaptors.messagerouter</groupId>
+ <artifactId>publisher.aggregate</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>publisher.api</artifactId>
+ <packaging>bundle</packaging>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <configuration>
+ <instructions>
+ <Export-Package>org.onap.ccsdk.sli.adaptors.messagerouter.publisher.api</Export-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/adaptors/message-router/publisher/api/src/main/java/org/onap/ccsdk/sli/adaptors/messagerouter/publisher/api/PublisherApi.java b/adaptors/message-router/publisher/api/src/main/java/org/onap/ccsdk/sli/adaptors/messagerouter/publisher/api/PublisherApi.java
new file mode 100755
index 000000000..3551e0441
--- /dev/null
+++ b/adaptors/message-router/publisher/api/src/main/java/org/onap/ccsdk/sli/adaptors/messagerouter/publisher/api/PublisherApi.java
@@ -0,0 +1,5 @@
+package org.onap.ccsdk.sli.adaptors.messagerouter.publisher.api;
+
+public interface PublisherApi {
+ public Boolean publish(String topic, String body);
+}
diff --git a/adaptors/message-router/publisher/installer/pom.xml b/adaptors/message-router/publisher/installer/pom.xml
new file mode 100644
index 000000000..bc0565e5b
--- /dev/null
+++ b/adaptors/message-router/publisher/installer/pom.xml
@@ -0,0 +1,133 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.sli.adaptors.messagerouter</groupId>
+ <artifactId>publisher.aggregate</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.adaptors.messagerouter</groupId>
+ <artifactId>publisher.installer</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>pom</packaging>
+
+ <properties>
+ <application.name>messagerouter-publisher</application.name>
+ <features.boot>messagerouter-publisher</features.boot>
+ <features.repositories>mvn:${project.groupId}/publisher.features/${project.version}/xml/features</features.repositories>
+ <include.transitive.dependencies>false</include.transitive.dependencies>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>publisher.api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>publisher.provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>sample.client</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <version>2.6</version>
+ <executions>
+ <execution>
+ <id>maven-repo-zip</id>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ <phase>package</phase>
+ <configuration>
+ <attach>true</attach>
+ <finalName>stage/${application.name}-${project.version}</finalName>
+ <descriptors>
+ <descriptor>src/assembly/assemble_mvnrepo_zip.xml</descriptor>
+ </descriptors>
+ <appendAssemblyId>true</appendAssemblyId>
+ </configuration>
+ </execution>
+ <execution>
+ <id>installer-zip</id>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ <phase>package</phase>
+ <configuration>
+ <attach>true</attach>
+ <finalName>${application.name}-${project.version}-installer</finalName>
+ <descriptors>
+ <descriptor>src/assembly/assemble_installer_zip.xml</descriptor>
+ </descriptors>
+ <appendAssemblyId>false</appendAssemblyId>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>copy-dependencies</id>
+ <goals>
+ <goal>copy-dependencies</goal>
+ </goals>
+ <phase>prepare-package</phase>
+ <configuration>
+ <transitive>false</transitive>
+ <outputDirectory>${project.build.directory}/assembly/system</outputDirectory>
+ <overWriteReleases>false</overWriteReleases>
+ <overWriteSnapshots>true</overWriteSnapshots>
+ <overWriteIfNewer>true</overWriteIfNewer>
+ <useRepositoryLayout>true</useRepositoryLayout>
+ <addParentPoms>false</addParentPoms>
+ <copyPom>false</copyPom>
+ <includeGroupIds>${project.groupId}</includeGroupIds>
+ <scope>provided</scope>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <artifactId>maven-resources-plugin</artifactId>
+ <version>2.6</version>
+ <executions>
+ <execution>
+ <id>copy-version</id>
+ <goals>
+ <goal>copy-resources</goal>
+ </goals><!-- here the phase you need -->
+ <phase>validate</phase>
+ <configuration>
+ <outputDirectory>${basedir}/target/stage</outputDirectory>
+ <resources>
+ <resource>
+ <directory>src/main/resources/scripts</directory>
+ <includes>
+ <include>install-feature.sh</include>
+ </includes>
+ <filtering>true</filtering>
+ </resource>
+ </resources>
+ </configuration>
+ </execution>
+
+ </executions>
+ </plugin>
+
+ </plugins>
+ </build>
+</project>
diff --git a/adaptors/message-router/publisher/installer/src/assembly/assemble_installer_zip.xml b/adaptors/message-router/publisher/installer/src/assembly/assemble_installer_zip.xml
new file mode 100644
index 000000000..c6169a879
--- /dev/null
+++ b/adaptors/message-router/publisher/installer/src/assembly/assemble_installer_zip.xml
@@ -0,0 +1,59 @@
+<!--
+ ============LICENSE_START=======================================================
+ openECOMP : SDN-C
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property. All rights
+ reserved.
+ ================================================================================
+ 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.
+ ============LICENSE_END=========================================================
+ -->
+
+<!-- Defines how we build the .zip file which is our distribution. -->
+
+<assembly
+ xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
+ <id>installer_zip</id>
+ <formats>
+ <format>zip</format>
+ </formats>
+
+ <!-- we want "system" and related files right at the root level
+ as this file is suppose to be unzip on top of a karaf
+ distro. -->
+ <includeBaseDirectory>false</includeBaseDirectory>
+
+ <fileSets>
+ <fileSet>
+ <directory>target/stage/</directory>
+ <outputDirectory>${application.name}</outputDirectory>
+ <fileMode>755</fileMode>
+ <includes>
+ <include>*.sh</include>
+ </includes>
+ </fileSet>
+ <fileSet>
+ <directory>target/stage/</directory>
+ <outputDirectory>${application.name}</outputDirectory>
+ <fileMode>644</fileMode>
+ <excludes>
+ <exclude>*.sh</exclude>
+ </excludes>
+ </fileSet>
+ </fileSets>
+
+
+
+</assembly> \ No newline at end of file
diff --git a/adaptors/message-router/publisher/installer/src/assembly/assemble_mvnrepo_zip.xml b/adaptors/message-router/publisher/installer/src/assembly/assemble_mvnrepo_zip.xml
new file mode 100644
index 000000000..377b5b153
--- /dev/null
+++ b/adaptors/message-router/publisher/installer/src/assembly/assemble_mvnrepo_zip.xml
@@ -0,0 +1,49 @@
+<!--
+ ============LICENSE_START=======================================================
+ openECOMP : SDN-C
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property. All rights
+ reserved.
+ ================================================================================
+ 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.
+ ============LICENSE_END=========================================================
+ -->
+
+<!-- Defines how we build the .zip file which is our distribution. -->
+
+<assembly
+ xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
+ <id>repo</id>
+ <formats>
+ <format>zip</format>
+ </formats>
+
+ <!-- we want "system" and related files right at the root level
+ as this file is suppose to be unzip on top of a karaf
+ distro. -->
+ <includeBaseDirectory>false</includeBaseDirectory>
+
+ <fileSets>
+ <fileSet>
+ <directory>target/assembly/</directory>
+ <outputDirectory>.</outputDirectory>
+ <excludes>
+ </excludes>
+ </fileSet>
+ </fileSets>
+
+
+
+</assembly> \ No newline at end of file
diff --git a/adaptors/message-router/publisher/installer/src/main/resources/scripts/install-feature.sh b/adaptors/message-router/publisher/installer/src/main/resources/scripts/install-feature.sh
new file mode 100644
index 000000000..15dc0c27a
--- /dev/null
+++ b/adaptors/message-router/publisher/installer/src/main/resources/scripts/install-feature.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+
+###
+# ============LICENSE_START=======================================================
+# openECOMP : SDN-C
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights
+# reserved.
+# ================================================================================
+# 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.
+# ============LICENSE_END=========================================================
+###
+
+ODL_HOME=${ODL_HOME:-/opt/opendaylight/current}
+ODL_KARAF_CLIENT=${ODL_KARAF_CLIENT:-${ODL_HOME}/bin/client}
+INSTALLERDIR=$(dirname $0)
+
+REPOZIP=${INSTALLERDIR}/${features.boot}-${project.version}.zip
+
+if [ -f ${REPOZIP} ]
+then
+ unzip -d ${ODL_HOME} ${REPOZIP}
+else
+ echo "ERROR : repo zip ($REPOZIP) not found"
+ exit 1
+fi
+
+${ODL_KARAF_CLIENT} feature:repo-add ${features.repositories}
+${ODL_KARAF_CLIENT} feature:install ${features.boot} \ No newline at end of file
diff --git a/adaptors/message-router/publisher/pom.xml b/adaptors/message-router/publisher/pom.xml
new file mode 100755
index 000000000..6fb9c82d3
--- /dev/null
+++ b/adaptors/message-router/publisher/pom.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.sli.adaptors.messagerouter</groupId>
+ <artifactId>messagerouter-root</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>publisher.aggregate</artifactId>
+ <packaging>pom</packaging>
+
+ <modules>
+ <module>api</module>
+ <module>provider</module>
+ <module>sample.client</module>
+ <module>installer</module>
+ </modules>
+</project>
diff --git a/adaptors/message-router/publisher/provider/pom.xml b/adaptors/message-router/publisher/provider/pom.xml
new file mode 100755
index 000000000..7cd311448
--- /dev/null
+++ b/adaptors/message-router/publisher/provider/pom.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.sli.adaptors.messagerouter</groupId>
+ <artifactId>publisher.aggregate</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>publisher.provider</artifactId>
+ <packaging>bundle</packaging>
+
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>publisher.api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <configuration>
+ <instructions>
+ <Private-Package>${project.groupId}.publisher.provider.impl</Private-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/adaptors/message-router/publisher/provider/src/main/java/org/onap/ccsdk/sli/adaptors/messagerouter/publisher/provider/impl/PublisherApiImpl.java b/adaptors/message-router/publisher/provider/src/main/java/org/onap/ccsdk/sli/adaptors/messagerouter/publisher/provider/impl/PublisherApiImpl.java
new file mode 100755
index 000000000..4aedc6071
--- /dev/null
+++ b/adaptors/message-router/publisher/provider/src/main/java/org/onap/ccsdk/sli/adaptors/messagerouter/publisher/provider/impl/PublisherApiImpl.java
@@ -0,0 +1,178 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ *
+ * Modifications Copyright (C) 2019 IBM.
+ * ===========================================================================
+ * 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.
+ * ============LICENSE_END====================================================
+ *
+ */
+package org.onap.ccsdk.sli.adaptors.messagerouter.publisher.provider.impl;
+
+import java.io.BufferedReader;
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.HttpURLConnection;
+import java.net.SocketException;
+import java.net.URL;
+import java.util.Base64;
+
+import org.onap.ccsdk.sli.adaptors.messagerouter.publisher.api.PublisherApi;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class PublisherApiImpl implements PublisherApi {
+ private static final Logger logger = LoggerFactory.getLogger(PublisherApiImpl.class);
+ protected static final Integer DEFAULT_CONNECT_TIMEOUT = 30000; // will be treated as 30 seconds
+ protected static final Integer DEFAULT_READ_TIMEOUT = 180000; // will be treated as 3 minutes
+ private String authorizationString;
+ protected Integer connectTimeout;
+ protected Integer readTimeout;
+ protected String baseUrl;
+ protected String username;
+ protected String[] hosts;
+ private String password;
+
+ public PublisherApiImpl() {
+ connectTimeout = DEFAULT_CONNECT_TIMEOUT;
+ readTimeout = DEFAULT_READ_TIMEOUT;
+ }
+
+ public void setUsername(String username) {
+ this.username = username;
+ setAuthorizationString();
+ }
+
+ public void setPassword(String password) {
+ this.password = password;
+ setAuthorizationString();
+ }
+
+ public void setHost(String hostString) {
+ // a comma separated list of hosts can be passed in or a single host may be used
+ if (!hostString.contains(",")) {
+ this.hosts = new String[] { hostString };
+ } else {
+ this.hosts = hostString.split(",");
+ }
+ }
+
+ public void init() {
+ setAuthorizationString();
+ }
+
+ protected String buildUrlString(Integer hostIndex, String topic) {
+ return hosts[hostIndex] + "/events/" + topic;
+ }
+
+ protected void configureHttpURLConnection(HttpURLConnection httpUrlConnection) {
+ httpUrlConnection.setRequestProperty("Content-Type", "application/json");
+ }
+
+ public Boolean publish(String topic, String body) {
+ for (int hostIndex = 0; hostIndex < hosts.length; hostIndex++) {
+ HttpURLConnection httpUrlConnection = null;
+ URL url = null;
+ try {
+ url = new URL(buildUrlString(hostIndex, topic));
+ logger.info("Publishing body to topic {} using the url {}", topic, url);
+ logger.info("Message to publish is\n{}", body);
+ httpUrlConnection = buildHttpURLConnection(url);
+ httpUrlConnection.setDoInput(true);
+ httpUrlConnection.setDoOutput(true);
+ httpUrlConnection.setUseCaches(false);
+ httpUrlConnection.setRequestMethod("POST");
+
+ // Write message
+ httpUrlConnection.setRequestProperty("Content-Length", Integer.toString(body.length()));
+ DataOutputStream outStr = new DataOutputStream(httpUrlConnection.getOutputStream());
+ outStr.write(body.getBytes());
+ outStr.close();
+
+ int status = httpUrlConnection.getResponseCode();
+ logger.info("Publishing body for topic {} using url {} returned status {}.", topic, url, status);
+ if (status < 300) {
+ String responseFromDMaaP = readFromStream(httpUrlConnection.getInputStream());
+ logger.info("Message router response is\n{}", responseFromDMaaP);
+ return true;
+ } else {
+ if (httpUrlConnection.getErrorStream() != null) {
+ String responseFromDMaaP = readFromStream(httpUrlConnection.getErrorStream());
+ logger.warn("Publishing body for topic {} using url {} failed." + " Error message is\n{}",
+ topic, url, responseFromDMaaP);
+ }
+ return false;
+ }
+
+ } catch (SocketException socketException) {
+ logger.error("SocketException was thrown during publishing message to DMaaP on url {}.", url,
+ socketException);
+ if (hostIndex < hosts.length) {
+ logger.info("Message sent to {} failed with a SocketException, but will be tried on {}",
+ hosts[hostIndex], hosts[hostIndex + 1]);
+ }
+ } catch (Exception e) {
+ logger.warn("Exception was thrown during publishing message to DMaaP on url {}.", url, e);
+ return false;
+ } finally {
+ if (httpUrlConnection != null) {
+ httpUrlConnection.disconnect();
+ }
+ }
+ }
+ return false;
+ }
+
+ protected void setAuthorizationString() {
+ String str = buildAuthorizationString(this.username, this.password);
+ this.authorizationString = str;
+ //System.out.println(this.authorizationString);
+ }
+
+ protected String buildAuthorizationString(String username, String password) {
+ String basicAuthString = username + ":" + password;
+ basicAuthString = Base64.getEncoder().encodeToString(basicAuthString.getBytes());
+ return "Basic " + basicAuthString;
+ }
+
+ protected HttpURLConnection buildHttpURLConnection(URL url) throws IOException {
+ HttpURLConnection httpUrlConnection = (HttpURLConnection) url.openConnection();
+ if (authorizationString != null) {
+ System.out.println(authorizationString);
+ httpUrlConnection.setRequestProperty("Authorization", authorizationString);
+ }
+ httpUrlConnection.setRequestProperty("Accept", "application/json");
+ httpUrlConnection.setUseCaches(false);
+ httpUrlConnection.setConnectTimeout(connectTimeout);
+ httpUrlConnection.setReadTimeout(readTimeout);
+ configureHttpURLConnection(httpUrlConnection);
+ return httpUrlConnection;
+ }
+
+ protected String readFromStream(InputStream stream) throws IOException {
+ BufferedReader br = new BufferedReader(new InputStreamReader(stream));
+ StringBuilder sb = new StringBuilder();
+ String line;
+ while ((line = br.readLine()) != null) {
+ sb.append(line);
+ }
+ br.close();
+ return sb.toString();
+ }
+
+} \ No newline at end of file
diff --git a/adaptors/message-router/publisher/provider/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/adaptors/message-router/publisher/provider/src/main/resources/OSGI-INF/blueprint/blueprint.xml
new file mode 100755
index 000000000..4702a6260
--- /dev/null
+++ b/adaptors/message-router/publisher/provider/src/main/resources/OSGI-INF/blueprint/blueprint.xml
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+ xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.2.0">
+
+ <bean id="publisher"
+ class="org.onap.ccsdk.sli.adaptors.messagerouter.publisher.provider.impl.PublisherApiImpl">
+ <cm:managed-properties
+ persistent-id="org.onap.ccsdk.sli.adaptors.messagerouter.publisher.provider"
+ update-strategy="container-managed" />
+ </bean>
+
+ <service ref="publisher" interface="org.onap.ccsdk.sli.adaptors.messagerouter.publisher.api.PublisherApi" />
+
+</blueprint> \ No newline at end of file
diff --git a/adaptors/message-router/publisher/provider/src/test/java/org/onap/ccsdk/sli/adaptors/messagerouter/publisher/provider/impl/PublisherApiImplTest.java b/adaptors/message-router/publisher/provider/src/test/java/org/onap/ccsdk/sli/adaptors/messagerouter/publisher/provider/impl/PublisherApiImplTest.java
new file mode 100644
index 000000000..53744f73e
--- /dev/null
+++ b/adaptors/message-router/publisher/provider/src/test/java/org/onap/ccsdk/sli/adaptors/messagerouter/publisher/provider/impl/PublisherApiImplTest.java
@@ -0,0 +1,51 @@
+package org.onap.ccsdk.sli.adaptors.messagerouter.publisher.provider.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.net.HttpURLConnection;
+import java.net.URL;
+
+import org.junit.Test;
+
+public class PublisherApiImplTest {
+ @Test
+ public void verifyDefaultTimeouts() {
+ PublisherApiImpl pub = new PublisherApiImpl();
+ assertEquals(pub.DEFAULT_CONNECT_TIMEOUT, pub.connectTimeout);
+ assertEquals(pub.DEFAULT_READ_TIMEOUT, pub.readTimeout);
+ }
+
+ @Test
+ public void buildHttpURLConnection() throws Exception {
+ PublisherApiImpl pub = new PublisherApiImpl();
+ pub.init();
+
+ String myUserName = "Batman";
+ pub.setUsername(myUserName);
+ assertEquals(myUserName, pub.username);
+ String password = "P@$$";
+ pub.setPassword(password);
+
+ HttpURLConnection httpUrlConnection = pub.buildHttpURLConnection(new URL("http://localhost:7001"));
+ assertNotNull(httpUrlConnection.getReadTimeout());
+ assertNotNull(httpUrlConnection.getConnectTimeout());
+ assertEquals("application/json", httpUrlConnection.getRequestProperty("Content-Type"));
+ assertEquals("application/json", httpUrlConnection.getRequestProperty("Accept"));
+ }
+
+ @Test
+ public void testMultipleHosts() {
+ PublisherApiImpl pub = new PublisherApiImpl();
+ String myTopic = "worldNews";
+ String hostOne = "http://localhost:7001";
+ String hostTwo = "http://localhost:7002";
+ String hostThree = "http://localhost:7003";
+
+ pub.setHost(hostOne + "," + hostTwo + "," + hostThree);
+
+ assertEquals("http://localhost:7001/events/worldNews", pub.buildUrlString(0, myTopic));
+ assertEquals("http://localhost:7002/events/worldNews", pub.buildUrlString(1, myTopic));
+ assertEquals("http://localhost:7003/events/worldNews", pub.buildUrlString(2, myTopic));
+ }
+} \ No newline at end of file
diff --git a/adaptors/message-router/publisher/sample.client/pom.xml b/adaptors/message-router/publisher/sample.client/pom.xml
new file mode 100755
index 000000000..694af1f4a
--- /dev/null
+++ b/adaptors/message-router/publisher/sample.client/pom.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.sli.adaptors.messagerouter</groupId>
+ <artifactId>publisher.aggregate</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>sample.client</artifactId>
+ <packaging>bundle</packaging>
+
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>publisher.api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <configuration>
+ <instructions>
+ <Private-Package>${project.groupId}.publisher.client.impl</Private-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/adaptors/message-router/publisher/sample.client/src/main/java/org/onap/ccsdk/sli/adaptors/messagerouter/publisher/client/impl/ClientImpl.java b/adaptors/message-router/publisher/sample.client/src/main/java/org/onap/ccsdk/sli/adaptors/messagerouter/publisher/client/impl/ClientImpl.java
new file mode 100755
index 000000000..d1610305a
--- /dev/null
+++ b/adaptors/message-router/publisher/sample.client/src/main/java/org/onap/ccsdk/sli/adaptors/messagerouter/publisher/client/impl/ClientImpl.java
@@ -0,0 +1,58 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2019 AT&T Intellectual Property. All rights reserved.
+ *
+ * Modifications Copyright (C) 2019 IBM.
+ * ===========================================================================
+ * 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.
+ * ============LICENSE_END====================================================
+ *
+ */
+
+package org.onap.ccsdk.sli.adaptors.messagerouter.publisher.client.impl;
+
+import org.onap.ccsdk.sli.adaptors.messagerouter.publisher.api.PublisherApi;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ClientImpl {
+ private static final Logger logger = LoggerFactory.getLogger(ClientImpl.class);
+ private String topic;
+ private PublisherApi publisher;
+
+ public ClientImpl() {
+
+ }
+
+ public void setPublisher(PublisherApi publisherApi) {
+ this.publisher = publisherApi;
+ }
+
+ public void setTopic(String topic) {
+ this.topic = topic;
+ }
+
+
+
+ public void init() {
+ for (int i = 0; i < 5; i++) {
+ String body = "{\"hello\":\"world " + Math.random() + "\"}";
+ logger.error("Loop iteration " + i + " sending body " + body + " to the topic " + topic);
+ Boolean result = publisher.publish(topic, body);
+ logger.error("Loop iteration " + i + " returned the boolean value " + result);
+ }
+ }
+
+} \ No newline at end of file
diff --git a/adaptors/message-router/publisher/sample.client/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/adaptors/message-router/publisher/sample.client/src/main/resources/OSGI-INF/blueprint/blueprint.xml
new file mode 100755
index 000000000..c2e981da2
--- /dev/null
+++ b/adaptors/message-router/publisher/sample.client/src/main/resources/OSGI-INF/blueprint/blueprint.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+ xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.2.0">
+
+ <bean id="client"
+ class="org.onap.ccsdk.sli.adaptors.messagerouter.publisher.client.impl.ClientImpl"
+ init-method="init">
+ <property name="publisher" ref="publisher" />
+ <cm:managed-properties
+ persistent-id="org.onap.ccsdk.sli.adaptors.messagerouter.publisher.client"
+ update-strategy="container-managed" />
+ </bean>
+
+ <reference id="publisher" interface="org.onap.ccsdk.sli.adaptors.messagerouter.publisher.api.PublisherApi" />
+
+</blueprint> \ No newline at end of file
diff --git a/adaptors/message-router/publisher/sample.client/src/test/java/org/onap/ccsdk/sli/adaptors/messagerouter/publisher/client/impl/ClientImplTest.java b/adaptors/message-router/publisher/sample.client/src/test/java/org/onap/ccsdk/sli/adaptors/messagerouter/publisher/client/impl/ClientImplTest.java
new file mode 100644
index 000000000..82a1566c3
--- /dev/null
+++ b/adaptors/message-router/publisher/sample.client/src/test/java/org/onap/ccsdk/sli/adaptors/messagerouter/publisher/client/impl/ClientImplTest.java
@@ -0,0 +1,29 @@
+package org.onap.ccsdk.sli.adaptors.messagerouter.publisher.client.impl;
+
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+import org.onap.ccsdk.sli.adaptors.messagerouter.publisher.api.PublisherApi;
+
+public class ClientImplTest {
+
+ @Test
+ public void testSetTopic() {
+ ClientImpl impl = new ClientImpl();
+ String myTopic = "stock updates";
+ impl.setTopic(myTopic);
+
+ PublisherApi publisherImpl = new PublisherApi() {
+
+ @Override
+ public Boolean publish(String topic, String body) {
+ assertEquals(myTopic,topic);
+ return true;
+ }
+
+ };
+ impl.setPublisher(publisherImpl);
+ impl.init();
+ }
+
+}
diff --git a/adaptors/netbox-client/installer/pom.xml b/adaptors/netbox-client/installer/pom.xml
new file mode 100755
index 000000000..44fa16490
--- /dev/null
+++ b/adaptors/netbox-client/installer/pom.xml
@@ -0,0 +1,146 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2018 AT&T, Bell Canada
+
+ 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.
+ -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>odlparent-lite</artifactId>
+ <version>2.1.0</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.adaptors</groupId>
+ <artifactId>netbox-client-installer</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>pom</packaging>
+
+ <name>ccsdk-sli-adaptors :: netbox-client :: ${project.artifactId}</name>
+
+ <properties>
+ <application.name>ccsdk-netbox-client</application.name>
+ <features.boot>${application.name}</features.boot>
+ <features.repositories>mvn:org.onap.ccsdk.sli.adaptors/${features.boot}/${project.version}/xml/features</features.repositories>
+ <include.transitive.dependencies>false</include.transitive.dependencies>
+ </properties>
+
+ <dependencies>
+
+
+
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.adaptors</groupId>
+ <artifactId>netbox-client-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <version>2.6</version>
+ <executions>
+ <execution>
+ <id>maven-repo-zip</id>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ <phase>package</phase>
+ <configuration>
+ <attach>true</attach>
+ <finalName>stage/${application.name}-${project.version}</finalName>
+ <descriptors>
+ <descriptor>src/assembly/assemble_mvnrepo_zip.xml</descriptor>
+ </descriptors>
+ <appendAssemblyId>true</appendAssemblyId>
+ </configuration>
+ </execution>
+ <execution>
+ <id>installer-zip</id>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ <phase>package</phase>
+ <configuration>
+ <attach>true</attach>
+ <finalName>${application.name}-${project.version}-installer</finalName>
+ <descriptors>
+ <descriptor>src/assembly/assemble_installer_zip.xml</descriptor>
+ </descriptors>
+ <appendAssemblyId>false</appendAssemblyId>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>copy-dependencies</id>
+ <goals>
+ <goal>copy-dependencies</goal>
+ </goals>
+ <phase>prepare-package</phase>
+ <configuration>
+ <transitive>false</transitive>
+ <outputDirectory>${project.build.directory}/assembly/system</outputDirectory>
+ <overWriteReleases>false</overWriteReleases>
+ <overWriteSnapshots>true</overWriteSnapshots>
+ <overWriteIfNewer>true</overWriteIfNewer>
+ <useRepositoryLayout>true</useRepositoryLayout>
+ <addParentPoms>false</addParentPoms>
+ <copyPom>false</copyPom>
+ <includeGroupIds>org.onap.ccsdk.sli.adaptors</includeGroupIds>
+ <scope>provided</scope>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <artifactId>maven-resources-plugin</artifactId>
+ <version>2.6</version>
+ <executions>
+ <execution>
+ <id>copy-version</id>
+ <goals>
+ <goal>copy-resources</goal>
+ </goals><!-- here the phase you need -->
+ <phase>validate</phase>
+ <configuration>
+ <outputDirectory>${basedir}/target/stage</outputDirectory>
+ <resources>
+ <resource>
+ <directory>src/main/resources/scripts</directory>
+ <includes>
+ <include>install-feature.sh</include>
+ </includes>
+ <filtering>true</filtering>
+ </resource>
+ </resources>
+ </configuration>
+ </execution>
+
+ </executions>
+ </plugin>
+
+ </plugins>
+ </build>
+</project>
diff --git a/adaptors/netbox-client/installer/src/assembly/assemble_installer_zip.xml b/adaptors/netbox-client/installer/src/assembly/assemble_installer_zip.xml
new file mode 100644
index 000000000..ea3bef72e
--- /dev/null
+++ b/adaptors/netbox-client/installer/src/assembly/assemble_installer_zip.xml
@@ -0,0 +1,53 @@
+<!--
+ Copyright (C) 2018 AT&T, Bell Canada
+
+ 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.
+ -->
+
+<!-- Defines how we build the .zip file which is our distribution. -->
+
+<assembly
+ xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
+ <id>installer_zip</id>
+ <formats>
+ <format>zip</format>
+ </formats>
+
+ <!-- we want "system" and related files right at the root level
+ as this file is suppose to be unzip on top of a karaf
+ distro. -->
+ <includeBaseDirectory>false</includeBaseDirectory>
+
+ <fileSets>
+ <fileSet>
+ <directory>target/stage/</directory>
+ <outputDirectory>${application.name}</outputDirectory>
+ <fileMode>755</fileMode>
+ <includes>
+ <include>*.sh</include>
+ </includes>
+ </fileSet>
+ <fileSet>
+ <directory>target/stage/</directory>
+ <outputDirectory>${application.name}</outputDirectory>
+ <fileMode>644</fileMode>
+ <excludes>
+ <exclude>*.sh</exclude>
+ </excludes>
+ </fileSet>
+ </fileSets>
+
+
+</assembly>
diff --git a/adaptors/netbox-client/installer/src/assembly/assemble_mvnrepo_zip.xml b/adaptors/netbox-client/installer/src/assembly/assemble_mvnrepo_zip.xml
new file mode 100644
index 000000000..b905cfe3f
--- /dev/null
+++ b/adaptors/netbox-client/installer/src/assembly/assemble_mvnrepo_zip.xml
@@ -0,0 +1,43 @@
+<!--
+ Copyright (C) 2018 AT&T, Bell Canada
+
+ 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.
+ -->
+
+<!-- Defines how we build the .zip file which is our distribution. -->
+
+<assembly
+ xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
+ <id>repo</id>
+ <formats>
+ <format>zip</format>
+ </formats>
+
+ <!-- we want "system" and related files right at the root level
+ as this file is suppose to be unzip on top of a karaf
+ distro. -->
+ <includeBaseDirectory>false</includeBaseDirectory>
+
+ <fileSets>
+ <fileSet>
+ <directory>target/assembly/</directory>
+ <outputDirectory>.</outputDirectory>
+ <excludes>
+ </excludes>
+ </fileSet>
+ </fileSets>
+
+
+</assembly>
diff --git a/adaptors/netbox-client/installer/src/main/resources/scripts/install-feature.sh b/adaptors/netbox-client/installer/src/main/resources/scripts/install-feature.sh
new file mode 100644
index 000000000..b48869120
--- /dev/null
+++ b/adaptors/netbox-client/installer/src/main/resources/scripts/install-feature.sh
@@ -0,0 +1,34 @@
+#!/bin/bash
+
+#
+# Copyright (C) 2018 AT&T, Bell Canada
+#
+# 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.
+#
+
+ODL_HOME=${ODL_HOME:-/opt/opendaylight/current}
+ODL_KARAF_CLIENT=${ODL_KARAF_CLIENT:-${ODL_HOME}/bin/client}
+INSTALLERDIR=$(dirname $0)
+
+REPOZIP=${INSTALLERDIR}/${features.boot}-${project.version}.zip
+
+if [ -f ${REPOZIP} ]
+then
+ unzip -nd ${ODL_HOME} ${REPOZIP}
+else
+ echo "ERROR : repo zip ($REPOZIP) not found"
+ exit 1
+fi
+
+${ODL_KARAF_CLIENT} feature:repo-add ${features.repositories}
+${ODL_KARAF_CLIENT} feature:install ${features.boot}
diff --git a/adaptors/netbox-client/pom.xml b/adaptors/netbox-client/pom.xml
new file mode 100644
index 000000000..6c9dbe85c
--- /dev/null
+++ b/adaptors/netbox-client/pom.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2018 AT&T, Bell Canada
+
+ 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.
+ -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>odlparent-lite</artifactId>
+ <version>2.1.0</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.adaptors</groupId>
+ <artifactId>netbox-client</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>pom</packaging>
+
+ <name>ccsdk-sli-adaptors :: netbox-client</name>
+ <description>The SDNC Adaptors for netbox IPAM as an OSGi service</description>
+
+ <modules>
+ <module>provider</module>
+ <module>installer</module>
+ </modules>
+</project>
diff --git a/adaptors/netbox-client/provider/pom.xml b/adaptors/netbox-client/provider/pom.xml
new file mode 100644
index 000000000..2242a157b
--- /dev/null
+++ b/adaptors/netbox-client/provider/pom.xml
@@ -0,0 +1,137 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2018 AT&T, Bell Canada
+
+ 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.
+ -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>binding-parent</artifactId>
+ <version>2.1.0</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.adaptors</groupId>
+ <artifactId>netbox-client-provider</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>bundle</packaging>
+
+ <name>ccsdk-sli-adaptors :: netbox-client :: ${project.artifactId}</name>
+
+ <properties>
+ <ccsdk.sli.adaptors.version>${project.version}</ccsdk.sli.adaptors.version>
+ </properties>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sli-core-artifacts</artifactId>
+ <version>${ccsdk.sli.core.version}</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+ <dependencies>
+
+ <dependency>
+ <groupId>com.google.code.gson</groupId>
+ <artifactId>gson</artifactId>
+ <version>${gson.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.httpcomponents</groupId>
+ <artifactId>httpcore</artifactId>
+ <version>${apache.httpcomponents.core.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.httpcomponents</groupId>
+ <artifactId>httpclient</artifactId>
+ <version>${apache.httpcomponents.client.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sli-common</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sliPluginUtils-provider</artifactId>
+ <version>${ccsdk.sli.core.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.core</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ <!--Testing-->
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <!-- Requires mockito v2 -->
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ <version>2.2.11</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.github.tomakehurst</groupId>
+ <artifactId>wiremock</artifactId>
+ <version>2.23.2</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-server</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>ch.qos.logback</groupId>
+ <artifactId>logback-classic</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Export-Package>
+ org.onap.ccsdk.sli.adaptors.netbox.api,
+ org.onap.ccsdk.sli.adaptors.netbox.ipam,
+ org.onap.ccsdk.sli.adaptors.netbox.model
+ </Export-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/adaptors/netbox-client/provider/src/main/java/org/onap/ccsdk/sli/adaptors/netbox/api/IpamException.java b/adaptors/netbox-client/provider/src/main/java/org/onap/ccsdk/sli/adaptors/netbox/api/IpamException.java
new file mode 100644
index 000000000..869a57cef
--- /dev/null
+++ b/adaptors/netbox-client/provider/src/main/java/org/onap/ccsdk/sli/adaptors/netbox/api/IpamException.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2018 Bell Canada.
+ *
+ * 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.
+ */
+package org.onap.ccsdk.sli.adaptors.netbox.api;
+
+public class IpamException extends Exception {
+
+ public IpamException(final String message) {
+ super(message);
+ }
+
+ public IpamException(final String message, final Throwable cause) {
+ super(message, cause);
+ }
+}
diff --git a/adaptors/netbox-client/provider/src/main/java/org/onap/ccsdk/sli/adaptors/netbox/api/NetboxClient.java b/adaptors/netbox-client/provider/src/main/java/org/onap/ccsdk/sli/adaptors/netbox/api/NetboxClient.java
new file mode 100644
index 000000000..f770d1543
--- /dev/null
+++ b/adaptors/netbox-client/provider/src/main/java/org/onap/ccsdk/sli/adaptors/netbox/api/NetboxClient.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2018 Bell Canada.
+ *
+ * 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.
+ */
+package org.onap.ccsdk.sli.adaptors.netbox.api;
+
+import java.util.Map;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicJavaPlugin;
+import org.onap.ccsdk.sli.core.sli.SvcLogicResource.QueryStatus;
+
+/**
+ * This client is meant to interact both with the IPAM system, and the SDNC DB, in order to provide, at any time,
+ * an up to date status of the assigned resources.
+ */
+public interface NetboxClient extends SvcLogicJavaPlugin {
+
+ /**
+ * Assign next available IP in prefix and store it in the SDNC database, table IPAM_IP_ASSIGNEMENT.
+ *
+ * @param parameters HashMap<String,String> of parameters passed by the DG to this function
+ * <table border="1">
+ * <thead><th>parameter</th><th>Mandatory/Optional</th><th>description</th></thead>
+ * <tbody>
+ * <tr><td>service_instance_id</td><td>Mandatory</td><td>The service instance ID uniquely identifying the service.</td></tr>
+ * <tr><td>vf_module_id</td><td>Mandatory</td><td>The VF module ID uniquely identifying the VF.</td></tr>
+ * <tr><td>prefix_id</td><td>Mandatory</td><td>The prefix from which to get next available IP.</td></tr>
+ * </tbody>
+ * </table>
+ */
+ QueryStatus assignIpAddress(Map<String, String> parameters, SvcLogicContext ctx);
+
+ /**
+ * Release the IP and update the entry in the SDNC database, table IPAM_IP_ASSIGNEMENT.
+ *
+ * @param parameters HashMap<String,String> of parameters passed by the DG to this function
+ * <table border="1">
+ * <thead><th>parameter</th><th>Mandatory/Optional</th><th>description</th></thead>
+ * <tbody>
+ * <tr><td>service_instance_id</td><td>Mandatory</td><td>The service instance ID uniquely identifying the service.</td></tr>
+ * <tr><td>vf_module_id</td><td>Mandatory</td><td>The VF module ID uniquely identifying the VF.</td></tr>
+ * <tr><td>ip_address_id</td><td>Mandatory</td><td>The IP to release.</td></tr>
+ * </tbody>
+ * </table>
+ */
+ QueryStatus unassignIpAddress(Map<String, String> parameters, SvcLogicContext ctx);
+}
+
diff --git a/adaptors/netbox-client/provider/src/main/java/org/onap/ccsdk/sli/adaptors/netbox/impl/NetboxClientImpl.java b/adaptors/netbox-client/provider/src/main/java/org/onap/ccsdk/sli/adaptors/netbox/impl/NetboxClientImpl.java
new file mode 100644
index 000000000..bfb5ee530
--- /dev/null
+++ b/adaptors/netbox-client/provider/src/main/java/org/onap/ccsdk/sli/adaptors/netbox/impl/NetboxClientImpl.java
@@ -0,0 +1,267 @@
+/*
+ * Copyright (C) 2018 Bell Canada.
+ *
+ * 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.
+ */
+package org.onap.ccsdk.sli.adaptors.netbox.impl;
+
+import com.google.common.collect.Lists;
+import com.google.gson.JsonSyntaxException;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.Properties;
+
+import javax.sql.rowset.CachedRowSet;
+import org.apache.http.HttpResponse;
+import org.apache.http.util.EntityUtils;
+import org.onap.ccsdk.sli.adaptors.netbox.api.NetboxClient;
+import org.onap.ccsdk.sli.adaptors.netbox.model.IPAddress;
+import org.onap.ccsdk.sli.adaptors.netbox.model.IPStatus;
+import org.onap.ccsdk.sli.adaptors.netbox.property.NetboxProperties;
+import org.onap.ccsdk.sli.core.dblib.DBResourceManager;
+import org.onap.ccsdk.sli.core.dblib.DbLibService;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.core.sli.SvcLogicResource.QueryStatus;
+import org.onap.ccsdk.sli.core.slipluginutils.SliPluginUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class NetboxClientImpl implements NetboxClient {
+
+ private static final Logger LOG = LoggerFactory.getLogger(NetboxClientImpl.class);
+
+ // Netbox URI
+
+ private static final String NEXT_AVAILABLE_IP_IN_PREFIX_PATH = "/api/ipam/prefixes/%s/available-ips/";
+ private static final String IP_ADDRESS_PATH = "/api/ipam/ip-addresses/%s/";
+
+ // Netbox Payload
+
+ private static final String ASSIGN_IP_ADDRESS_PAYLOAD = "{\n"
+ + " \"custom_fields\": {\n"
+ + " \"external-key\": \"%s\",\n"
+ + " \"resource-name\": \"%s\"\n"
+ + " }\n"
+ + "}";
+
+ // Service Logic Context input variables and exception
+
+ private static final String SERVICE_INSTANCE_ID_PROP = "service_instance_id";
+ private static final String VF_MODULE_ID_PROP = "vf_module_id";
+ private static final String EXTERNAL_KEY_PROP = "external_key";
+ private static final String SQL_EXCEPTION_MESSAGE = "Caught SQL exception";
+
+ // SQL statement
+
+ private static final String ASSIGN_IP_SQL_STATEMENT =
+ "INSERT INTO IPAM_IP_ASSIGNEMENT (service_instance_id, vf_module_id, prefix_id, ip_address_id, ip_address, ip_status, ip_response_json, external_key, ip_address_type) \n"
+ + "VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)";
+ private static final String UNASSIGN_IP_SQL_STATEMENT =
+ "UPDATE IPAM_IP_ASSIGNEMENT SET ip_status = ? WHERE service_instance_id = ? AND external_key = ?";
+ private static final String GET_IP_ADDRESS_ID_SQL_STATEMENT =
+ "SELECT ip_address_id FROM IPAM_IP_ASSIGNEMENT WHERE service_instance_id = ? AND external_key = ?";
+
+ private final NetboxHttpClient client;
+ private final DbLibService dbLibService;
+
+ public NetboxClientImpl() {
+ this(null, null);
+ }
+
+ public NetboxClientImpl(final NetboxHttpClient client, final DbLibService dbLibService) {
+ if (client == null) {
+ this.client = new NetboxHttpClient(new NetboxProperties());
+ } else {
+ this.client = client;
+ }
+
+ if (dbLibService == null) {
+ Properties dblibProps = System.getProperties();
+
+ String cfgDir = dblibProps.getProperty("sdnc.config.dir", System.getenv("SDNC_CONFIG_DIR"));
+
+ if ((cfgDir == null) || (cfgDir.length() == 0)) {
+ cfgDir = "/opt/sdnc/data/properties";
+ }
+
+ File dblibPropFile = new File(cfgDir + "/dblib.properties");
+ if (dblibPropFile.exists()) {
+ try {
+ LOG.debug("Loading dblib properties from {}", dblibPropFile.getAbsolutePath());
+ dblibProps = new Properties();
+ dblibProps.load(new FileInputStream(dblibPropFile));
+ } catch (Exception e) {
+ LOG.warn("Could not load properties file {}", dblibPropFile.getAbsolutePath(), e);
+
+ dblibProps = System.getProperties();
+ }
+ }
+
+ DbLibService dbSvc = null;
+ try {
+ dbSvc = new DBResourceManager(dblibProps);
+ } catch (Exception e) {
+ LOG.error("Caught exception trying to create dblib service", e);
+ }
+
+ try {
+ dbSvc = new DBResourceManager(dblibProps);
+ } catch (Exception e) {
+ LOG.error("Caught exception trying to create dblib service", e);
+ }
+ this.dbLibService = dbSvc;
+
+ } else {
+ this.dbLibService = dbLibService;
+ }
+ }
+
+ @Override
+ public QueryStatus assignIpAddress(final Map<String, String> parameters, final SvcLogicContext ctx) {
+
+ try {
+ SliPluginUtils
+ .checkParameters(parameters,
+ new String[]{SERVICE_INSTANCE_ID_PROP, VF_MODULE_ID_PROP, "prefix_id", "resource_name",
+ EXTERNAL_KEY_PROP}, LOG);
+ } catch (SvcLogicException e) {
+ return QueryStatus.FAILURE;
+ }
+
+ final String serviceInstanceId = parameters.get(SERVICE_INSTANCE_ID_PROP);
+ final String vfModuleId = parameters.get(VF_MODULE_ID_PROP);
+ final String prefixId = parameters.get("prefix_id");
+ final String resourceName = parameters.get("resource_name");
+ final String externalKey = parameters.get(EXTERNAL_KEY_PROP);
+
+ HttpResponse httpResp;
+ try {
+ httpResp = client
+ .post(String.format(NEXT_AVAILABLE_IP_IN_PREFIX_PATH, prefixId),
+ String.format(ASSIGN_IP_ADDRESS_PAYLOAD, externalKey, resourceName));
+ } catch (IOException e) {
+ LOG.error("Fail to assign IP for Prefix(id={}). {}", prefixId, e.getMessage(), e.getCause());
+ return QueryStatus.FAILURE;
+ }
+
+ String ipamRespJson;
+ try {
+ ipamRespJson = EntityUtils.toString(httpResp.getEntity(), "UTF-8");
+ } catch (IOException e) {
+ LOG.error("Fail to parse IPAM response for assign in Prefix(id={}). Response={}", prefixId,
+ httpResp.getEntity(), e);
+ return QueryStatus.FAILURE;
+ }
+
+ if (httpResp.getStatusLine().getStatusCode() != 201) {
+ LOG.error("Fail to assign IP for Prefix(id={}). HTTP code 201!={}. Response={}", prefixId,
+ httpResp.getStatusLine().getStatusCode(), ipamRespJson);
+ return QueryStatus.FAILURE;
+ }
+
+ IPAddress ipAddress;
+ try {
+ ipAddress = IPAddress.fromJson(ipamRespJson);
+ } catch (JsonSyntaxException e) {
+ LOG.error("Fail to parse IPAM JSON reponse to IPAddress POJO. IPAM JSON Response={}", ipamRespJson, e);
+ return QueryStatus.FAILURE;
+ }
+
+ ArrayList<String> args = Lists.newArrayList(
+ serviceInstanceId,
+ vfModuleId,
+ String.valueOf(prefixId),
+ String.valueOf(ipAddress.getId()),
+ ipAddress.getAddress(),
+ IPStatus.ASSIGNED.name(),
+ ipamRespJson,
+ externalKey,
+ resourceName);
+
+ try {
+ dbLibService.writeData(ASSIGN_IP_SQL_STATEMENT, args, null);
+ } catch (SQLException e) {
+ LOG.error(SQL_EXCEPTION_MESSAGE, e);
+ return QueryStatus.FAILURE;
+ }
+
+ ctx.setAttribute("self_serve_netbox_ip_assignement.ip-address", ipAddress.getAddress());
+
+ return QueryStatus.SUCCESS;
+ }
+
+ @Override
+ public QueryStatus unassignIpAddress(final Map<String, String> parameters, final SvcLogicContext ctx) {
+ try {
+ SliPluginUtils
+ .checkParameters(parameters, new String[]{SERVICE_INSTANCE_ID_PROP, EXTERNAL_KEY_PROP},
+ LOG);
+ } catch (SvcLogicException e) {
+ return QueryStatus.FAILURE;
+ }
+
+ final String serviceInstanceId = parameters.get(SERVICE_INSTANCE_ID_PROP);
+ final String externalKey = parameters.get(EXTERNAL_KEY_PROP);
+
+ String ipAddressId;
+ ArrayList<String> args = Lists.newArrayList(
+ serviceInstanceId,
+ externalKey);
+ try (CachedRowSet row = dbLibService.getData(GET_IP_ADDRESS_ID_SQL_STATEMENT, args, null)) {
+ if (row.next()) {
+ ipAddressId = row.getString("ip_address_id");
+ } else {
+ throw new SQLException("Data not found.");
+ }
+ } catch (SQLException e) {
+ LOG.error(SQL_EXCEPTION_MESSAGE, e);
+ return QueryStatus.FAILURE;
+ }
+
+ HttpResponse httpResp;
+ try {
+ httpResp = client.delete(String.format(IP_ADDRESS_PATH, ipAddressId));
+ } catch (IOException e) {
+ LOG.error("Fail to unassign IP for IPAddress(id= " + ipAddressId + "). " + e.getMessage(),
+ e.getCause());
+ return QueryStatus.FAILURE;
+ }
+
+ if (httpResp.getStatusLine().getStatusCode() - 200 >= 100) {
+ LOG.error("Fail to unassign IP for IPAddress(id={}). HTTP code={}.", ipAddressId,
+ httpResp.getStatusLine().getStatusCode());
+ return QueryStatus.FAILURE;
+ }
+
+ args.clear();
+ args = Lists.newArrayList(
+ IPStatus.DELETED.name(),
+ serviceInstanceId,
+ externalKey);
+
+ try {
+ dbLibService.writeData(UNASSIGN_IP_SQL_STATEMENT, args, null);
+ } catch (SQLException e) {
+ LOG.error(SQL_EXCEPTION_MESSAGE, e);
+ return QueryStatus.FAILURE;
+ }
+
+ return QueryStatus.SUCCESS;
+ }
+}
diff --git a/adaptors/netbox-client/provider/src/main/java/org/onap/ccsdk/sli/adaptors/netbox/impl/NetboxHttpClient.java b/adaptors/netbox-client/provider/src/main/java/org/onap/ccsdk/sli/adaptors/netbox/impl/NetboxHttpClient.java
new file mode 100644
index 000000000..505c5a77e
--- /dev/null
+++ b/adaptors/netbox-client/provider/src/main/java/org/onap/ccsdk/sli/adaptors/netbox/impl/NetboxHttpClient.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2018 Bell Canada.
+ *
+ * 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.
+ */
+package org.onap.ccsdk.sli.adaptors.netbox.impl;
+
+import static org.apache.http.HttpHeaders.ACCEPT;
+import static org.apache.http.HttpHeaders.AUTHORIZATION;
+import static org.apache.http.HttpHeaders.CONTENT_TYPE;
+
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.security.KeyManagementException;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import javax.net.ssl.SSLContext;
+import org.apache.http.HttpResponse;
+import org.apache.http.client.methods.HttpDelete;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.client.methods.HttpRequestBase;
+import org.apache.http.conn.ssl.NoopHostnameVerifier;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClientBuilder;
+import org.apache.http.ssl.SSLContexts;
+import org.apache.http.ssl.TrustStrategy;
+import org.onap.ccsdk.sli.adaptors.netbox.property.NetboxProperties;
+
+public class NetboxHttpClient implements AutoCloseable {
+
+ private static final String APPLICATION_JSON = "application/json";
+
+ private final CloseableHttpClient client;
+ private final String url;
+ private final String token;
+
+ // Used by the blueprint container
+ public NetboxHttpClient(NetboxProperties properties) {
+ this(properties.getHost(), properties.getApiKey());
+ }
+
+ NetboxHttpClient(final String url, final String token) {
+ this.url = url;
+ this.token = token;
+
+ final TrustStrategy acceptingTrustStrategy = (certificate, authType) -> true;
+ final SSLContext sslContext;
+ try {
+ sslContext = SSLContexts.custom()
+ .loadTrustMaterial(null, acceptingTrustStrategy).build();
+ } catch (final NoSuchAlgorithmException | KeyManagementException | KeyStoreException e) {
+ throw new IllegalStateException("Can't create http client", e);
+ }
+ client = HttpClientBuilder.create()
+ .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
+ .setSSLContext(sslContext)
+ .build();
+ }
+
+ @Override
+ public void close() throws IOException {
+ client.close();
+ }
+
+ HttpResponse post(final String uri, final String requestBody) throws IOException {
+ final HttpPost request = new HttpPost(url + uri);
+ setHeaders(request);
+ request.setEntity(new StringEntity(requestBody, Charset.forName("UTF-8")));
+ return client.execute(request);
+ }
+
+ HttpResponse delete(final String uri) throws IOException {
+ final HttpDelete request = new HttpDelete(url + uri);
+ setHeaders(request);
+ return client.execute(request);
+ }
+
+ private void setHeaders(final HttpRequestBase request) {
+ request.addHeader(ACCEPT, APPLICATION_JSON);
+ request.addHeader(CONTENT_TYPE, APPLICATION_JSON);
+ request.addHeader(AUTHORIZATION, "Token " + token);
+ }
+} \ No newline at end of file
diff --git a/adaptors/netbox-client/provider/src/main/java/org/onap/ccsdk/sli/adaptors/netbox/model/IPAddress.java b/adaptors/netbox-client/provider/src/main/java/org/onap/ccsdk/sli/adaptors/netbox/model/IPAddress.java
new file mode 100644
index 000000000..4c2880bc4
--- /dev/null
+++ b/adaptors/netbox-client/provider/src/main/java/org/onap/ccsdk/sli/adaptors/netbox/model/IPAddress.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2018 Bell Canada.
+ *
+ * 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.
+ */
+package org.onap.ccsdk.sli.adaptors.netbox.model;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import java.util.Objects;
+
+public class IPAddress extends Identifiable {
+
+ private static final Gson gson = new GsonBuilder().create();
+
+ private String address;
+
+ public void setAddress(String address) {
+ this.address = address;
+ }
+
+ public String getAddress() {
+ return address;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ IPAddress ipAddress = (IPAddress) o;
+ return Objects.equals(address, ipAddress.address);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(address);
+ }
+
+ public static IPAddress fromJson(final String json) {
+ return gson.fromJson(json, IPAddress.class);
+ }
+}
diff --git a/adaptors/netbox-client/provider/src/main/java/org/onap/ccsdk/sli/adaptors/netbox/model/IPStatus.java b/adaptors/netbox-client/provider/src/main/java/org/onap/ccsdk/sli/adaptors/netbox/model/IPStatus.java
new file mode 100644
index 000000000..f3a74387a
--- /dev/null
+++ b/adaptors/netbox-client/provider/src/main/java/org/onap/ccsdk/sli/adaptors/netbox/model/IPStatus.java
@@ -0,0 +1,5 @@
+package org.onap.ccsdk.sli.adaptors.netbox.model;
+
+public enum IPStatus {
+ ASSIGNED, DELETED
+}
diff --git a/adaptors/netbox-client/provider/src/main/java/org/onap/ccsdk/sli/adaptors/netbox/model/Identifiable.java b/adaptors/netbox-client/provider/src/main/java/org/onap/ccsdk/sli/adaptors/netbox/model/Identifiable.java
new file mode 100644
index 000000000..501088d78
--- /dev/null
+++ b/adaptors/netbox-client/provider/src/main/java/org/onap/ccsdk/sli/adaptors/netbox/model/Identifiable.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2018 Bell Canada.
+ *
+ * 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.
+ */
+package org.onap.ccsdk.sli.adaptors.netbox.model;
+
+public abstract class Identifiable {
+
+ private Integer id;
+
+ public Integer getId() {
+ return id;
+ }
+
+ public void setId(final Integer id) {
+ this.id = id;
+ }
+}
diff --git a/adaptors/netbox-client/provider/src/main/java/org/onap/ccsdk/sli/adaptors/netbox/model/Prefix.java b/adaptors/netbox-client/provider/src/main/java/org/onap/ccsdk/sli/adaptors/netbox/model/Prefix.java
new file mode 100644
index 000000000..b20be91db
--- /dev/null
+++ b/adaptors/netbox-client/provider/src/main/java/org/onap/ccsdk/sli/adaptors/netbox/model/Prefix.java
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2018 Bell Canada.
+ *
+ * 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.
+ */
+package org.onap.ccsdk.sli.adaptors.netbox.model;
+
+public class Prefix extends Identifiable {
+
+}
diff --git a/adaptors/netbox-client/provider/src/main/java/org/onap/ccsdk/sli/adaptors/netbox/property/NetboxProperties.java b/adaptors/netbox-client/provider/src/main/java/org/onap/ccsdk/sli/adaptors/netbox/property/NetboxProperties.java
new file mode 100644
index 000000000..9b4751e64
--- /dev/null
+++ b/adaptors/netbox-client/provider/src/main/java/org/onap/ccsdk/sli/adaptors/netbox/property/NetboxProperties.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2018 Bell Canada.
+ *
+ * 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.
+ */
+package org.onap.ccsdk.sli.adaptors.netbox.property;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.Properties;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.FrameworkUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class NetboxProperties {
+
+ private static final Logger LOG = LoggerFactory.getLogger(NetboxProperties.class);
+
+ private static final String NETBOX_PROPERTY_FILE_NAME = "netbox.properties";
+ private static final String DEFAULT_PROPERTIES_DIR = "/opt/onap/ccsdk/data/properties";
+ private static final String PROPERTIES_DIR_KEY = "SDNC_CONFIG_DIR";
+
+ private static final String NETBOX_URL_PROP = "org.onap.ccsdk.sli.adaptors.netbox.url";
+ private static final String NETBOX_API_KEY_PROP = "org.onap.ccsdk.sli.adaptors.netbox.apikey";
+
+ private Properties properties;
+
+ public NetboxProperties() {
+ loadProps();
+ }
+
+ public String getHost() {
+ return properties.getProperty(NETBOX_URL_PROP);
+ }
+
+ public String getApiKey() {
+ return properties.getProperty(NETBOX_API_KEY_PROP);
+ }
+
+ private void loadProps() {
+ properties = new Properties();
+ // Try to load config from dir
+ final String ccsdkConfigDir =
+ System.getProperty(PROPERTIES_DIR_KEY, DEFAULT_PROPERTIES_DIR) + "/" + NETBOX_PROPERTY_FILE_NAME;
+ try (FileInputStream in = new FileInputStream(ccsdkConfigDir)) {
+ properties.load(in);
+ LOG.info("Loaded {} properties from file {}", properties.size(), ccsdkConfigDir);
+ } catch (Exception e) {
+ try {
+ // Try to load config from jar via OSGi
+ final Bundle bundle = FrameworkUtil.getBundle(NetboxProperties.class);
+ final BundleContext ctx = bundle.getBundleContext();
+ final URL url = ctx.getBundle().getResource(NETBOX_PROPERTY_FILE_NAME);
+ InputStream inputStream = url.openStream();
+ properties.load(inputStream);
+ LOG.info("Loaded {} properties from file {}", properties.size(), NETBOX_PROPERTY_FILE_NAME);
+ } catch (NoClassDefFoundError e1) {
+ // Try to load config from jar via class loader
+ try (InputStream inputStream = NetboxProperties.class.getResourceAsStream("/"+NETBOX_PROPERTY_FILE_NAME)) {
+ properties.load(inputStream);
+ } catch (Exception e2) {
+ LOG.error("Failed to load properties for file: {} " + NETBOX_PROPERTY_FILE_NAME, e1);
+ }
+ ;
+ LOG.info("Loaded {} properties from file {}", properties.size(), NETBOX_PROPERTY_FILE_NAME);
+
+ } catch (IOException e1) {
+ LOG.error("Failed to load properties for file: {} " + NETBOX_PROPERTY_FILE_NAME, e1);
+ }
+ }
+ }
+}
diff --git a/adaptors/netbox-client/provider/src/main/resources/OSGI-INF/blueprint/netbox-client.xml b/adaptors/netbox-client/provider/src/main/resources/OSGI-INF/blueprint/netbox-client.xml
new file mode 100644
index 000000000..b667dcba5
--- /dev/null
+++ b/adaptors/netbox-client/provider/src/main/resources/OSGI-INF/blueprint/netbox-client.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2018 AT&T, Bell Canada
+
+ 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.
+ -->
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0"
+ odl:use-default-for-reference-types="true">
+
+ <reference id="dbLibService"
+ interface="org.onap.ccsdk.sli.core.dblib.DbLibService"/>
+
+ <bean id="netboxProperty" class="org.onap.ccsdk.sli.adaptors.netbox.property.NetboxProperties"/>
+ <bean id="httpClient" class="org.onap.ccsdk.sli.adaptors.netbox.impl.NetboxHttpClient" destroy-method="close">
+ <argument ref="netboxProperty"/>
+ </bean>
+
+ <bean id="netboxClient" class="org.onap.ccsdk.sli.adaptors.netbox.impl.NetboxClientImpl">
+ <argument ref="httpClient"/>
+ <argument ref="dbLibService"/>
+ </bean>
+
+ <service ref="netboxClient"
+ interface="org.onap.ccsdk.sli.adaptors.netbox.api.NetboxClient"
+ odl:type="default"/>
+
+</blueprint>
diff --git a/adaptors/netbox-client/provider/src/main/resources/netbox.properties b/adaptors/netbox-client/provider/src/main/resources/netbox.properties
new file mode 100644
index 000000000..4346d1774
--- /dev/null
+++ b/adaptors/netbox-client/provider/src/main/resources/netbox.properties
@@ -0,0 +1,19 @@
+#
+# Copyright (C) 2019 Bell Canada.
+#
+# 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.
+#
+
+# Configuration file for Netbox client
+org.onap.ccsdk.sli.adaptors.netbox.url=http://netbox-nginx:8080
+org.onap.ccsdk.sli.adaptors.netbox.apikey=onceuponatimeiplayedwithnetbox20180814 \ No newline at end of file
diff --git a/adaptors/netbox-client/provider/src/main/resources/org/opendaylight/blueprint/netbox-client.xml b/adaptors/netbox-client/provider/src/main/resources/org/opendaylight/blueprint/netbox-client.xml
new file mode 100644
index 000000000..b667dcba5
--- /dev/null
+++ b/adaptors/netbox-client/provider/src/main/resources/org/opendaylight/blueprint/netbox-client.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright (C) 2018 AT&T, Bell Canada
+
+ 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.
+ -->
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0"
+ odl:use-default-for-reference-types="true">
+
+ <reference id="dbLibService"
+ interface="org.onap.ccsdk.sli.core.dblib.DbLibService"/>
+
+ <bean id="netboxProperty" class="org.onap.ccsdk.sli.adaptors.netbox.property.NetboxProperties"/>
+ <bean id="httpClient" class="org.onap.ccsdk.sli.adaptors.netbox.impl.NetboxHttpClient" destroy-method="close">
+ <argument ref="netboxProperty"/>
+ </bean>
+
+ <bean id="netboxClient" class="org.onap.ccsdk.sli.adaptors.netbox.impl.NetboxClientImpl">
+ <argument ref="httpClient"/>
+ <argument ref="dbLibService"/>
+ </bean>
+
+ <service ref="netboxClient"
+ interface="org.onap.ccsdk.sli.adaptors.netbox.api.NetboxClient"
+ odl:type="default"/>
+
+</blueprint>
diff --git a/adaptors/netbox-client/provider/src/test/java/org/onap/ccsdk/sli/adaptors/netbox/impl/NetboxClientImplTest.java b/adaptors/netbox-client/provider/src/test/java/org/onap/ccsdk/sli/adaptors/netbox/impl/NetboxClientImplTest.java
new file mode 100644
index 000000000..624a1906e
--- /dev/null
+++ b/adaptors/netbox-client/provider/src/test/java/org/onap/ccsdk/sli/adaptors/netbox/impl/NetboxClientImplTest.java
@@ -0,0 +1,313 @@
+/*
+ * Copyright (C) 2018 Bell Canada.
+ *
+ * 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.
+ */
+package org.onap.ccsdk.sli.adaptors.netbox.impl;
+
+import static com.github.tomakehurst.wiremock.client.WireMock.created;
+import static com.github.tomakehurst.wiremock.client.WireMock.delete;
+import static com.github.tomakehurst.wiremock.client.WireMock.deleteRequestedFor;
+import static com.github.tomakehurst.wiremock.client.WireMock.equalTo;
+import static com.github.tomakehurst.wiremock.client.WireMock.givenThat;
+import static com.github.tomakehurst.wiremock.client.WireMock.post;
+import static com.github.tomakehurst.wiremock.client.WireMock.postRequestedFor;
+import static com.github.tomakehurst.wiremock.client.WireMock.serverError;
+import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
+import static com.github.tomakehurst.wiremock.client.WireMock.verify;
+import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig;
+import static org.apache.http.HttpHeaders.ACCEPT;
+import static org.apache.http.HttpHeaders.AUTHORIZATION;
+import static org.apache.http.HttpHeaders.CONTENT_TYPE;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+
+import ch.qos.logback.classic.spi.ILoggingEvent;
+import ch.qos.logback.core.Appender;
+import com.github.tomakehurst.wiremock.junit.WireMockRule;
+import com.google.common.base.Charsets;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.io.Resources;
+import java.io.IOException;
+import java.net.URL;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import javax.sql.rowset.CachedRowSet;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.onap.ccsdk.sli.core.dblib.DbLibService;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicResource.QueryStatus;
+import org.slf4j.LoggerFactory;
+
+@RunWith(MockitoJUnitRunner.class)
+public class NetboxClientImplTest {
+
+ private static final String APPLICATION_JSON = "application/json";
+
+ @Rule
+ public WireMockRule wm = new WireMockRule(wireMockConfig().dynamicPort());
+ @Mock
+ private DbLibService dbLib;
+ @Mock
+ private SvcLogicContext svcLogicContext;
+ @Mock
+ private Appender<ILoggingEvent> appender;
+ @Captor
+ private ArgumentCaptor<ILoggingEvent> captor;
+
+
+ private String token = "token";
+ private String serviceInstanceId = UUID.randomUUID().toString();
+ private String vfModuleId = UUID.randomUUID().toString();
+
+ private Map<String, String> params = ImmutableMap
+ .of("service_instance_id", serviceInstanceId,
+ "vf_module_id", vfModuleId,
+ "prefix_id", "3",
+ "external_key", "3",
+ "resource_name", "3"
+ );
+
+ private NetboxHttpClient httpClient;
+ private NetboxClientImpl netboxClient;
+
+ @Mock
+ private NetboxHttpClient httpClientMock;
+ @Mock
+ private NetboxClientImpl netboxClientMock;
+
+
+ @Before
+ public void setup() {
+ ch.qos.logback.classic.Logger logger = (ch.qos.logback.classic.Logger) LoggerFactory
+ .getLogger(NetboxClientImpl.class);
+ logger.addAppender(appender);
+
+ String baseUrl = "http://localhost:" + wm.port();
+
+ httpClient = new NetboxHttpClient(baseUrl, token);
+
+ netboxClient = new NetboxClientImpl(httpClient, dbLib);
+
+ netboxClientMock = new NetboxClientImpl(httpClientMock, dbLib);
+
+ wm.addMockServiceRequestListener(
+ (request, response) -> {
+ System.out.println("Request URL :" + request.getAbsoluteUrl());
+ System.out.println("Request body :" + request.getBodyAsString());
+ System.out.println("Response status :" + response.getStatus());
+ System.out.println("Response body :" + response.getBodyAsString());
+ });
+ }
+
+ @After
+ public void tearDown() throws IOException {
+ httpClient.close();
+ }
+
+ @Test
+ public void unassignIpAddressTestNoParams() {
+ QueryStatus status = netboxClient.unassignIpAddress(ImmutableMap.of(), svcLogicContext);
+ Assert.assertEquals(QueryStatus.FAILURE, status);
+ verifyLogEntry(
+ "This method requires the parameters [service_instance_id,external_key], but no parameters were passed in.");
+ }
+
+ @Test
+ public void unassignIpAddressFailedRequest() throws IOException, SQLException {
+ doThrow(new IOException("Failed request")).when(httpClientMock).delete(anyString());
+
+ CachedRowSet crs = mock(CachedRowSet.class);
+ doReturn("3").when(crs).getString(eq("ip_address_id"));
+ doReturn(true).when(crs).next();
+ doReturn(crs).when(dbLib).getData(anyString(), any(ArrayList.class), eq(null));
+
+ QueryStatus status = netboxClientMock
+ .unassignIpAddress(params, svcLogicContext);
+
+ Assert.assertEquals(QueryStatus.FAILURE, status);
+ verifyLogEntry("Fail to unassign IP for IPAddress(id= 3). Failed request");
+ }
+
+ @Test
+ public void unassignIpAddressServerError() throws SQLException {
+
+ String expectedUrl = "/api/ipam/ip-addresses/3/";
+ givenThat(delete(urlEqualTo(expectedUrl)).willReturn(serverError()));
+
+ CachedRowSet crs = mock(CachedRowSet.class);
+ doReturn("3").when(crs).getString(eq("ip_address_id"));
+ doReturn(true).when(crs).next();
+ doReturn(crs).when(dbLib).getData(anyString(), any(ArrayList.class), eq(null));
+
+ QueryStatus status = netboxClient.unassignIpAddress(params, svcLogicContext);
+
+ Assert.assertEquals(QueryStatus.FAILURE, status);
+ verifyLogEntry("Fail to unassign IP for IPAddress(id=3). HTTP code=500.");
+ }
+
+ @Test
+ public void unassignIpAddressFailSQL() throws IOException, SQLException {
+
+ String response = "{}";
+
+ String expectedUrl = "/api/ipam/ip-addresses/3/";
+ givenThat(delete(urlEqualTo(expectedUrl)).willReturn(created().withBody(response)));
+
+ CachedRowSet crs = mock(CachedRowSet.class);
+ doReturn(true).when(crs).next();
+ doReturn("3").when(crs).getString(eq("ip_address_id"));
+ doReturn(crs).when(dbLib).getData(anyString(), any(ArrayList.class), eq(null));
+
+ doThrow(new SQLException("Failed")).when(dbLib).writeData(anyString(), any(ArrayList.class), eq(null));
+
+ QueryStatus status = netboxClient.unassignIpAddress(params, svcLogicContext);
+
+ Assert.assertEquals(QueryStatus.FAILURE, status);
+ verifyLogEntry("Caught SQL exception");
+ }
+
+ @Test
+ public void unassignIpAddressSuccess() throws IOException, SQLException {
+ String response = "{}";
+
+ String expectedUrl = "/api/ipam/ip-addresses/3/";
+ givenThat(delete(urlEqualTo(expectedUrl)).willReturn(created().withBody(response)));
+
+ CachedRowSet crs = mock(CachedRowSet.class);
+ doReturn("3").when(crs).getString(eq("ip_address_id"));
+ doReturn(true).when(crs).next();
+ doReturn(crs).when(dbLib).getData(anyString(), any(ArrayList.class), eq(null));
+
+ QueryStatus status = netboxClient.unassignIpAddress(params, svcLogicContext);
+
+ verify(deleteRequestedFor(urlEqualTo(expectedUrl))
+ .withHeader(ACCEPT, equalTo(APPLICATION_JSON))
+ .withHeader(CONTENT_TYPE, equalTo(APPLICATION_JSON))
+ .withHeader(AUTHORIZATION, equalTo("Token " + token)));
+
+ Mockito.verify(dbLib).writeData(anyString(), any(ArrayList.class), eq(null));
+ Assert.assertEquals(QueryStatus.SUCCESS, status);
+ }
+
+
+ @Test
+ public void nextAvailableIpInPrefixTestNoId() {
+ QueryStatus status = netboxClient.assignIpAddress(ImmutableMap.of(), svcLogicContext);
+ Assert.assertEquals(QueryStatus.FAILURE, status);
+ verifyLogEntry(
+ "This method requires the parameters [service_instance_id,vf_module_id,prefix_id,resource_name,external_key], but no parameters were passed in.");
+ }
+
+ @Test
+ public void nextAvailableIpInPrefixFailedRequest() throws IOException {
+ doThrow(new IOException("Failed request")).when(httpClientMock).post(anyString(), anyString());
+ QueryStatus status = netboxClientMock.assignIpAddress(params, svcLogicContext);
+
+ Assert.assertEquals(QueryStatus.FAILURE, status);
+ verifyLogEntry("Fail to assign IP for Prefix(id=3). Failed request");
+ }
+
+ @Test
+ public void nextAvailableIpInPrefixBadRespPayload() throws IOException {
+ URL url = Resources.getResource("badResponse.json");
+ String response = Resources.toString(url, Charsets.UTF_8);
+
+ String expectedUrl = "/api/ipam/prefixes/3/available-ips/";
+ givenThat(post(urlEqualTo(expectedUrl)).willReturn(created().withBody(response)));
+
+ QueryStatus status = netboxClient.assignIpAddress(params, svcLogicContext);
+
+ Assert.assertEquals(QueryStatus.FAILURE, status);
+ verifyLogEntry("Fail to parse IPAM JSON reponse to IPAddress POJO. IPAM JSON Response={\n"
+ + " \"id\": 8\n"
+ + " \"address\": \"192.168.20.7/32\"\n"
+ + "}");
+ }
+
+ @Test
+ public void nextAvailableIpInPrefixFailSQL() throws IOException, SQLException {
+ URL url = Resources.getResource("nextAvailableIpResponse.json");
+ String response = Resources.toString(url, Charsets.UTF_8);
+
+ String expectedUrl = "/api/ipam/prefixes/3/available-ips/";
+ givenThat(post(urlEqualTo(expectedUrl)).willReturn(created().withBody(response)));
+
+ doThrow(new SQLException("Failed")).when(dbLib).writeData(anyString(), any(ArrayList.class), eq(null));
+
+ QueryStatus status = netboxClient.assignIpAddress(params, svcLogicContext);
+
+ Assert.assertEquals(QueryStatus.FAILURE, status);
+ verifyLogEntry("Caught SQL exception");
+ }
+
+ @Test
+ public void nextAvailableIpInPrefixError500() throws IOException {
+ URL url = Resources.getResource("nextAvailableIpResponse.json");
+ String response = Resources.toString(url, Charsets.UTF_8);
+
+ String expectedUrl = "/api/ipam/prefixes/3/available-ips/";
+ givenThat(post(urlEqualTo(expectedUrl)).willReturn(serverError().withBody(response)));
+
+ QueryStatus status = netboxClient.assignIpAddress(params, svcLogicContext);
+
+ Assert.assertEquals(QueryStatus.FAILURE, status);
+ verifyLogEntry("Fail to assign IP for Prefix(id=3). HTTP code 201!=500.");
+ }
+
+ @Test
+ public void nextAvailableIpInPrefixSuccess() throws IOException, SQLException {
+ URL url = Resources.getResource("nextAvailableIpResponse.json");
+ String response = Resources.toString(url, Charsets.UTF_8);
+
+ String expectedUrl = "/api/ipam/prefixes/3/available-ips/";
+ givenThat(post(urlEqualTo(expectedUrl)).willReturn(created().withBody(response)));
+
+ QueryStatus status = netboxClient.assignIpAddress(params, svcLogicContext);
+
+ verify(postRequestedFor(urlEqualTo(expectedUrl))
+ .withHeader(ACCEPT, equalTo(APPLICATION_JSON))
+ .withHeader(CONTENT_TYPE, equalTo(APPLICATION_JSON))
+ .withHeader(AUTHORIZATION, equalTo("Token " + token)));
+
+ Mockito.verify(dbLib).writeData(anyString(), any(ArrayList.class), eq(null));
+ Assert.assertEquals(QueryStatus.SUCCESS, status);
+ }
+
+ private void verifyLogEntry(String message) {
+ Mockito.verify(appender, times(1)).doAppend(captor.capture());
+ List<ILoggingEvent> allValues = captor.getAllValues();
+ for (ILoggingEvent loggingEvent : allValues) {
+ Assert.assertTrue(loggingEvent.getFormattedMessage().contains(message));
+ }
+ }
+
+} \ No newline at end of file
diff --git a/adaptors/netbox-client/provider/src/test/java/org/onap/ccsdk/sli/adaptors/netbox/impl/NetboxHttpClientTest.java b/adaptors/netbox-client/provider/src/test/java/org/onap/ccsdk/sli/adaptors/netbox/impl/NetboxHttpClientTest.java
new file mode 100644
index 000000000..8634742ae
--- /dev/null
+++ b/adaptors/netbox-client/provider/src/test/java/org/onap/ccsdk/sli/adaptors/netbox/impl/NetboxHttpClientTest.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2018 Bell Canada.
+ *
+ * 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.
+ */
+package org.onap.ccsdk.sli.adaptors.netbox.impl;
+
+import static com.github.tomakehurst.wiremock.client.WireMock.delete;
+import static com.github.tomakehurst.wiremock.client.WireMock.deleteRequestedFor;
+import static com.github.tomakehurst.wiremock.client.WireMock.equalTo;
+import static com.github.tomakehurst.wiremock.client.WireMock.givenThat;
+import static com.github.tomakehurst.wiremock.client.WireMock.ok;
+import static com.github.tomakehurst.wiremock.client.WireMock.post;
+import static com.github.tomakehurst.wiremock.client.WireMock.postRequestedFor;
+import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
+import static com.github.tomakehurst.wiremock.client.WireMock.verify;
+import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig;
+import static org.apache.http.HttpHeaders.ACCEPT;
+import static org.apache.http.HttpHeaders.CONTENT_TYPE;
+
+import com.github.tomakehurst.wiremock.junit.WireMockRule;
+import java.io.IOException;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+public class NetboxHttpClientTest {
+
+ private static final String APPLICATION_JSON = "application/json";
+
+ @Rule
+ public WireMockRule wm = new WireMockRule(wireMockConfig().dynamicPort());
+
+ private NetboxHttpClient httpClient;
+
+ @Before
+ public void setup() {
+ String baseUrl = "http://localhost:" + wm.port();
+ String token = "token";
+
+ httpClient = new NetboxHttpClient(baseUrl, token);
+
+ wm.addMockServiceRequestListener(
+ (request, response) -> {
+ System.out.println("Request URL :" + request.getAbsoluteUrl());
+ System.out.println("Request body :" + request.getBodyAsString());
+ System.out.println("Response status :" + response.getStatus());
+ System.out.println("Response body :" + response.getBodyAsString());
+ });
+ }
+
+ @After
+ public void tearDown() throws IOException {
+ httpClient.close();
+ }
+
+ @Test
+ public void postTest() throws IOException {
+ String expectedUrl = "/testPost";
+ givenThat(post(urlEqualTo(expectedUrl)).willReturn(ok()));
+
+ httpClient.post(expectedUrl, "");
+
+ verify(postRequestedFor(urlEqualTo(expectedUrl))
+ .withHeader(ACCEPT, equalTo(APPLICATION_JSON))
+ .withHeader(CONTENT_TYPE, equalTo(APPLICATION_JSON)));
+ }
+
+ @Test
+ public void deleteTest() throws IOException {
+ String expectedUrl = "/testDelete";
+ givenThat(delete(urlEqualTo(expectedUrl)).willReturn(ok()));
+ httpClient.delete(expectedUrl);
+ verify(deleteRequestedFor(urlEqualTo(expectedUrl))
+ .withHeader(ACCEPT, equalTo(APPLICATION_JSON))
+ .withHeader(CONTENT_TYPE, equalTo(APPLICATION_JSON)));
+ }
+}
diff --git a/adaptors/netbox-client/provider/src/test/resources/badResponse.json b/adaptors/netbox-client/provider/src/test/resources/badResponse.json
new file mode 100644
index 000000000..713109fd9
--- /dev/null
+++ b/adaptors/netbox-client/provider/src/test/resources/badResponse.json
@@ -0,0 +1,4 @@
+{
+ "id": 8
+ "address": "192.168.20.7/32"
+} \ No newline at end of file
diff --git a/adaptors/netbox-client/provider/src/test/resources/nextAvailableIpResponse.json b/adaptors/netbox-client/provider/src/test/resources/nextAvailableIpResponse.json
new file mode 100644
index 000000000..dec1245e9
--- /dev/null
+++ b/adaptors/netbox-client/provider/src/test/resources/nextAvailableIpResponse.json
@@ -0,0 +1,13 @@
+{
+ "id": 8,
+ "address": "192.168.20.7/32",
+ "vrf": null,
+ "tenant": 1,
+ "status": 1,
+ "role": null,
+ "interface": null,
+ "description": "",
+ "nat_inside": null,
+ "created": "2018-08-15",
+ "last_updated": "2018-08-15T15:51:26.634903Z"
+} \ No newline at end of file
diff --git a/adaptors/releases/0.5.0.yaml b/adaptors/releases/0.5.0.yaml
new file mode 100644
index 000000000..37812aa12
--- /dev/null
+++ b/adaptors/releases/0.5.0.yaml
@@ -0,0 +1,5 @@
+---
+distribution_type: 'maven'
+version: '0.5.0'
+project: 'ccsdk-sli-adaptors'
+log_dir: 'ccsdk-sli-adaptors-maven-stage-master/160/'
diff --git a/adaptors/releases/0.5.1.yaml b/adaptors/releases/0.5.1.yaml
new file mode 100644
index 000000000..3a5c7e5a4
--- /dev/null
+++ b/adaptors/releases/0.5.1.yaml
@@ -0,0 +1,5 @@
+---
+distribution_type: 'maven'
+version: '0.5.1'
+project: 'ccsdk-sli-adaptors'
+log_dir: 'ccsdk-sli-adaptors-maven-stage-master/166/'
diff --git a/adaptors/releases/0.5.2.yaml b/adaptors/releases/0.5.2.yaml
new file mode 100644
index 000000000..b12976297
--- /dev/null
+++ b/adaptors/releases/0.5.2.yaml
@@ -0,0 +1,5 @@
+---
+distribution_type: 'maven'
+version: '0.5.2'
+project: 'ccsdk-sli-adaptors'
+log_dir: 'ccsdk-sli-adaptors-maven-stage-master/175/'
diff --git a/adaptors/releases/0.6.0.yaml b/adaptors/releases/0.6.0.yaml
new file mode 100644
index 000000000..44bed26c8
--- /dev/null
+++ b/adaptors/releases/0.6.0.yaml
@@ -0,0 +1,5 @@
+---
+distribution_type: 'maven'
+version: '0.6.0'
+project: 'ccsdk-sli-adaptors'
+log_dir: 'ccsdk-sli-adaptors-maven-stage-master/189/'
diff --git a/adaptors/releases/0.6.1.yaml b/adaptors/releases/0.6.1.yaml
new file mode 100644
index 000000000..54d356532
--- /dev/null
+++ b/adaptors/releases/0.6.1.yaml
@@ -0,0 +1,5 @@
+---
+distribution_type: 'maven'
+version: '0.6.1'
+project: 'ccsdk-sli-adaptors'
+log_dir: 'ccsdk-sli-adaptors-maven-stage-master/206/'
diff --git a/adaptors/releases/0.7.0.yaml b/adaptors/releases/0.7.0.yaml
new file mode 100644
index 000000000..e0490b849
--- /dev/null
+++ b/adaptors/releases/0.7.0.yaml
@@ -0,0 +1,5 @@
+---
+distribution_type: 'maven'
+version: '0.7.0'
+project: 'ccsdk-sli-adaptors'
+log_dir: 'ccsdk-sli-adaptors-maven-stage-master/304/'
diff --git a/adaptors/releases/0.7.1.yaml b/adaptors/releases/0.7.1.yaml
new file mode 100644
index 000000000..da8191dee
--- /dev/null
+++ b/adaptors/releases/0.7.1.yaml
@@ -0,0 +1,5 @@
+---
+distribution_type: 'maven'
+version: '0.7.1'
+project: 'ccsdk-sli-adaptors'
+log_dir: 'ccsdk-sli-adaptors-maven-stage-master/305/'
diff --git a/adaptors/releases/1.0.0.yaml b/adaptors/releases/1.0.0.yaml
new file mode 100644
index 000000000..b7c72915b
--- /dev/null
+++ b/adaptors/releases/1.0.0.yaml
@@ -0,0 +1,5 @@
+---
+distribution_type: 'maven'
+version: '1.0.0'
+project: 'ccsdk-sli-adaptors'
+log_dir: 'ccsdk-sli-adaptors-maven-stage-master/306/'
diff --git a/adaptors/releases/1.0.1.yaml b/adaptors/releases/1.0.1.yaml
new file mode 100644
index 000000000..3499a88b4
--- /dev/null
+++ b/adaptors/releases/1.0.1.yaml
@@ -0,0 +1,5 @@
+---
+distribution_type: 'maven'
+version: '1.0.1'
+project: 'ccsdk-sli-adaptors'
+log_dir: 'ccsdk-sli-adaptors-maven-stage-master/307/'
diff --git a/adaptors/releases/1.1.0.yaml b/adaptors/releases/1.1.0.yaml
new file mode 100644
index 000000000..9aa20862e
--- /dev/null
+++ b/adaptors/releases/1.1.0.yaml
@@ -0,0 +1,5 @@
+---
+distribution_type: 'maven'
+version: '1.1.0'
+project: 'ccsdk-sli-adaptors'
+log_dir: 'ccsdk-sli-adaptors-maven-stage-master/308/'
diff --git a/adaptors/resource-assignment/.gitignore b/adaptors/resource-assignment/.gitignore
new file mode 100755
index 000000000..b73caf31e
--- /dev/null
+++ b/adaptors/resource-assignment/.gitignore
@@ -0,0 +1,34 @@
+#####standard .git ignore entries#####
+
+## IDE Specific Files ##
+org.eclipse.core.resources.prefs
+.classpath
+.project
+.settings
+.idea
+.externalToolBuilders
+maven-eclipse.xml
+workspace
+
+## Compilation Files ##
+*.class
+**/target
+target
+target-ide
+MANIFEST.MF
+
+## Misc Ignores (OS specific etc) ##
+bin/
+dist
+*~
+*.ipr
+*.iml
+*.iws
+classes
+out/
+.DS_STORE
+.metadata
+
+## Folders which contain auto generated source code ##
+yang-gen-config
+yang-gen-sal
diff --git a/adaptors/resource-assignment/.sonar/checkstyle.xml b/adaptors/resource-assignment/.sonar/checkstyle.xml
new file mode 100755
index 000000000..3fa231535
--- /dev/null
+++ b/adaptors/resource-assignment/.sonar/checkstyle.xml
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE module PUBLIC "-//Puppy Crawl//DTD Check Configuration 1.2//EN" "http://www.puppycrawl.com/dtds/configuration_1_2.dtd"><!-- Generated by Sonar --><module name="Checker"><module name="SuppressionCommentFilter"/><module name="TreeWalker"><module name="FileContentsHolder"/> <module name="ClassFanOutComplexity"><property name="severity" value="warning"/></module><module name="NestedForDepth"><property name="severity" value="warning"/><property name="max" value="1"/></module><module name="ClassDataAbstractionCoupling"><property name="severity" value="warning"/></module></module></module> \ No newline at end of file
diff --git a/adaptors/resource-assignment/.sonar/pmd.xml b/adaptors/resource-assignment/.sonar/pmd.xml
new file mode 100755
index 000000000..80343b3bd
--- /dev/null
+++ b/adaptors/resource-assignment/.sonar/pmd.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ruleset>
+ <rule ref="rulesets/java/naming.xml/BooleanGetMethodName">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/j2ee.xml/StaticEJBFieldShouldBeFinal">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/coupling.xml/CouplingBetweenObjects">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/codesize.xml/TooManyMethods">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/naming.xml/AvoidFieldNameMatchingTypeName">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/basic.xml/DoubleCheckedLocking">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/naming.xml/AvoidFieldNameMatchingMethodName">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/coupling.xml/ExcessiveImports">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/basic.xml/OverrideBothEqualsAndHashcode">
+ <priority>2</priority>
+ </rule>
+ <rule ref="rulesets/java/naming.xml/ShortMethodName">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/basic.xml/BooleanInstantiation">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/codesize.xml/TooManyFields">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/controversial.xml/AvoidUsingNativeCode">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/optimizations.xml/UseStringBufferForStringAppends">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/coupling.xml/LooseCoupling">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/design.xml/NonThreadSafeSingleton">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/j2ee.xml/DoNotUseThreads">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/sunsecure.xml/ArrayIsStoredDirectly">
+ <priority>5</priority>
+ </rule>
+ <rule ref="rulesets/java/sunsecure.xml/MethodReturnsInternalArray">
+ <priority>2</priority>
+ </rule>
+ <rule ref="rulesets/java/design.xml/AssignmentToNonFinalStatic">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/strictexception.xml/AvoidCatchingGenericException">
+ <priority>3</priority>
+ </rule>
+</ruleset>
+
diff --git a/adaptors/resource-assignment/installer/pom.xml b/adaptors/resource-assignment/installer/pom.xml
new file mode 100755
index 000000000..11ff40ce3
--- /dev/null
+++ b/adaptors/resource-assignment/installer/pom.xml
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>odlparent-lite</artifactId>
+ <version>2.1.0</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.adaptors</groupId>
+ <artifactId>resource-assignment-installer</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>pom</packaging>
+
+ <name>ccsdk-sli-adaptors :: resource-assignment :: ${project.artifactId}</name>
+
+ <properties>
+ <application.name>ccsdk-resource-assignment</application.name>
+ <features.boot>${application.name}</features.boot>
+ <features.repositories>mvn:org.onap.ccsdk.sli.adaptors/${features.boot}/${project.version}/xml/features</features.repositories>
+ <include.transitive.dependencies>false</include.transitive.dependencies>
+ </properties>
+
+ <dependencies>
+
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.adaptors</groupId>
+ <artifactId>resource-assignment-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <version>2.6</version>
+ <executions>
+ <execution>
+ <id>maven-repo-zip</id>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ <phase>package</phase>
+ <configuration>
+ <attach>true</attach>
+ <finalName>stage/${application.name}-${project.version}</finalName>
+ <descriptors>
+ <descriptor>src/assembly/assemble_mvnrepo_zip.xml</descriptor>
+ </descriptors>
+ <appendAssemblyId>true</appendAssemblyId>
+ </configuration>
+ </execution>
+ <execution>
+ <id>installer-zip</id>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ <phase>package</phase>
+ <configuration>
+ <attach>true</attach>
+ <finalName>${application.name}-${project.version}-installer</finalName>
+ <descriptors>
+ <descriptor>src/assembly/assemble_installer_zip.xml</descriptor>
+ </descriptors>
+ <appendAssemblyId>false</appendAssemblyId>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>copy-dependencies</id>
+ <goals>
+ <goal>copy-dependencies</goal>
+ </goals>
+ <phase>prepare-package</phase>
+ <configuration>
+ <transitive>false</transitive>
+ <outputDirectory>${project.build.directory}/assembly/system</outputDirectory>
+ <overWriteReleases>false</overWriteReleases>
+ <overWriteSnapshots>true</overWriteSnapshots>
+ <overWriteIfNewer>true</overWriteIfNewer>
+ <useRepositoryLayout>true</useRepositoryLayout>
+ <addParentPoms>false</addParentPoms>
+ <copyPom>false</copyPom>
+ <includeGroupIds>org.onap.ccsdk.sli.adaptors</includeGroupIds>
+ <scope>provided</scope>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <artifactId>maven-resources-plugin</artifactId>
+ <version>2.6</version>
+ <executions>
+ <execution>
+ <id>copy-version</id>
+ <goals>
+ <goal>copy-resources</goal>
+ </goals><!-- here the phase you need -->
+ <phase>validate</phase>
+ <configuration>
+ <outputDirectory>${basedir}/target/stage</outputDirectory>
+ <resources>
+ <resource>
+ <directory>src/main/resources/scripts</directory>
+ <includes>
+ <include>install-feature.sh</include>
+ </includes>
+ <filtering>true</filtering>
+ </resource>
+ </resources>
+ </configuration>
+ </execution>
+
+ </executions>
+ </plugin>
+
+ </plugins>
+ </build>
+</project>
diff --git a/adaptors/resource-assignment/installer/src/assembly/assemble_installer_zip.xml b/adaptors/resource-assignment/installer/src/assembly/assemble_installer_zip.xml
new file mode 100644
index 000000000..b81e1d47a
--- /dev/null
+++ b/adaptors/resource-assignment/installer/src/assembly/assemble_installer_zip.xml
@@ -0,0 +1,59 @@
+<!--
+ ============LICENSE_START=======================================================
+ openECOMP : SDN-C
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property. All rights
+ reserved.
+ ================================================================================
+ 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.
+ ============LICENSE_END=========================================================
+ -->
+
+<!-- Defines how we build the .zip file which is our distribution. -->
+
+<assembly
+ xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
+ <id>installer_zip</id>
+ <formats>
+ <format>zip</format>
+ </formats>
+
+ <!-- we want "system" and related files right at the root level
+ as this file is suppose to be unzip on top of a karaf
+ distro. -->
+ <includeBaseDirectory>false</includeBaseDirectory>
+
+ <fileSets>
+ <fileSet>
+ <directory>target/stage/</directory>
+ <outputDirectory>${application.name}</outputDirectory>
+ <fileMode>755</fileMode>
+ <includes>
+ <include>*.sh</include>
+ </includes>
+ </fileSet>
+ <fileSet>
+ <directory>target/stage/</directory>
+ <outputDirectory>${application.name}</outputDirectory>
+ <fileMode>644</fileMode>
+ <excludes>
+ <exclude>*.sh</exclude>
+ </excludes>
+ </fileSet>
+ </fileSets>
+
+
+
+</assembly>
diff --git a/adaptors/resource-assignment/installer/src/assembly/assemble_mvnrepo_zip.xml b/adaptors/resource-assignment/installer/src/assembly/assemble_mvnrepo_zip.xml
new file mode 100644
index 000000000..9b4a25f49
--- /dev/null
+++ b/adaptors/resource-assignment/installer/src/assembly/assemble_mvnrepo_zip.xml
@@ -0,0 +1,49 @@
+<!--
+ ============LICENSE_START=======================================================
+ openECOMP : SDN-C
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property. All rights
+ reserved.
+ ================================================================================
+ 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.
+ ============LICENSE_END=========================================================
+ -->
+
+<!-- Defines how we build the .zip file which is our distribution. -->
+
+<assembly
+ xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
+ <id>repo</id>
+ <formats>
+ <format>zip</format>
+ </formats>
+
+ <!-- we want "system" and related files right at the root level
+ as this file is suppose to be unzip on top of a karaf
+ distro. -->
+ <includeBaseDirectory>false</includeBaseDirectory>
+
+ <fileSets>
+ <fileSet>
+ <directory>target/assembly/</directory>
+ <outputDirectory>.</outputDirectory>
+ <excludes>
+ </excludes>
+ </fileSet>
+ </fileSets>
+
+
+
+</assembly>
diff --git a/adaptors/resource-assignment/installer/src/main/resources/scripts/install-feature.sh b/adaptors/resource-assignment/installer/src/main/resources/scripts/install-feature.sh
new file mode 100644
index 000000000..06f5b7d5e
--- /dev/null
+++ b/adaptors/resource-assignment/installer/src/main/resources/scripts/install-feature.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+
+###
+# ============LICENSE_START=======================================================
+# openECOMP : SDN-C
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights
+# reserved.
+# ================================================================================
+# 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.
+# ============LICENSE_END=========================================================
+###
+
+ODL_HOME=${ODL_HOME:-/opt/opendaylight/current}
+ODL_KARAF_CLIENT=${ODL_KARAF_CLIENT:-${ODL_HOME}/bin/client}
+INSTALLERDIR=$(dirname $0)
+
+REPOZIP=${INSTALLERDIR}/${features.boot}-${project.version}.zip
+
+if [ -f ${REPOZIP} ]
+then
+ unzip -nd ${ODL_HOME} ${REPOZIP}
+else
+ echo "ERROR : repo zip ($REPOZIP) not found"
+ exit 1
+fi
+
+${ODL_KARAF_CLIENT} feature:repo-add ${features.repositories}
+${ODL_KARAF_CLIENT} feature:install ${features.boot}
diff --git a/adaptors/resource-assignment/pom.xml b/adaptors/resource-assignment/pom.xml
new file mode 100755
index 000000000..c2ef269ca
--- /dev/null
+++ b/adaptors/resource-assignment/pom.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>odlparent-lite</artifactId>
+ <version>2.1.0</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.adaptors</groupId>
+ <artifactId>resource-assignment</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>pom</packaging>
+
+ <name>ccsdk-sli-adaptors :: resource-assignment</name>
+ <description>The resource assignment adaptor allows service logic to check and allocate network capacity</description>
+
+ <modules>
+ <module>provider</module>
+ <module>installer</module>
+ </modules>
+</project>
diff --git a/adaptors/resource-assignment/provider/pom.xml b/adaptors/resource-assignment/provider/pom.xml
new file mode 100755
index 000000000..014daeae5
--- /dev/null
+++ b/adaptors/resource-assignment/provider/pom.xml
@@ -0,0 +1,91 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>binding-parent</artifactId>
+ <version>2.1.0</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.adaptors</groupId>
+ <artifactId>resource-assignment-provider</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>bundle</packaging>
+
+ <name>ccsdk-sli-adaptors :: resource-assignment :: ${project.artifactId}</name>
+ <url>http://maven.apache.org</url>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <ccsdk.sli.adaptors.version>${project.version}</ccsdk.sli.adaptors.version>
+ </properties>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sli-core-artifacts</artifactId>
+ <version>${ccsdk.sli.core.version}</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-test</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.h2database</groupId>
+ <artifactId>h2</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sli-common</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sli-provider</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>dblib-provider</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.mariadb.jdbc</groupId>
+ <artifactId>mariadb-java-client</artifactId>
+ <type>jar</type>
+ <scope>runtime</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-beans</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-context</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-jdbc</artifactId>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/lock/comp/LockHelper.java b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/lock/comp/LockHelper.java
new file mode 100644
index 000000000..040d19273
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/lock/comp/LockHelper.java
@@ -0,0 +1,39 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.lock.comp;
+
+import java.util.Collection;
+
+public interface LockHelper {
+
+ void lock(String resourceName, String lockRequester, int lockTimeout /* Seconds */);
+
+ void lock(String resourceName, String lockRequester, int lockTimeout /* Seconds */, int lockWait /* Seconds */, int retryCount);
+
+ void unlock(String resourceName, boolean force);
+
+ void lock(Collection<String> resourceNameList, String lockRequester, int lockTimeout /* Seconds */);
+
+ void lock(Collection<String> resourceNameList, String lockRequester, int lockTimeout /* Seconds */, int lockWait /* Seconds */, int retryCount);
+
+ void unlock(Collection<String> resourceNameList, boolean force);
+}
diff --git a/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/lock/comp/LockHelperImpl.java b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/lock/comp/LockHelperImpl.java
new file mode 100644
index 000000000..735d240c0
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/lock/comp/LockHelperImpl.java
@@ -0,0 +1,206 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.lock.comp;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Date;
+import java.util.List;
+import org.onap.ccsdk.sli.adaptors.lock.dao.ResourceLockDao;
+import org.onap.ccsdk.sli.adaptors.lock.data.ResourceLock;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class LockHelperImpl implements LockHelper {
+
+ private static final Logger log = LoggerFactory.getLogger(LockHelperImpl.class);
+
+ private ResourceLockDao resourceLockDao;
+ private int retryCount = 10;
+ private int lockWait = 5; // Seconds
+
+ @Override
+ public void lock(String resourceName, String lockRequester, int lockTimeout /* Seconds */) {
+ lock(resourceName, lockRequester, lockTimeout, lockWait, retryCount);
+ }
+
+ @Override
+ public void lock(String resourceName, String lockRequester, int lockTimeout /* Seconds */,
+ int lockWait /* Seconds */, int retryCount) {
+ lock(Collections.singleton(resourceName), lockRequester, lockTimeout, lockWait, retryCount);
+ }
+
+ @Override
+ public void unlock(String resourceName, boolean force) {
+ unlock(Collections.singleton(resourceName), force);
+ }
+
+ @Override
+ public void lock(Collection<String> resourceNameList, String lockRequester, int lockTimeout /* Seconds */) {
+ lock(resourceNameList, lockRequester, lockTimeout, lockWait, retryCount);
+ }
+
+ @Override
+ public void lock(Collection<String> resourceNameList, String lockRequester, int lockTimeout /* Seconds */,
+ int lockWait /* Seconds */, int retryCount) {
+ for (int i = 0; true; i++) {
+ try {
+ tryLock(resourceNameList, lockRequester, lockTimeout);
+ log.info("Resources locked: " + resourceNameList);
+ return;
+ } catch (ResourceLockedException e) {
+ if (i >= retryCount) {
+ throw e;
+ }
+ try {
+ Thread.sleep(lockWait * 1000);
+ } catch (InterruptedException ex) {
+ log.error("Interrupted Exception", ex);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void unlock(Collection<String> lockNames, boolean force) {
+ if (lockNames == null || lockNames.isEmpty()) {
+ return;
+ }
+
+ try {
+ for (String name : lockNames) {
+ ResourceLock l = resourceLockDao.getByResourceName(name);
+ if (l != null) {
+ if (force || l.lockCount == 1) {
+ resourceLockDao.delete(l.id);
+ } else {
+ resourceLockDao.decrementLockCount(l.id);
+ }
+ }
+ }
+
+ resourceLockDao.commit();
+
+ log.info("Resources unlocked: " + lockNames);
+ } finally {
+ resourceLockDao.rollback();
+ }
+ }
+
+ public void tryLock(Collection<String> resourceNameList, String lockRequester, int lockTimeout /* Seconds */) {
+ if (resourceNameList == null || resourceNameList.isEmpty()) {
+ return;
+ }
+
+ lockRequester = generateLockRequester(lockRequester, 100);
+
+ // First check if all requested records are available to lock
+
+ Date now = new Date();
+
+ try {
+ List<ResourceLock> dbLockList = new ArrayList<>();
+ List<String> insertLockNameList = new ArrayList<>();
+ for (String name : resourceNameList) {
+ ResourceLock l = resourceLockDao.getByResourceName(name);
+
+ boolean canLock = l == null || now.getTime() > l.expirationTime.getTime() ||
+ lockRequester != null && lockRequester.equals(l.lockHolder) || l.lockCount <= 0;
+ if (!canLock) {
+ throw new ResourceLockedException(l.resourceName, l.lockHolder, lockRequester);
+ }
+
+ if (l != null) {
+ if (now.getTime() > l.expirationTime.getTime() || l.lockCount <= 0) {
+ l.lockCount = 0;
+ }
+ dbLockList.add(l);
+ } else {
+ insertLockNameList.add(name);
+ }
+ }
+
+ // Update the lock info in DB
+ for (ResourceLock l : dbLockList) {
+ resourceLockDao.update(l.id, lockRequester, now, new Date(now.getTime() + lockTimeout * 1000), l.lockCount + 1);
+ }
+
+ // Insert records for those that are not yet there
+ for (String lockName : insertLockNameList) {
+ ResourceLock l = new ResourceLock();
+ l.resourceName = lockName;
+ l.lockHolder = lockRequester;
+ l.lockTime = now;
+ l.expirationTime = new Date(now.getTime() + lockTimeout * 1000);
+ l.lockCount = 1;
+
+ try {
+ resourceLockDao.add(l);
+ } catch (Exception e) {
+ log.info("Failed to insert lock record: " + lockName);
+ throw new ResourceLockedException(l.resourceName, "unknown", lockRequester);
+ }
+ }
+
+ resourceLockDao.commit();
+
+ }finally
+
+ {
+ resourceLockDao.rollback();
+ }
+ }
+
+ private static String generateLockRequester(String name, int maxLength) {
+ if (name == null) {
+ name = "";
+ }
+ int l1 = name.length();
+ String tname = Thread.currentThread().getName();
+ int l2 = tname.length();
+ if (l1 + l2 + 1 > maxLength) {
+ int maxl1 = maxLength / 2;
+ if (l1 > maxl1) {
+ name = name.substring(0, maxl1);
+ l1 = maxl1;
+ }
+ int maxl2 = maxLength - l1 - 1;
+ if (l2 > maxl2) {
+ tname = tname.substring(0, 6) + "..." + tname.substring(l2 - maxl2 + 9);
+ }
+ }
+ return tname + '-' + name;
+ }
+
+ public void setResourceLockDao(ResourceLockDao resourceLockDao) {
+ this.resourceLockDao = resourceLockDao;
+ }
+
+ public void setRetryCount(int retryCount) {
+ this.retryCount = retryCount;
+ }
+
+ public void setLockWait(int lockWait /* Seconds */) {
+ this.lockWait = lockWait;
+ }
+}
diff --git a/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/lock/comp/ResourceLockedException.java b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/lock/comp/ResourceLockedException.java
new file mode 100644
index 000000000..f503332cc
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/lock/comp/ResourceLockedException.java
@@ -0,0 +1,43 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.lock.comp;
+
+public class ResourceLockedException extends RuntimeException {
+
+ private static final long serialVersionUID = 1L;
+
+ private final String lockName;
+ private final String lockHolder;
+ private final String lockRequester;
+
+ public ResourceLockedException(String lockName, String lockHolder, String lockRequester) {
+ this.lockName = lockName;
+ this.lockHolder = lockHolder;
+ this.lockRequester = lockRequester;
+ }
+
+ @Override
+ public String getMessage() {
+ return "Failed to lock [" + lockName + "] for [" + lockRequester + "]. Currently locked by [" + lockHolder +
+ "].";
+ }
+}
diff --git a/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/lock/comp/SynchronizedFunction.java b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/lock/comp/SynchronizedFunction.java
new file mode 100644
index 000000000..9cce17a46
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/lock/comp/SynchronizedFunction.java
@@ -0,0 +1,58 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.lock.comp;
+
+import java.security.SecureRandom;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+
+public abstract class SynchronizedFunction {
+
+ private Set<String> synchset;
+ private String lockRequester;
+ private int lockTimeout; // Seconds
+ private LockHelper lockHelper;
+
+ protected SynchronizedFunction(LockHelper lockHelper, Collection<String> synchset, int lockTimeout) {
+ this.lockHelper = lockHelper;
+ this.synchset = new HashSet<String>(synchset);
+ this.lockRequester = generateLockRequester();
+ this.lockTimeout = lockTimeout;
+ }
+
+ protected abstract void _exec();
+
+ public void exec() {
+ lockHelper.lock(synchset, lockRequester, lockTimeout);
+ try {
+ _exec();
+ } finally {
+ lockHelper.unlock(synchset, true);
+ }
+ }
+
+ private static String generateLockRequester() {
+ SecureRandom rand = new SecureRandom();
+ return "SynchronizedFunction-" + (int) (rand.nextDouble() * 1000000);
+ }
+}
diff --git a/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/lock/dao/ResourceLockDao.java b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/lock/dao/ResourceLockDao.java
new file mode 100644
index 000000000..dc86f70af
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/lock/dao/ResourceLockDao.java
@@ -0,0 +1,42 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.lock.dao;
+
+import java.util.Date;
+import org.onap.ccsdk.sli.adaptors.lock.data.ResourceLock;
+
+public interface ResourceLockDao {
+
+ void add(ResourceLock l);
+
+ void update(long id, String lockHolder, Date lockTime, Date expirationTime, int lockCount);
+
+ ResourceLock getByResourceName(String resourceName);
+
+ void delete(long id);
+
+ void decrementLockCount(long id);
+
+ void commit();
+
+ void rollback();
+}
diff --git a/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/lock/dao/ResourceLockDaoImpl.java b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/lock/dao/ResourceLockDaoImpl.java
new file mode 100644
index 000000000..b8b3a66d6
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/lock/dao/ResourceLockDaoImpl.java
@@ -0,0 +1,103 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.lock.dao;
+
+import java.util.Date;
+import java.util.List;
+import org.onap.ccsdk.sli.adaptors.lock.data.ResourceLock;
+import org.onap.ccsdk.sli.adaptors.util.db.CachedDataSourceWrap;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.core.RowMapper;
+
+public class ResourceLockDaoImpl implements ResourceLockDao {
+
+ @SuppressWarnings("unused")
+ private static final Logger log = LoggerFactory.getLogger(ResourceLockDaoImpl.class);
+
+ private JdbcTemplate jdbcTemplate;
+
+ @Override
+ public void add(ResourceLock l) {
+ jdbcTemplate.update(
+ "INSERT INTO RESOURCE_LOCK (resource_name, lock_holder, lock_count, lock_time, expiration_time)\n" +
+ "VALUES (?, ?, ?, ?, ?)",
+ new Object[] { l.resourceName, l.lockHolder, l.lockCount, l.lockTime, l.expirationTime });
+ }
+
+ @Override
+ public void update(long id, String lockHolder, Date lockTime, Date expirationTime, int lockCount) {
+ jdbcTemplate.update(
+ "UPDATE RESOURCE_LOCK SET lock_holder = ?, lock_time = ?, expiration_time = ?, lock_count = ? WHERE resource_lock_id = ?",
+ new Object[] { lockHolder, lockTime, expirationTime, lockCount, id });
+ }
+
+ @Override
+ public ResourceLock getByResourceName(String resourceName) {
+ List<ResourceLock> ll = jdbcTemplate.query("SELECT * FROM RESOURCE_LOCK WHERE resource_name = ?",
+ new Object[] { resourceName }, (RowMapper<ResourceLock>) (rs, rowNum) -> {
+ ResourceLock rl = new ResourceLock();
+ rl.id = rs.getLong("resource_lock_id");
+ rl.resourceName = rs.getString("resource_name");
+ rl.lockHolder = rs.getString("lock_holder");
+ rl.lockCount = rs.getInt("lock_count");
+ rl.lockTime = rs.getTimestamp("lock_time");
+ rl.expirationTime = rs.getTimestamp("expiration_time");
+ return rl;
+ });
+ return ll != null && !ll.isEmpty() ? ll.get(0) : null;
+ }
+
+ @Override
+ public void delete(long id) {
+ jdbcTemplate.update("DELETE FROM RESOURCE_LOCK WHERE resource_lock_id = ?", new Object[] { id });
+ }
+
+ @Override
+ public void decrementLockCount(long id) {
+ jdbcTemplate.update("UPDATE RESOURCE_LOCK SET lock_count = lock_count - 1 WHERE resource_lock_id = ?",
+ new Object[] { id });
+ }
+
+ public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
+ this.jdbcTemplate = jdbcTemplate;
+ }
+
+ @Override
+ public void commit() {
+ if (jdbcTemplate.getDataSource() instanceof CachedDataSourceWrap) {
+ CachedDataSourceWrap ds = (CachedDataSourceWrap) jdbcTemplate.getDataSource();
+ ds.commit();
+ ds.releaseConnection();
+ }
+ }
+
+ @Override
+ public void rollback() {
+ if (jdbcTemplate.getDataSource() instanceof CachedDataSourceWrap) {
+ CachedDataSourceWrap ds = (CachedDataSourceWrap) jdbcTemplate.getDataSource();
+ ds.rollback();
+ ds.releaseConnection();
+ }
+ }
+}
diff --git a/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/lock/data/ResourceLock.java b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/lock/data/ResourceLock.java
new file mode 100644
index 000000000..cb434e142
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/lock/data/ResourceLock.java
@@ -0,0 +1,34 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.lock.data;
+
+import java.util.Date;
+
+public class ResourceLock {
+
+ public long id;
+ public String resourceName;
+ public String lockHolder;
+ public int lockCount;
+ public Date lockTime;
+ public Date expirationTime;
+}
diff --git a/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/ra/ResourceAllocator.java b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/ra/ResourceAllocator.java
new file mode 100644
index 000000000..10f3e02b7
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/ra/ResourceAllocator.java
@@ -0,0 +1,583 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ * reserved.
+ * Modifications Copyright (C) 2019 IBM.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.ra;
+
+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 java.util.Set;
+import org.onap.ccsdk.sli.adaptors.ra.comp.AllocationData;
+import org.onap.ccsdk.sli.adaptors.ra.comp.EndPointAllocator;
+import org.onap.ccsdk.sli.adaptors.ra.comp.ResourceData;
+import org.onap.ccsdk.sli.adaptors.ra.comp.ResourceEntity;
+import org.onap.ccsdk.sli.adaptors.ra.comp.ResourceRequest;
+import org.onap.ccsdk.sli.adaptors.ra.comp.ResourceResponse;
+import org.onap.ccsdk.sli.adaptors.ra.comp.ResourceTarget;
+import org.onap.ccsdk.sli.adaptors.rm.comp.ResourceManager;
+import org.onap.ccsdk.sli.adaptors.rm.data.AllocationStatus;
+import org.onap.ccsdk.sli.adaptors.rm.data.ReleaseRequest;
+import org.onap.ccsdk.sli.adaptors.util.speed.SpeedUtil;
+import org.onap.ccsdk.sli.adaptors.util.str.StrUtil;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.core.sli.SvcLogicResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ResourceAllocator implements SvcLogicResource {
+
+ private static final Logger log = LoggerFactory.getLogger(ResourceAllocator.class);
+
+ private static final String[] INPUT_PREFIX = {"ra-input.", "tmp.resource-allocator."};
+
+ private ResourceManager resourceManager;
+ private EndPointAllocator endPointAllocator;
+ private SpeedUtil speedUtil;
+
+ public ResourceAllocator() {
+ log.info("ResourceAllocator created.");
+ }
+
+ @Override
+ public QueryStatus notify(String resource, String action, String key, SvcLogicContext ctx)
+ throws SvcLogicException {
+ return QueryStatus.SUCCESS;
+ }
+
+ @Override
+ public QueryStatus update(String resource, String key, Map<String, String> parms, String prefix,
+ SvcLogicContext ctx) throws SvcLogicException {
+
+ return QueryStatus.SUCCESS;
+ }
+
+ @Override
+ public QueryStatus exists(String resource, String key, String prefix, SvcLogicContext ctx)
+ throws SvcLogicException {
+ return QueryStatus.SUCCESS;
+ }
+
+ @Override
+ public QueryStatus delete(String arg0, String arg1, SvcLogicContext arg2) throws SvcLogicException {
+ return QueryStatus.SUCCESS;
+ }
+
+ @Override
+ public QueryStatus save(String arg0, boolean arg1, boolean arg2, String arg3, Map<String, String> arg4, String arg5,
+ SvcLogicContext arg6) throws SvcLogicException {
+ return QueryStatus.SUCCESS;
+ }
+
+ @Override
+ public QueryStatus isAvailable(String resource, String key, String prefix, SvcLogicContext ctx)
+ throws SvcLogicException {
+ return allocateResources(ctx, true, prefix);
+ }
+
+ @Override
+ public QueryStatus query(String resource, boolean localOnly, String select, String key, String prefix,
+ String orderBy, SvcLogicContext ctx) throws SvcLogicException {
+
+ String resourceEntityId = getParam(ctx,
+ new String[] {"service-instance-id", "resource-entity-id", "reservation-entity-id"}, false, null);
+ String resourceEntityType =
+ getParam(ctx, new String[] {"reservation-entity-type", "resource-entity-type"}, false, null);
+ String resourceEntityVersion =
+ getParam(ctx, new String[] {"reservation-entity-version", "resource-entity-version"}, false, "1");
+
+ String resourceTargetId =
+ getParam(ctx, new String[] {"reservation-target-id", "resource-target-id"}, false, null);
+ String resourceTargetType =
+ getParam(ctx, new String[] {"reservation-target-type", "resource-target-type"}, false, null);
+ String resourceName = getParam(ctx, "resource-name", false, null);
+ String resourceEntityTypeFilter = getParam(ctx, "resource-entity-type-filter", false, null);
+ String resourceEntityIdFilter = getParam(ctx, "resource-entity-id-filter", false, null);
+ String resourceShareGroupFilter = getParam(ctx, "resource-share-group-filter", false, null);
+ String resourceTargetTypeFilter = getParam(ctx, "resource-target-type-filter", false, null);
+ String resourceTargetIdFilter = getParam(ctx, "resource-target-id-filter", false, null);
+
+ if (resourceEntityId != null && resourceEntityType != null) {
+ List<ResourceData> rdlist = endPointAllocator.getResourcesForEntity(resourceEntityType, resourceEntityId,
+ resourceEntityVersion);
+ setResourceDataInContext(ctx, prefix, rdlist);
+ } else if (resourceTargetId != null && resourceTargetType != null && resourceName != null) {
+ ResourceData rd = endPointAllocator.getResource(resourceTargetType, resourceTargetId, resourceName,
+ resourceEntityTypeFilter, resourceEntityIdFilter, resourceShareGroupFilter);
+ if (rd != null) {
+ setResourceDataInContext(ctx, prefix, Collections.singletonList(rd));
+ }
+ } else if ((resourceTargetTypeFilter != null || resourceTargetIdFilter != null) && resourceName != null) {
+ List<ResourceData> rdlist = endPointAllocator.getResourcesForTarget(resourceTargetTypeFilter,
+ resourceTargetIdFilter, resourceName);
+ setResourceDataInContext(ctx, prefix, rdlist);
+ }
+
+ return QueryStatus.SUCCESS;
+ }
+
+ public AllocationStatus query(ResourceEntity sd, ResourceTarget rt, ResourceRequest rr,
+ List<ResourceResponse> rsList) throws Exception {
+
+ if (sd != null && sd.resourceEntityId != null && sd.resourceEntityType != null) {
+ List<ResourceData> rdlist = endPointAllocator.getResourcesForEntity(sd.resourceEntityType,
+ sd.resourceEntityId, sd.resourceEntityVersion);
+ setResourceDataInResponse(rdlist, rsList);
+ } else if (rt != null && rt.resourceTargetId != null && rt.resourceTargetType != null && rr != null
+ && rr.resourceName != null) {
+ ResourceData rd = endPointAllocator.getResource(rt.resourceTargetType, rt.resourceTargetId, rr.resourceName,
+ rr.resourceEntityTypeFilter, rr.resourceEntityIdFilter, rr.resourceShareGroupFilter);
+ setResourceDataInResponse(Collections.singletonList(rd), rsList);
+ } else if (rr != null && (rr.resourceTargetTypeFilter != null || rr.resourceTargetIdFilter != null)
+ && rr.resourceName != null) {
+ List<ResourceData> rdlist = endPointAllocator.getResourcesForTarget(rr.resourceTargetTypeFilter,
+ rr.resourceTargetIdFilter, rr.resourceName);
+ setResourceDataInResponse(rdlist, rsList);
+ }
+
+ return AllocationStatus.Success;
+ }
+
+ private void setResourceDataInContext(SvcLogicContext ctx, String prefix, List<ResourceData> rdlist) {
+ if (rdlist == null || rdlist.isEmpty()) {
+ return;
+ }
+
+ prefix = prefix == null ? "" : prefix + '.';
+
+ setAttr(ctx, prefix + "resource-list_length", String.valueOf(rdlist.size()));
+
+ for (int i = 0; i < rdlist.size(); i++) {
+ ResourceData rd = rdlist.get(i);
+
+ String pp = prefix + "resource-list[" + i + "].";
+
+ setAttr(ctx, pp + "resource-name", rd.resourceName);
+ setAttr(ctx, pp + "endpoint-position", rd.endPointPosition);
+ setAttr(ctx, pp + "resource-target-type", rd.resourceTargetType);
+ setAttr(ctx, pp + "resource-target-id", rd.resourceTargetId);
+ setAttr(ctx, pp + "resource-target-value", rd.resourceTargetValue);
+ setAttr(ctx, pp + "status", rd.status);
+
+ Map<String, String> dataProp = dataToProperties(rd.data);
+ for (String kk : dataProp.keySet()) {
+ String value = String.valueOf(dataProp.get(kk));
+ setAttr(ctx, pp + kk, value);
+ }
+
+ if (rd.allocationDataList != null && !rd.allocationDataList.isEmpty()) {
+
+ setAttr(ctx, pp + "allocation-data-list_length", String.valueOf(rd.allocationDataList.size()));
+
+ for (int j = 0; j < rd.allocationDataList.size(); j++) {
+ AllocationData ad = rd.allocationDataList.get(j);
+
+ String ppp = pp + "allocation-data-list[" + j + "].";
+
+ setAttr(ctx, ppp + "resource-entity-type", ad.resourceEntityType);
+ setAttr(ctx, ppp + "resource-entity-id", ad.resourceEntityId);
+ setAttr(ctx, ppp + "resource-entity-version", ad.resourceEntityVersion);
+
+ if (ad.data != null && !ad.data.isEmpty()) {
+ for (String kk : ad.data.keySet()) {
+ String value = String.valueOf(ad.data.get(kk));
+ setAttr(ctx, ppp + kk, value);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ @Override
+ public QueryStatus reserve(String resource, String select, String key, String prefix, SvcLogicContext ctx)
+ throws SvcLogicException {
+ return allocateResources(ctx, false, prefix);
+ }
+
+ public AllocationStatus reserve(ResourceEntity sd, ResourceTarget rt, ResourceRequest rr,
+ List<ResourceResponse> rsList) throws Exception {
+ return allocateResources(sd, rt, rr, rsList);
+ }
+
+ @Override
+ public QueryStatus release(String resource, String key, SvcLogicContext ctx) throws SvcLogicException {
+ String resourceEntityId = getParam(ctx,
+ new String[] {"service-instance-id", "resource-entity-id", "reservation-entity-id"}, true, null);
+ String resourceEntityType =
+ getParam(ctx, new String[] {"reservation-entity-type", "resource-entity-type"}, true, null);
+ String resourceEntityVersion =
+ getParam(ctx, new String[] {"reservation-entity-version", "resource-entity-version"}, false, null);
+ String resourceTargetId =
+ getParam(ctx, new String[] {"reservation-target-id", "resource-target-id"}, false, null);
+ String resourceTargetType =
+ getParam(ctx, new String[] {"reservation-target-type", "resource-target-type"}, false, null);
+ String resourceName = getParam(ctx, new String[] {"resource-name"}, false, null);
+ String limitReleaseAmountStr = getParam(ctx, new String[] {"limit-release-amount"}, false, "-1");
+ int limitReleaseAmount = Integer.parseInt(limitReleaseAmountStr);
+ String rangeReleaseNumbers = getParam(ctx, new String[] {"range-release-numbers"}, false, null);
+
+
+ String endPointPosition = getParam(ctx, "endpoint-position", false, null);
+
+ ResourceEntity sd = new ResourceEntity();
+ sd.resourceEntityId = resourceEntityId;
+ sd.resourceEntityType = resourceEntityType;
+ sd.resourceEntityVersion = resourceEntityVersion;
+
+ ResourceRequest rr = new ResourceRequest();
+ rr.endPointPosition = endPointPosition;
+ rr.resourceName = resourceName;
+ rr.rangeReleaseNumbers = rangeReleaseNumbers;
+ rr.limitReleaseAmount = limitReleaseAmount;
+
+ ResourceTarget rt = new ResourceTarget();
+ rt.resourceTargetType = resourceTargetType;
+ rt.resourceTargetId = resourceTargetId;
+
+ try {
+ this.release(sd, rr, rt);
+ } catch (Exception e) {
+ throw new SvcLogicException(e.getMessage());
+ }
+ return QueryStatus.SUCCESS;
+ }
+
+ public AllocationStatus release(ResourceEntity sd) throws Exception {
+ return release(sd, null, null);
+ }
+
+ public AllocationStatus release(ResourceEntity sd, ResourceRequest rr) throws Exception {
+ return release(sd, rr, null);
+ }
+
+ public AllocationStatus release(ResourceEntity sd, ResourceRequest rr, ResourceTarget rt) {
+
+ ReleaseRequest releaseRequest = new ReleaseRequest();
+
+ if (sd != null && sd.resourceEntityVersion != null) {
+ releaseRequest.resourceSetId = null;
+
+ if (rr != null && rr.endPointPosition != null && !rr.endPointPosition.isEmpty()) {
+ releaseRequest.resourceSetId = sd.resourceEntityType + "::" + sd.resourceEntityId + "::"
+ + rr.endPointPosition + "::" + sd.resourceEntityVersion;
+ } else {
+ releaseRequest.resourceSetId =
+ sd.resourceEntityType + "::" + sd.resourceEntityId + "::" + sd.resourceEntityVersion;
+ }
+
+ } else if (sd != null && (sd.resourceEntityVersion == null || sd.resourceEntityVersion.isEmpty())) {
+ releaseRequest.resourceUnionId = null;
+
+ if (rr != null && rr.endPointPosition != null && !rr.endPointPosition.isEmpty()) {
+ releaseRequest.resourceUnionId =
+ sd.resourceEntityType + "::" + sd.resourceEntityId + "::" + rr.endPointPosition;
+ } else {
+ releaseRequest.resourceUnionId = sd.resourceEntityType + "::" + sd.resourceEntityId;
+ }
+ }
+
+ if (rt != null && rt.resourceTargetId != null && rt.resourceTargetType != null) {
+ releaseRequest.assetId = rt.resourceTargetType + "::" + rt.resourceTargetId;
+ }
+
+ if (rr != null) {
+ releaseRequest.resourceName = rr.resourceName;
+ releaseRequest.releaseNumbers =
+ StrUtil.listInt(rr.rangeReleaseNumbers, "Invalid value for range-release-numbers");
+ releaseRequest.releaseAmount = rr.limitReleaseAmount;
+ }
+
+ log.info("Releasing resources:");
+ StrUtil.info(log, releaseRequest);
+
+ resourceManager.releaseResources(releaseRequest);
+
+ return AllocationStatus.Success;
+ }
+
+ private QueryStatus allocateResources(SvcLogicContext ctx, boolean checkOnly, String prefix)
+ throws SvcLogicException {
+ String serviceModel = getParam(ctx, "service-model", true, null);
+ String requestType = getParam(ctx, "request-type", false, "New");
+
+ ResourceEntity sd = getResourceEntityData(ctx);
+ ResourceTarget rt = getResourceTargetData(ctx);
+ ResourceRequest rr = getResourceRequest(ctx);
+
+ log.info("Starting reserve: " + requestType + ", service-model: " + serviceModel);
+ StrUtil.info(log, sd);
+ StrUtil.info(log, rt);
+ StrUtil.info(log, rr);
+
+ boolean change = "change".equalsIgnoreCase(requestType);
+
+ List<ResourceData> rlist = endPointAllocator.allocateResources(serviceModel, sd, rt, rr, checkOnly, change);
+
+ if (rlist != null && !rlist.isEmpty()) {
+ setResourceDataInContext(ctx, prefix, rlist);
+
+ for (ResourceData rd : rlist) {
+ if (!"Success".equals(rd.status)) {
+ log.info("Capacity not found for: " + sd.resourceEntityType + "::" + sd.resourceEntityId);
+ return QueryStatus.NOT_FOUND;
+ }
+ }
+ }
+ return QueryStatus.SUCCESS;
+ }
+
+ private AllocationStatus allocateResources(ResourceEntity sd, ResourceTarget rt, ResourceRequest rr,
+ List<ResourceResponse> rsList) throws Exception {
+
+ String serviceModel = rr.serviceModel;
+ String requestType = rr.requestType == null ? "New" : rr.requestType;
+
+ log.info("Starting reserve: " + requestType + ", service-model: " + serviceModel);
+ StrUtil.info(log, sd);
+ StrUtil.info(log, rt);
+ StrUtil.info(log, rr);
+
+ boolean change = "change".equalsIgnoreCase(requestType);
+
+ List<ResourceData> rlist = endPointAllocator.allocateResources(serviceModel, sd, rt, rr, rr.checkOnly, change);
+
+ if (rlist != null && !rlist.isEmpty()) {
+ setResourceDataInResponse(rlist, rsList);
+
+ for (ResourceData rd : rlist) {
+ if (!"Success".equals(rd.status)) {
+ log.info("Capacity not found for: " + sd.resourceEntityType + "::" + sd.resourceEntityId);
+ return AllocationStatus.ResourceNotFound;
+ }
+ }
+ }
+
+ return AllocationStatus.Success;
+ }
+
+ private void setResourceDataInResponse(List<ResourceData> rlist, List<ResourceResponse> rsList) {
+ for (ResourceData rd : emptyIfNull(rlist)) {
+ ResourceResponse res = new ResourceResponse();
+ res.resourceName = rd.resourceName;
+ res.endPointPosition = rd.endPointPosition;
+ res.resourceTargetId = rd.resourceTargetId;
+ res.resourceTargetType = rd.resourceTargetType;
+ res.status = rd.status;
+ if (rd.data != null && !rd.data.isEmpty()) {
+ for (String kk : rd.data.keySet()) {
+ if ("allocated".equalsIgnoreCase(kk)) {
+ res.resourceAllocated = String.valueOf(rd.data.get(kk));
+ }
+
+ if ("used".equalsIgnoreCase(kk)) {
+ res.resourceUsed = String.valueOf(rd.data.get(kk));
+ }
+
+ if ("available".equalsIgnoreCase(kk)) {
+ res.resourceAvailable = String.valueOf(rd.data.get(kk));
+ }
+
+ if ("limit".equalsIgnoreCase(kk)) {
+ res.resourceLimit = String.valueOf(rd.data.get(kk));
+ }
+
+ }
+ }
+ rsList.add(res);
+ }
+
+ }
+
+ public static <T> Iterable<T> emptyIfNull(Iterable<T> iterable) {
+ return iterable == null ? Collections.<T>emptyList() : iterable;
+ }
+
+ private void setAttr(SvcLogicContext ctx, String name, String value) {
+ ctx.setAttribute(name, value);
+ log.info("Added context attr: " + name + ": " + value);
+ }
+
+ private ResourceEntity getResourceEntityData(SvcLogicContext ctx) throws SvcLogicException {
+ ResourceEntity sd = new ResourceEntity();
+ sd.resourceEntityId = getParam(ctx,
+ new String[] {"service-instance-id", "resource-entity-id", "reservation-entity-id"}, true, null);
+ sd.resourceEntityType =
+ getParam(ctx, new String[] {"reservation-entity-type", "resource-entity-type"}, true, null);
+ sd.resourceEntityVersion =
+ getParam(ctx, new String[] {"reservation-entity-version", "resource-entity-version"}, false, "1");
+ sd.data = getDataParam(ctx, "reservation-entity-data", "resource-entity-data", "service-data");
+ return sd;
+ }
+
+ private ResourceTarget getResourceTargetData(SvcLogicContext ctx) throws SvcLogicException {
+ ResourceTarget sd = new ResourceTarget();
+ sd.resourceTargetId = getParam(ctx, new String[] {"reservation-target-id", "resource-target-id"}, true, null);
+ sd.resourceTargetType =
+ getParam(ctx, new String[] {"reservation-target-type", "resource-target-type"}, true, null);
+ sd.data = getDataParam(ctx, "reservation-target-data", "resource-target-data", "equipment-data");
+ return sd;
+ }
+
+ private ResourceRequest getResourceRequest(SvcLogicContext ctx) throws SvcLogicException {
+ ResourceRequest rr = new ResourceRequest();
+ rr.resourceName = getParam(ctx, "resource-name", false, null);
+ rr.resourceShareGroup = getParam(ctx, "resource-share-group", false, null);
+ rr.rangeRequestedNumbers = getParam(ctx, "range-requested-numbers", false, null);
+ rr.rangeExcludeNumbers = getParam(ctx, "range-exclude-numbers", false, null);
+ String rangeReverseOrderStr = getParam(ctx, "range-reverse-order", false, "false");
+ rr.rangeReverseOrder = Boolean.parseBoolean(rangeReverseOrderStr);
+ String rangeMinOverrideStr = getParam(ctx, "range-min-override", false, "-1");
+ rr.rangeMinOverride = Integer.parseInt(rangeMinOverrideStr);
+ String rangeMaxOverrideStr = getParam(ctx, "range-max-override", false, "-1");
+ rr.rangeMaxOverride = Integer.parseInt(rangeMaxOverrideStr);
+ String rangeForceNewNumbersStr = getParam(ctx, "range-force-new-numbers", false, "false");
+ rr.rangeForceNewNumbers = Boolean.parseBoolean(rangeForceNewNumbersStr);
+ String rangeNextInSequenceStr = getParam(ctx, "range-next-in-sequence", false, "false");
+ rr.rangeNextInSequence = Boolean.parseBoolean(rangeNextInSequenceStr);
+ String replaceStr = getParam(ctx, "replace", false, "true");
+ rr.replace = Boolean.parseBoolean(replaceStr);
+ rr.applicationId = getParam(ctx, "application-id", false, "SDNC");
+ rr.endPointPosition = getParam(ctx, "endpoint-position", false, null);
+ return rr;
+ }
+
+ private String getParam(SvcLogicContext ctx, String name, boolean required, String def) throws SvcLogicException {
+ String v = null;
+ for (String p : INPUT_PREFIX) {
+ v = ctx.getAttribute(p + name);
+ if (v != null && v.trim().length() > 0) {
+ log.info("Param: " + name + ": " + v.trim());
+ return v.trim();
+ }
+ }
+ if (required) {
+ throw new SvcLogicException("The following variable is required in DG context: " + name);
+ }
+
+ log.info("Param: " + name + " not supplied. Using default: " + def);
+ return def;
+ }
+
+ private String getParam(SvcLogicContext ctx, String[] names, boolean required, String def)
+ throws SvcLogicException {
+ String v = null;
+ for (String name : names) {
+ v = getParam(ctx, name, false, def);
+ if (v != null) {
+ return v;
+ }
+ }
+ if (required) {
+ throw new SvcLogicException(
+ "One of the following variable is required in DG context: " + Arrays.deepToString(names));
+ }
+
+ log.info("Param: " + Arrays.deepToString(names) + " not supplied. Using default: " + def);
+ return def;
+ }
+
+ private Map<String, String> getDataParam(SvcLogicContext ctx, String... names) {
+ Map<String, String> data = new HashMap<>();
+ Set<String> ctxNames = ctx.getAttributeKeySet();
+ for (String n : ctxNames) {
+ for (String p : INPUT_PREFIX) {
+ for (String name : names) {
+ String pp = p + name + '.';
+ if (n.startsWith(pp)) {
+ String nn = n.substring(pp.length());
+ String vv = ctx.getAttribute(n);
+ data.put(nn, vv);
+
+ log.info("Data param: " + nn + ": " + vv);
+
+ if (ctxNames.contains(n + "-unit")) {
+ try {
+ long v = Long.parseLong(vv);
+ String unit = ctx.getAttribute(n + "-unit");
+ long kbps = speedUtil.convertToKbps(v, unit);
+ long mbps = speedUtil.convertToMbps(v, unit);
+ data.put(nn + "-kbps", String.valueOf(kbps));
+ data.put(nn + "-mbps", String.valueOf(mbps));
+
+ log.info("Data param: " + nn + "-kbps: " + kbps);
+ log.info("Data param: " + nn + "-mbps: " + mbps);
+
+ } catch (Exception e) {
+ log.warn("Invalid number for " + n + ": " + vv);
+ }
+ }
+ }
+ }
+ }
+ }
+ return data;
+ }
+
+ @SuppressWarnings("unchecked")
+ public static Map<String, String> dataToProperties(Map<String, Object> data) {
+ if (data == null || data.isEmpty()) {
+ return Collections.emptyMap();
+ }
+
+ Map<String, String> prop = new HashMap<>();
+ Map<String, Object> data1 = new HashMap<>(data);
+
+ while (!data1.isEmpty()) {
+ for (String key : new ArrayList<>(data1.keySet())) {
+ Object o = data1.get(key);
+ data1.remove(key);
+
+ if (o instanceof Boolean || o instanceof Number || o instanceof String) {
+ prop.put(key, o.toString());
+ } else if (o instanceof Map) {
+ Map<String, Object> mm = (Map<String, Object>) o;
+ for (String key1 : mm.keySet()) {
+ data1.put(key + "." + key1, mm.get(key1));
+ }
+ } else if (o instanceof List) {
+ List<Object> ll = (List<Object>) o;
+ prop.put(key + "_length", String.valueOf(ll.size()));
+ for (int i = 0; i < ll.size(); i++) {
+ data1.put(key + '[' + i + ']', ll.get(i));
+ }
+ }
+ }
+ }
+ return prop;
+ }
+
+ public void setResourceManager(ResourceManager resourceManager) {
+ this.resourceManager = resourceManager;
+ }
+
+ public void setEndPointAllocator(EndPointAllocator endPointAllocator) {
+ this.endPointAllocator = endPointAllocator;
+ }
+
+ public void setSpeedUtil(SpeedUtil speedUtil) {
+ this.speedUtil = speedUtil;
+ }
+}
diff --git a/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/ra/ResourceLockNode.java b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/ra/ResourceLockNode.java
new file mode 100644
index 000000000..a7d4b0e27
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/ra/ResourceLockNode.java
@@ -0,0 +1,101 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.ra;
+
+import java.security.SecureRandom;
+import java.util.Map;
+import org.onap.ccsdk.sli.adaptors.lock.comp.LockHelper;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.core.sli.SvcLogicJavaPlugin;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ResourceLockNode implements SvcLogicJavaPlugin {
+
+ private static final Logger log = LoggerFactory.getLogger(ResourceLockNode.class);
+
+ private LockHelper lockHelper;
+
+ public void setLockHelper(LockHelper lockHelper) {
+ this.lockHelper = lockHelper;
+ }
+
+ public void lockResource(Map<String, String> paramMap, SvcLogicContext ctx) throws SvcLogicException {
+ String resourceName = getParam(paramMap, "resource-name", true, null);
+ String lockRequester = getParam(paramMap, "lock-requester", false, generateLockRequester());
+ String lockTimeoutStr = getParam(paramMap, "lock-timeout", false, "600"); // Default lock timeout: 10 min
+ int lockTimeout = Integer.parseInt(lockTimeoutStr);
+ String lockWaitStr = getParam(paramMap, "lock-wait", false, "5"); // Time waiting before next retry. Default: 5 sec
+ int lockWait = Integer.parseInt(lockWaitStr);
+ String lockRetryCountStr = getParam(paramMap, "lock-retry-count", false, "10"); // Default: 10 retries
+ int lockRetryCount = Integer.parseInt(lockRetryCountStr);
+
+ lockHelper.lock(resourceName, lockRequester, lockTimeout, lockWait, lockRetryCount);
+ }
+
+ public void unlockResource(Map<String, String> paramMap, SvcLogicContext ctx) throws SvcLogicException {
+ String resourceName = getParam(paramMap, "resource-name", true, null);
+
+ lockHelper.unlock(resourceName, false);
+ }
+
+ public void lockResource(String resourceName, String lockRequester, int lockTimeout /* sec */) {
+ lockResource(resourceName, lockRequester, lockTimeout, 5, 10);
+ }
+
+ public void lockResource(String resourceName, String lockRequester, int lockTimeout /* sec */, int lockWait /* Seconds */, int retryCount) {
+ if (lockRequester == null) {
+ lockRequester = generateLockRequester();
+ }
+ if (lockTimeout <= 0) {
+ lockTimeout = 600;
+ }
+
+ lockHelper.lock(resourceName, lockRequester, lockTimeout, lockWait, retryCount);
+ }
+
+ public void unlockResource(String resourceName) {
+ lockHelper.unlock(resourceName, false);
+ }
+
+ private String getParam(Map<String, String> paramMap, String name, boolean required, String def)
+ throws SvcLogicException {
+ String v = paramMap.get(name);
+ if (v != null && v.trim().length() > 0) {
+ log.info("Param: " + name + ": " + v.trim());
+ return v.trim();
+ }
+ if (required) {
+ throw new SvcLogicException("The following node parameter is required: " + name);
+ }
+
+ log.info("Param: " + name + " not supplied. Using default: " + def);
+ return def;
+ }
+
+ private static String generateLockRequester() {
+ SecureRandom rand = new SecureRandom();
+ return "SynchronizedFunction-" + (int) (rand.nextDouble() * 1000000);
+ }
+}
+
diff --git a/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/ra/alloc/DbAllocationRule.java b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/ra/alloc/DbAllocationRule.java
new file mode 100644
index 000000000..d15b1508f
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/ra/alloc/DbAllocationRule.java
@@ -0,0 +1,256 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.ra.alloc;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import org.onap.ccsdk.sli.adaptors.ra.comp.AllocationRule;
+import org.onap.ccsdk.sli.adaptors.ra.comp.ResourceEntity;
+import org.onap.ccsdk.sli.adaptors.ra.comp.ResourceRequest;
+import org.onap.ccsdk.sli.adaptors.ra.comp.ResourceTarget;
+import org.onap.ccsdk.sli.adaptors.ra.rule.dao.RangeRuleDao;
+import org.onap.ccsdk.sli.adaptors.ra.rule.dao.ResourceRuleDao;
+import org.onap.ccsdk.sli.adaptors.ra.rule.data.RangeRule;
+import org.onap.ccsdk.sli.adaptors.ra.rule.data.ResourceRule;
+import org.onap.ccsdk.sli.adaptors.rm.data.AllocationAction;
+import org.onap.ccsdk.sli.adaptors.rm.data.AllocationRequest;
+import org.onap.ccsdk.sli.adaptors.rm.data.LimitAllocationRequest;
+import org.onap.ccsdk.sli.adaptors.rm.data.MultiResourceAllocationRequest;
+import org.onap.ccsdk.sli.adaptors.rm.data.Range;
+import org.onap.ccsdk.sli.adaptors.rm.data.RangeAllocationRequest;
+import org.onap.ccsdk.sli.adaptors.rm.data.ResourceType;
+import org.onap.ccsdk.sli.adaptors.util.expr.ExpressionEvaluator;
+import org.onap.ccsdk.sli.adaptors.util.str.StrUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class DbAllocationRule implements AllocationRule {
+
+ private static final Logger log = LoggerFactory.getLogger(DbAllocationRule.class);
+
+ private ResourceRuleDao resourceRuleDao;
+ private RangeRuleDao rangeRuleDao;
+
+ @Override
+ public AllocationRequest buildAllocationRequest(String serviceModel, ResourceEntity resourceEntity,
+ ResourceTarget resourceTarget, ResourceRequest resourceRequest, boolean checkOnly, boolean change) {
+ List<ResourceRule> resourceRuleList = resourceRuleDao.getResourceRules(serviceModel,
+ resourceTarget.resourceTargetType);
+ List<RangeRule> rangeRuleList = rangeRuleDao.getRangeRules(serviceModel, resourceTarget.resourceTargetType);
+
+ List<AllocationRequest> arlist = new ArrayList<>();
+
+ for (ResourceRule rr : resourceRuleList) {
+ if (resourceRequest.resourceName != null && !resourceRequest.resourceName.equals(rr.resourceName)) {
+ continue;
+ }
+
+ boolean matches = ExpressionEvaluator.evalBoolean(rr.serviceExpression, resourceEntity.data);
+ matches = matches && ExpressionEvaluator.evalBoolean(rr.equipmentExpression, resourceTarget.data);
+
+ if (matches) {
+ AllocationRequest ar1 = buildAllocationRequest(rr, resourceEntity, resourceTarget, resourceRequest,
+ checkOnly, change);
+ arlist.add(ar1);
+ }
+ }
+
+ for (RangeRule rr : rangeRuleList) {
+ if (resourceRequest.resourceName != null && !resourceRequest.resourceName.equals(rr.rangeName)) {
+ continue;
+ }
+ if (resourceRequest.endPointPosition != null
+ && !resourceRequest.endPointPosition.equals(rr.endPointPosition)) {
+ continue;
+ }
+
+ if (!ExpressionEvaluator.evalBoolean(rr.equipmentExpression, resourceTarget.data)) {
+ continue;
+ }
+
+ AllocationRequest ar1 = buildAllocationRequest(rr, resourceEntity, resourceTarget, resourceRequest,
+ checkOnly, change);
+ arlist.add(ar1);
+ }
+
+ if ((rangeRuleList == null || rangeRuleList.isEmpty())
+ && ResourceType.Range.equals(resourceRequest.resourceType)) {
+ AllocationRequest ar1 = buildAllocationRequest(resourceEntity, resourceTarget, resourceRequest, checkOnly,
+ change);
+ arlist.add(ar1);
+ }
+
+ if (arlist.isEmpty()) {
+ return null;
+ }
+
+ if (arlist.size() == 1) {
+ return arlist.get(0);
+ }
+
+ MultiResourceAllocationRequest ar = new MultiResourceAllocationRequest();
+ ar.stopOnFirstFailure = false;
+ ar.allocationRequestList = arlist;
+ return ar;
+ }
+
+ private AllocationRequest buildAllocationRequest(ResourceEntity resourceEntity, ResourceTarget resourceTarget,
+ ResourceRequest resourceRequest, boolean checkOnly, boolean change) {
+
+ RangeAllocationRequest ar = new RangeAllocationRequest();
+ ar.applicationId = resourceRequest.applicationId;
+ if (resourceRequest.endPointPosition != null) {
+ ar.resourceUnionId = resourceEntity.resourceEntityType + "::" + resourceEntity.resourceEntityId + "::"
+ + resourceRequest.endPointPosition;
+ ar.endPointPosition = resourceRequest.endPointPosition;
+ } else {
+ ar.resourceUnionId = resourceEntity.resourceEntityType + "::" + resourceEntity.resourceEntityId;
+ }
+ ar.resourceSetId = ar.resourceUnionId + "::" + resourceEntity.resourceEntityVersion;
+ ar.resourceName = resourceRequest.resourceName;
+ if (resourceRequest.resourceShareGroup != null) {
+ ar.resourceShareGroupList = Collections.singleton(resourceRequest.resourceShareGroup);
+ }
+ ar.assetId = resourceTarget.resourceTargetType + "::" + resourceTarget.resourceTargetId;
+ ar.requestedNumbers = StrUtil.listInt(resourceRequest.rangeRequestedNumbers,
+ "Invalid value for requested-numbers");
+ if (ar.requestedNumbers != null) {
+ ar.requestedCount = ar.requestedNumbers.size();
+ }
+ ar.excludeNumbers = StrUtil.listInt(resourceRequest.rangeExcludeNumbers, "Invalid value for exclude-numbers");
+ ar.reverseOrder = resourceRequest.rangeReverseOrder;
+ ar.missingResourceAction = AllocationAction.Succeed_Allocate;
+ ar.expiredResourceAction = AllocationAction.Succeed_Allocate;
+ ar.replace = resourceRequest.replace;
+ ar.check = true;
+ ar.allocate = !checkOnly;
+ ar.rangeList = resourceRequest.rangeOverrideList;
+ if (ar.rangeList == null || ar.rangeList.isEmpty()) {
+ if (resourceRequest.rangeMinOverride >= 0
+ && resourceRequest.rangeMaxOverride >= resourceRequest.rangeMinOverride) {
+ ar.rangeList = new ArrayList<>();
+ Range range = new Range();
+ range.min = resourceRequest.rangeMinOverride;
+ range.max = resourceRequest.rangeMaxOverride;
+ ar.rangeList.add(range);
+ }
+ } else {
+ if (resourceRequest.rangeMinOverride >= 0) {
+ ar.rangeList.get(0).min = resourceRequest.rangeMinOverride;
+ }
+ if (resourceRequest.rangeMaxOverride >= 0) {
+ ar.rangeList.get(ar.rangeList.size() - 1).max = resourceRequest.rangeMaxOverride;
+ }
+ }
+ ar.forceNewNumbers = resourceRequest.rangeForceNewNumbers;
+ StrUtil.info(log, ar);
+ return ar;
+ }
+
+ private AllocationRequest buildAllocationRequest(ResourceRule resourceRule, ResourceEntity resourceEntity,
+ ResourceTarget resourceTarget, ResourceRequest resourceRequest, boolean checkOnly, boolean change) {
+ StrUtil.info(log, resourceRule);
+
+ LimitAllocationRequest ar = new LimitAllocationRequest();
+ ar.applicationId = resourceRequest.applicationId;
+ ar.resourceUnionId = resourceEntity.resourceEntityType + "::" + resourceEntity.resourceEntityId;
+ ar.resourceSetId = ar.resourceUnionId + "::" + resourceEntity.resourceEntityVersion;
+ ar.resourceName = resourceRule.resourceName;
+ if (resourceRequest.resourceShareGroup != null) {
+ ar.resourceShareGroupList = Collections.singleton(resourceRequest.resourceShareGroup);
+ }
+ ar.assetId = resourceTarget.resourceTargetType + "::" + resourceTarget.resourceTargetId;
+ ar.missingResourceAction = AllocationAction.Succeed_Allocate;
+ ar.expiredResourceAction = AllocationAction.Succeed_Allocate;
+ ar.replace = resourceRequest.replace;
+ ar.strict = false;
+ ar.checkLimit = ExpressionEvaluator.evalLong(
+ change ? resourceRule.hardLimitExpression : resourceRule.softLimitExpression, resourceTarget.data);
+ ar.checkCount = ExpressionEvaluator.evalLong(resourceRule.allocationExpression, resourceEntity.data);
+ ar.allocateCount = checkOnly ? 0 : ar.checkCount;
+ return ar;
+ }
+
+ private AllocationRequest buildAllocationRequest(RangeRule rangeRule, ResourceEntity resourceEntity,
+ ResourceTarget resourceTarget, ResourceRequest resourceRequest, boolean checkOnly, boolean change) {
+ StrUtil.info(log, rangeRule);
+
+ RangeAllocationRequest ar = new RangeAllocationRequest();
+ ar.applicationId = resourceRequest.applicationId;
+ if (resourceRequest.endPointPosition != null) {
+ ar.resourceUnionId = resourceEntity.resourceEntityType + "::" + resourceEntity.resourceEntityId + "::"
+ + resourceRequest.endPointPosition;
+ ar.endPointPosition = resourceRequest.endPointPosition;
+ } else {
+ ar.resourceUnionId = resourceEntity.resourceEntityType + "::" + resourceEntity.resourceEntityId;
+ }
+ ar.resourceSetId = ar.resourceUnionId + "::" + resourceEntity.resourceEntityVersion;
+ ar.resourceName = rangeRule.rangeName;
+ if (resourceRequest.resourceShareGroup != null) {
+ ar.resourceShareGroupList = Collections.singleton(resourceRequest.resourceShareGroup);
+ }
+ ar.assetId = resourceTarget.resourceTargetType + "::" + resourceTarget.resourceTargetId;
+ ar.requestedNumbers = StrUtil.listInt(resourceRequest.rangeRequestedNumbers,
+ "Invalid value for requested-numbers");
+ if (ar.requestedNumbers != null) {
+ ar.requestedCount = ar.requestedNumbers.size();
+ }
+ ar.excludeNumbers = StrUtil.listInt(resourceRequest.rangeExcludeNumbers, "Invalid value for exclude-numbers");
+ ar.reverseOrder = resourceRequest.rangeReverseOrder;
+ ar.missingResourceAction = AllocationAction.Succeed_Allocate;
+ ar.expiredResourceAction = AllocationAction.Succeed_Allocate;
+ ar.replace = resourceRequest.replace;
+ ar.check = true;
+ ar.allocate = !checkOnly;
+ ar.rangeList = rangeRule.rangeList;
+ if (ar.rangeList == null || ar.rangeList.isEmpty()) {
+ if (resourceRequest.rangeMinOverride >= 0
+ && resourceRequest.rangeMaxOverride >= resourceRequest.rangeMinOverride) {
+ ar.rangeList = new ArrayList<>();
+ Range range = new Range();
+ range.min = resourceRequest.rangeMinOverride;
+ range.max = resourceRequest.rangeMaxOverride;
+ ar.rangeList.add(range);
+ }
+ } else {
+ if (resourceRequest.rangeMinOverride >= 0) {
+ ar.rangeList.get(0).min = resourceRequest.rangeMinOverride;
+ }
+ if (resourceRequest.rangeMaxOverride >= 0) {
+ ar.rangeList.get(ar.rangeList.size() - 1).max = resourceRequest.rangeMaxOverride;
+ }
+
+ }
+ ar.forceNewNumbers = resourceRequest.rangeForceNewNumbers;
+ ar.nextInSequence = resourceRequest.rangeNextInSequence;
+ return ar;
+ }
+
+ public void setResourceRuleDao(ResourceRuleDao resourceRuleDao) {
+ this.resourceRuleDao = resourceRuleDao;
+ }
+
+ public void setRangeRuleDao(RangeRuleDao rangeRuleDao) {
+ this.rangeRuleDao = rangeRuleDao;
+ }
+} \ No newline at end of file
diff --git a/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/ra/comp/AllocationData.java b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/ra/comp/AllocationData.java
new file mode 100644
index 000000000..3e0e6b140
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/ra/comp/AllocationData.java
@@ -0,0 +1,11 @@
+package org.onap.ccsdk.sli.adaptors.ra.comp;
+
+import java.util.Map;
+
+public class AllocationData {
+
+ public String resourceEntityType;
+ public String resourceEntityId;
+ public String resourceEntityVersion;
+ public Map<String, String> data;
+}
diff --git a/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/ra/comp/AllocationRule.java b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/ra/comp/AllocationRule.java
new file mode 100644
index 000000000..0e9737419
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/ra/comp/AllocationRule.java
@@ -0,0 +1,30 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.ra.comp;
+
+import org.onap.ccsdk.sli.adaptors.rm.data.AllocationRequest;
+
+public interface AllocationRule {
+
+ AllocationRequest buildAllocationRequest(String serviceModel, ResourceEntity resourceEntity,
+ ResourceTarget resourceTarget, ResourceRequest resourceRequest, boolean checkOnly, boolean change);
+}
diff --git a/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/ra/comp/EndPointAllocator.java b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/ra/comp/EndPointAllocator.java
new file mode 100644
index 000000000..abfb8d44f
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/ra/comp/EndPointAllocator.java
@@ -0,0 +1,39 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.ra.comp;
+
+import java.util.List;
+
+public interface EndPointAllocator {
+
+ List<ResourceData> allocateResources(String serviceModel, ResourceEntity resourceEntity,
+ ResourceTarget resourceTarget, ResourceRequest resourceRequest, boolean checkOnly, boolean change);
+
+ List<ResourceData> getResourcesForEntity(String resourceEntityType, String resourceEntityId,
+ String resourceEntityVersion);
+
+ ResourceData getResource(String resourceTargetType, String resourceTargetId, String resourceName,
+ String resourceEntityTypeFilter, String resourceEntityIdFilter, String resourceShareGroupFilter);
+
+ List<ResourceData> getResourcesForTarget(String resourceTargetTypeFilter, String resourceTargetIdFilter,
+ String resourceName);
+}
diff --git a/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/ra/comp/EndPointAllocatorImpl.java b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/ra/comp/EndPointAllocatorImpl.java
new file mode 100644
index 000000000..36e40d589
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/ra/comp/EndPointAllocatorImpl.java
@@ -0,0 +1,368 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ *
+ * Modifications Copyright (C) 2019 IBM.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.ra.comp;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.onap.ccsdk.sli.adaptors.rm.comp.ResourceManager;
+import org.onap.ccsdk.sli.adaptors.rm.data.AllocationItem;
+import org.onap.ccsdk.sli.adaptors.rm.data.AllocationOutcome;
+import org.onap.ccsdk.sli.adaptors.rm.data.AllocationRequest;
+import org.onap.ccsdk.sli.adaptors.rm.data.AllocationStatus;
+import org.onap.ccsdk.sli.adaptors.rm.data.LimitAllocationItem;
+import org.onap.ccsdk.sli.adaptors.rm.data.LimitAllocationOutcome;
+import org.onap.ccsdk.sli.adaptors.rm.data.LimitResource;
+import org.onap.ccsdk.sli.adaptors.rm.data.MultiResourceAllocationOutcome;
+import org.onap.ccsdk.sli.adaptors.rm.data.Range;
+import org.onap.ccsdk.sli.adaptors.rm.data.RangeAllocationItem;
+import org.onap.ccsdk.sli.adaptors.rm.data.RangeAllocationOutcome;
+import org.onap.ccsdk.sli.adaptors.rm.data.RangeAllocationRequest;
+import org.onap.ccsdk.sli.adaptors.rm.data.RangeResource;
+import org.onap.ccsdk.sli.adaptors.rm.data.ReleaseRequest;
+import org.onap.ccsdk.sli.adaptors.rm.data.Resource;
+import org.onap.ccsdk.sli.adaptors.util.str.StrUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class EndPointAllocatorImpl implements EndPointAllocator {
+
+ private static final Logger log = LoggerFactory.getLogger(EndPointAllocatorImpl.class);
+
+ private ResourceManager resourceManager;
+
+ private Map<String, List<AllocationRule>> allocationRuleMap;
+
+ @Override
+ public List<ResourceData> allocateResources(String serviceModel, ResourceEntity resourceEntity,
+ ResourceTarget resourceTarget, ResourceRequest resourceRequest, boolean checkOnly, boolean change) {
+
+ List<ResourceData> resourceList = new ArrayList<>();
+
+ if (allocationRuleMap != null) {
+ List<AllocationRule> allocationRuleList = allocationRuleMap.get(serviceModel);
+ if (allocationRuleList == null) {
+ allocationRuleList = allocationRuleMap.get("DEFAULT");
+ }
+
+ if (allocationRuleList != null) {
+ boolean allgood = true;
+ for (AllocationRule allocationRule : allocationRuleList) {
+ AllocationRequest ar = allocationRule.buildAllocationRequest(serviceModel, resourceEntity,
+ resourceTarget, resourceRequest, checkOnly, change);
+ if (ar != null) {
+ AllocationOutcome ao = resourceManager.allocateResources(ar);
+ List<ResourceData> rr = getResourceData(ao);
+ resourceList.addAll(rr);
+
+ if (ao.status != AllocationStatus.Success) {
+ allgood = false;
+ }
+ }
+ }
+
+ if (!allgood) {
+ String resourceSetId = resourceEntity.resourceEntityType + "::" + resourceEntity.resourceEntityId
+ + "::" + resourceEntity.resourceEntityVersion;
+ resourceManager.releaseResources(ReleaseRequest.resourceSet(resourceSetId));
+ }
+ }
+ }
+
+ return resourceList;
+ }
+
+ private List<ResourceData> getResourceData(AllocationOutcome ao) {
+ if (ao instanceof MultiResourceAllocationOutcome) {
+ List<ResourceData> rr = new ArrayList<>();
+ for (AllocationOutcome ao1 : ((MultiResourceAllocationOutcome) ao).allocationOutcomeList) {
+ rr.addAll(getResourceData(ao1));
+ }
+ return rr;
+ }
+
+ ResourceData rd = new ResourceData();
+ rd.data = new HashMap<>();
+
+ AllocationRequest ar = ao.request;
+ rd.resourceName = ar.resourceName;
+ rd.endPointPosition = ar.endPointPosition;
+ int i1 = ar.assetId.indexOf("::");
+ if (i1 > 0) {
+ rd.resourceTargetType = ar.assetId.substring(0, i1);
+ rd.resourceTargetId = ar.assetId.substring(i1 + 2);
+ } else {
+ rd.resourceTargetType = "";
+ rd.resourceTargetId = ar.assetId;
+ }
+ rd.status = ao.status.toString();
+
+ if (ao instanceof LimitAllocationOutcome) {
+ LimitAllocationOutcome lao = (LimitAllocationOutcome) ao;
+ rd.data.put("allocated", String.valueOf(lao.allocatedCount));
+ rd.data.put("used", String.valueOf(lao.used));
+ rd.data.put("limit", String.valueOf(lao.limit));
+ rd.data.put("available", String.valueOf(lao.limit - lao.used));
+ } else if (ao instanceof RangeAllocationOutcome) {
+ RangeAllocationOutcome rao = (RangeAllocationOutcome) ao;
+ rd.data.put("allocated", String.valueOf(StrUtil.listInt(rao.allocated)));
+ rd.data.put("used", String.valueOf(StrUtil.listInt(rao.used)));
+ List<Range> rangeList = ((RangeAllocationRequest) rao.request).rangeList;
+ if (rangeList != null && !rangeList.isEmpty()) {
+ List<Object> ll = new ArrayList<>();
+ for (Range r : rangeList) {
+ Map<String, Object> mm = new HashMap<>();
+ mm.put("min", r.min);
+ mm.put("max", r.max);
+ ll.add(mm);
+ }
+ rd.data.put("range-list", ll);
+ }
+ }
+
+ return Collections.singletonList(rd);
+ }
+
+ @Override
+ public List<ResourceData> getResourcesForEntity(String resourceEntityType, String resourceEntityId,
+ String resourceEntityVersion) {
+ List<ResourceData> rdlist = new ArrayList<>();
+
+ String resourceUnionId = resourceEntityType + "::" + resourceEntityId;
+ List<Resource> rlist = resourceManager.getResourceUnion(resourceUnionId);
+
+ for (Resource r : rlist) {
+
+ // Find the needed allocation item: if resourceEntityVersion is specified, use that,
+ // otherwise, find the latest allocation item
+ AllocationItem ai = null;
+ if (resourceEntityVersion != null) {
+ String resourceSetId = resourceUnionId + "::" + resourceEntityVersion;
+ for (AllocationItem ai1 : r.allocationItems) {
+ if (ai1.resourceSetId.equals(resourceSetId)) {
+ ai = ai1;
+ break;
+ }
+ }
+ } else {
+ Date aitime = null;
+ for (AllocationItem ai1 : r.allocationItems) {
+ if (ai1.resourceUnionId.equals(resourceUnionId)) {
+ if (aitime == null || ai1.allocationTime.after(aitime)) {
+ ai = ai1;
+ aitime = ai1.allocationTime;
+ }
+ }
+ }
+ }
+
+ if (ai != null) {
+ ResourceData rd = new ResourceData();
+ rdlist.add(rd);
+
+ rd.resourceName = r.resourceKey.resourceName;
+ int i1 = r.resourceKey.assetId.indexOf("::");
+ if (i1 > 0) {
+ rd.resourceTargetType = r.resourceKey.assetId.substring(0, i1);
+ rd.resourceTargetId = r.resourceKey.assetId.substring(i1 + 2);
+
+ int i2 = r.resourceKey.assetId.lastIndexOf("::");
+ if (i2 > i1) {
+ rd.resourceTargetValue = r.resourceKey.assetId.substring(i2 + 2);
+ }
+ } else {
+ rd.resourceTargetType = "";
+ rd.resourceTargetId = r.resourceKey.assetId;
+ }
+
+ rd.data = new HashMap<>();
+
+ if (ai instanceof RangeAllocationItem) {
+ RangeAllocationItem rai = (RangeAllocationItem) ai;
+
+ String ss = String.valueOf(rai.used);
+ ss = ss.substring(1, ss.length() - 1);
+ rd.data.put("allocated", ss);
+
+ } else if (ai instanceof LimitAllocationItem) {
+ LimitAllocationItem lai = (LimitAllocationItem) ai;
+
+ rd.data.put("allocated", String.valueOf(lai.used));
+ }
+ }
+ }
+
+ return rdlist;
+ }
+
+ @Override
+ public List<ResourceData> getResourcesForTarget(String resourceTargetTypeFilter, String resourceTargetIdFilter,
+ String resourceName) {
+ List<ResourceData> rdlist = new ArrayList<>();
+
+ String assetIdFilter = null;
+ if (resourceTargetTypeFilter != null && resourceTargetIdFilter != null) {
+ assetIdFilter = resourceTargetTypeFilter + "::" + resourceTargetIdFilter;
+ } else if (resourceTargetTypeFilter != null) {
+ assetIdFilter = resourceTargetTypeFilter;
+ } else if (resourceTargetIdFilter != null) {
+ assetIdFilter = resourceTargetIdFilter;
+ }
+
+ List<Resource> rlist = resourceManager.queryResources(resourceName, assetIdFilter);
+
+ for (Resource r : rlist) {
+ if (r.allocationItems == null || r.allocationItems.isEmpty()) {
+ continue;
+ }
+
+ log.info("ResourceName:" + r.resourceKey.resourceName + " assetId:" + r.resourceKey.assetId);
+
+
+ rdlist.add(getResourceData(r));
+ }
+
+ return rdlist;
+ }
+
+ @Override
+ public ResourceData getResource(String resourceTargetType, String resourceTargetId, String resourceName,
+ String resourceEntityTypeFilter, String resourceEntityIdFilter, String resourceShareGroupFilter) {
+ String assetId = resourceTargetType + "::" + resourceTargetId;
+
+ String resourceUnionFilter = null;
+ if (resourceEntityTypeFilter != null && resourceEntityIdFilter != null) {
+ resourceUnionFilter = resourceEntityTypeFilter + "::" + resourceEntityIdFilter;
+ } else if (resourceEntityTypeFilter != null) {
+ resourceUnionFilter = resourceEntityTypeFilter;
+ } else if (resourceEntityIdFilter != null) {
+ resourceUnionFilter = resourceEntityIdFilter;
+ }
+
+ Resource r = null;
+ if (resourceUnionFilter != null || resourceShareGroupFilter != null) {
+ r = resourceManager.queryResource(resourceName, assetId, resourceUnionFilter, resourceShareGroupFilter);
+ } else {
+ r = resourceManager.getResource(resourceName, assetId);
+ }
+
+ if (r != null && r.allocationItems != null && !r.allocationItems.isEmpty()) {
+ log.info("ResourceName:" + r.resourceKey.resourceName + " assetId:" + r.resourceKey.assetId);
+ return getResourceData(r);
+ }
+
+ return null;
+ }
+
+ private ResourceData getResourceData(Resource r) {
+ ResourceData rd = new ResourceData();
+
+ rd.resourceName = r.resourceKey.resourceName;
+ int i1 = r.resourceKey.assetId.indexOf("::");
+ if (i1 > 0) {
+ rd.resourceTargetType = r.resourceKey.assetId.substring(0, i1);
+ rd.resourceTargetId = r.resourceKey.assetId.substring(i1 + 2);
+
+ int i2 = r.resourceKey.assetId.lastIndexOf("::");
+ if (i2 > i1) {
+ rd.resourceTargetValue = r.resourceKey.assetId.substring(i2 + 2);
+ }
+ } else {
+ rd.resourceTargetType = "";
+ rd.resourceTargetId = r.resourceKey.assetId;
+ }
+
+ rd.data = new HashMap<>();
+
+ if (r instanceof RangeResource) {
+ RangeResource rr = (RangeResource) r;
+
+ log.info("rr.used: " + rr.used);
+ String ss = String.valueOf(rr.used);
+ ss = ss.substring(1, ss.length() - 1);
+ rd.data.put("allocated", ss);
+
+ } else if (r instanceof LimitResource) {
+ LimitResource lr = (LimitResource) r;
+
+ log.info("lr.used: " + lr.used);
+ rd.data.put("allocated", String.valueOf(lr.used));
+ }
+
+ rd.allocationDataList = new ArrayList<>();
+
+ if (r.allocationItems != null) {
+ for (AllocationItem ai : r.allocationItems) {
+ AllocationData ad = new AllocationData();
+ rd.allocationDataList.add(ad);
+
+ i1 = ai.resourceUnionId.indexOf("::");
+ if (i1 > 0) {
+ ad.resourceEntityType = ai.resourceUnionId.substring(0, i1);
+ ad.resourceEntityId = ai.resourceUnionId.substring(i1 + 2);
+ } else {
+ ad.resourceEntityType = "";
+ ad.resourceEntityId = ai.resourceUnionId;
+ }
+
+ i1 = ai.resourceSetId.lastIndexOf("::");
+ if (i1 > 0) {
+ ad.resourceEntityVersion = ai.resourceSetId.substring(i1 + 2);
+ } else {
+ ad.resourceEntityVersion = "";
+ }
+
+ ad.data = new HashMap<>();
+
+ if (ai instanceof RangeAllocationItem) {
+ RangeAllocationItem rai = (RangeAllocationItem) ai;
+
+ log.info("rr.used: " + rai.used);
+ String ss = String.valueOf(rai.used);
+ ss = ss.substring(1, ss.length() - 1);
+ ad.data.put("allocated", ss);
+
+ } else if (ai instanceof LimitAllocationItem) {
+ LimitAllocationItem lai = (LimitAllocationItem) ai;
+
+ log.info("lr.used: " + lai.used);
+ ad.data.put("allocated", String.valueOf(lai.used));
+ }
+ }
+ }
+
+ return rd;
+ }
+
+ public void setResourceManager(ResourceManager resourceManager) {
+ this.resourceManager = resourceManager;
+ }
+
+ public void setAllocationRuleMap(Map<String, List<AllocationRule>> allocationRuleMap) {
+ this.allocationRuleMap = allocationRuleMap;
+ }
+}
diff --git a/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/ra/comp/ResourceData.java b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/ra/comp/ResourceData.java
new file mode 100644
index 000000000..d83d4cdb4
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/ra/comp/ResourceData.java
@@ -0,0 +1,37 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.ra.comp;
+
+import java.util.List;
+import java.util.Map;
+
+public class ResourceData {
+
+ public String resourceName;
+ public String resourceTargetId;
+ public String resourceTargetValue;
+ public String resourceTargetType;
+ public String endPointPosition;
+ public String status;
+ public Map<String, Object> data;
+ public List<AllocationData> allocationDataList;
+}
diff --git a/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/ra/comp/ResourceEntity.java b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/ra/comp/ResourceEntity.java
new file mode 100644
index 000000000..12fb695b7
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/ra/comp/ResourceEntity.java
@@ -0,0 +1,32 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.ra.comp;
+
+import java.util.Map;
+
+public class ResourceEntity {
+
+ public String resourceEntityId;
+ public String resourceEntityVersion;
+ public String resourceEntityType;
+ public Map<String, String> data;
+}
diff --git a/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/ra/comp/ResourceRequest.java b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/ra/comp/ResourceRequest.java
new file mode 100644
index 000000000..2ebad4c89
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/ra/comp/ResourceRequest.java
@@ -0,0 +1,54 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.ra.comp;
+
+import java.util.List;
+import org.onap.ccsdk.sli.adaptors.rm.data.Range;
+import org.onap.ccsdk.sli.adaptors.rm.data.ResourceType;
+
+public class ResourceRequest {
+
+ public String resourceName;
+ public String resourceShareGroup;
+ public String rangeRequestedNumbers;
+ public String rangeExcludeNumbers;
+ public boolean rangeReverseOrder;
+ public int rangeMinOverride;
+ public int rangeMaxOverride;
+ public boolean rangeForceNewNumbers;
+ public boolean rangeNextInSequence;
+ public boolean replace;
+ public String requestType;
+ public String serviceModel;
+ public boolean checkOnly;
+ public String applicationId;
+ public String endPointPosition;
+ public ResourceType resourceType;
+ public List<Range> rangeOverrideList;
+ public String resourceEntityTypeFilter;
+ public String resourceEntityIdFilter;
+ public String resourceShareGroupFilter;
+ public String resourceTargetTypeFilter;
+ public String resourceTargetIdFilter;
+ public String rangeReleaseNumbers;
+ public int limitReleaseAmount;
+}
diff --git a/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/ra/comp/ResourceResponse.java b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/ra/comp/ResourceResponse.java
new file mode 100644
index 000000000..989333c3e
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/ra/comp/ResourceResponse.java
@@ -0,0 +1,13 @@
+package org.onap.ccsdk.sli.adaptors.ra.comp;
+
+public class ResourceResponse {
+ public String resourceName;
+ public String endPointPosition;
+ public String resourceTargetType;
+ public String resourceTargetId;
+ public String resourceLimit;
+ public String resourceAvailable;
+ public String resourceUsed;
+ public String resourceAllocated;
+ public String status;
+}
diff --git a/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/ra/comp/ResourceTarget.java b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/ra/comp/ResourceTarget.java
new file mode 100644
index 000000000..95cec330a
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/ra/comp/ResourceTarget.java
@@ -0,0 +1,31 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.ra.comp;
+
+import java.util.Map;
+
+public class ResourceTarget {
+
+ public String resourceTargetId;
+ public String resourceTargetType;
+ public Map<String, String> data;
+}
diff --git a/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/ra/rule/dao/RangeRuleDao.java b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/ra/rule/dao/RangeRuleDao.java
new file mode 100644
index 000000000..a7fcb61f2
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/ra/rule/dao/RangeRuleDao.java
@@ -0,0 +1,30 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.ra.rule.dao;
+
+import java.util.List;
+import org.onap.ccsdk.sli.adaptors.ra.rule.data.RangeRule;
+
+public interface RangeRuleDao {
+
+ List<RangeRule> getRangeRules(String serviceModel, String equipLevel);
+}
diff --git a/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/ra/rule/dao/RangeRuleDaoImpl.java b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/ra/rule/dao/RangeRuleDaoImpl.java
new file mode 100644
index 000000000..b021620ba
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/ra/rule/dao/RangeRuleDaoImpl.java
@@ -0,0 +1,87 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.ra.rule.dao;
+
+import java.util.ArrayList;
+import java.util.List;
+import org.onap.ccsdk.sli.adaptors.ra.rule.data.RangeRule;
+import org.onap.ccsdk.sli.adaptors.rm.data.Range;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.core.RowMapper;
+
+public class RangeRuleDaoImpl implements RangeRuleDao {
+
+ private static final Logger log = LoggerFactory.getLogger(RangeRuleDaoImpl.class);
+
+ private static final String GET_SQL = "SELECT * FROM RANGE_RULE WHERE service_model = ? AND equipment_level = ?";
+
+ private JdbcTemplate jdbcTemplate;
+
+ @Override
+ public List<RangeRule> getRangeRules(String serviceModel, String equipLevel) {
+ return jdbcTemplate.query(GET_SQL, new Object[] { serviceModel, equipLevel },
+ (RowMapper<RangeRule>) (rs, rowNum) -> {
+ RangeRule rl = new RangeRule();
+ rl.id = rs.getLong("range_rule_id");
+ rl.rangeName = rs.getString("range_name");
+ rl.serviceModel = rs.getString("service_model");
+ rl.endPointPosition = rs.getString("end_point_position");
+ rl.equipmentLevel = rs.getString("equipment_level");
+ rl.equipmentExpression = rs.getString("equipment_expression");
+
+ String rangesStr = rs.getString("ranges");
+ String[] ranges = rangesStr.split(",");
+ rl.rangeList = new ArrayList<>();
+ for (String rangeStr : ranges) {
+ Range range = new Range();
+ String[] nn = rangeStr.split("-");
+ if (nn.length >= 1) {
+ try {
+ range.min = range.max = Integer.parseInt(nn[0]);
+ } catch (NumberFormatException e) {
+ log.warn("Invalid value found in DB for range: " + rangeStr, e);
+ }
+ }
+ if (nn.length >= 2) {
+ try {
+ range.max = Integer.parseInt(nn[1]);
+ } catch (NumberFormatException e) {
+ log.warn("Invalid value found in DB for range: " + rangeStr, e);
+ }
+ }
+ if (nn.length > 2) {
+ log.warn("Invalid value found in DB for range: {}", rangeStr);
+ }
+ rl.rangeList.add(range);
+ }
+
+ return rl;
+ });
+
+ }
+
+ public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
+ this.jdbcTemplate = jdbcTemplate;
+ }
+} \ No newline at end of file
diff --git a/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/ra/rule/dao/ResourceRuleDao.java b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/ra/rule/dao/ResourceRuleDao.java
new file mode 100644
index 000000000..54fdcbc20
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/ra/rule/dao/ResourceRuleDao.java
@@ -0,0 +1,32 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.ra.rule.dao;
+
+import java.util.List;
+import org.onap.ccsdk.sli.adaptors.ra.rule.data.ResourceRule;
+
+public interface ResourceRuleDao {
+
+ List<ResourceRule> getResourceRules(String serviceModel, String equipLevel);
+
+ ResourceRule getResourceRule(String serviceModel, String endPointPosition, String equipLevel, String resourceName);
+}
diff --git a/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/ra/rule/dao/ResourceRuleDaoImpl.java b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/ra/rule/dao/ResourceRuleDaoImpl.java
new file mode 100644
index 000000000..451dc57cd
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/ra/rule/dao/ResourceRuleDaoImpl.java
@@ -0,0 +1,110 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.ra.rule.dao;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.List;
+import org.onap.ccsdk.sli.adaptors.ra.rule.data.ResourceRule;
+import org.onap.ccsdk.sli.adaptors.ra.rule.data.ResourceThreshold;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.core.RowMapper;
+
+public class ResourceRuleDaoImpl implements ResourceRuleDao {
+
+ @SuppressWarnings("unused")
+ private static final Logger log = LoggerFactory.getLogger(ResourceRuleDaoImpl.class);
+
+ private static final String GET1_SQL =
+ "SELECT * FROM RESOURCE_RULE WHERE service_model = ? AND equipment_level = ?";
+ private static final String GET2_SQL =
+ "SELECT * FROM RESOURCE_RULE WHERE service_model = ? AND end_point_position = ? AND equipment_level = ? AND resource_name = ?";
+ private static final String THRESHOLD_SQL = "SELECT * FROM RESOURCE_THRESHOLD WHERE resource_rule_id = ?";
+
+ private JdbcTemplate jdbcTemplate;
+ ResourceRuleRowMapper resourceRuleRowMapper = new ResourceRuleRowMapper();
+ ResourceThresholdRowMapper resourceThresholdRowMapper = new ResourceThresholdRowMapper();
+
+ @Override
+ public List<ResourceRule> getResourceRules(String serviceModel, String equipLevel) {
+ List<ResourceRule> resourceRuleList =
+ jdbcTemplate.query(GET1_SQL, new Object[] {serviceModel, equipLevel}, resourceRuleRowMapper);
+
+ for (ResourceRule rr : resourceRuleList) {
+ rr.thresholdList = jdbcTemplate.query(THRESHOLD_SQL, new Object[] {rr.id}, resourceThresholdRowMapper);
+ }
+
+ return resourceRuleList;
+ }
+
+ @Override
+ public ResourceRule getResourceRule(String serviceModel, String endPointPosition, String equipLevel,
+ String resourceName) {
+ List<ResourceRule> resourceRuleList = jdbcTemplate.query(GET2_SQL,
+ new Object[] {serviceModel, endPointPosition, equipLevel, resourceName}, resourceRuleRowMapper);
+
+ if (resourceRuleList == null || resourceRuleList.isEmpty()) {
+ return null;
+ }
+
+ ResourceRule rr = resourceRuleList.get(0);
+ rr.thresholdList = jdbcTemplate.query(THRESHOLD_SQL, new Object[] {rr.id}, resourceThresholdRowMapper);
+
+ return rr;
+ }
+
+ private static class ResourceRuleRowMapper implements RowMapper<ResourceRule> {
+
+ @Override
+ public ResourceRule mapRow(ResultSet rs, int rowNum) throws SQLException {
+ ResourceRule rl = new ResourceRule();
+ rl.id = rs.getLong("resource_rule_id");
+ rl.resourceName = rs.getString("resource_name");
+ rl.serviceModel = rs.getString("service_model");
+ rl.endPointPosition = rs.getString("end_point_position");
+ rl.serviceExpression = rs.getString("service_expression");
+ rl.equipmentLevel = rs.getString("equipment_level");
+ rl.equipmentExpression = rs.getString("equipment_expression");
+ rl.allocationExpression = rs.getString("allocation_expression");
+ rl.softLimitExpression = rs.getString("soft_limit_expression");
+ rl.hardLimitExpression = rs.getString("hard_limit_expression");
+ return rl;
+ }
+ }
+
+ private static class ResourceThresholdRowMapper implements RowMapper<ResourceThreshold> {
+
+ @Override
+ public ResourceThreshold mapRow(ResultSet rs, int rowNum) throws SQLException {
+ ResourceThreshold th = new ResourceThreshold();
+ th.expression = rs.getString("threshold_expression");
+ th.message = rs.getString("threshold_message");
+ return th;
+ }
+ }
+
+ public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
+ this.jdbcTemplate = jdbcTemplate;
+ }
+}
diff --git a/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/ra/rule/data/RangeRule.java b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/ra/rule/data/RangeRule.java
new file mode 100644
index 000000000..c1ccd8196
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/ra/rule/data/RangeRule.java
@@ -0,0 +1,36 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.ra.rule.data;
+
+import java.util.List;
+import org.onap.ccsdk.sli.adaptors.rm.data.Range;
+
+public class RangeRule {
+
+ public long id;
+ public String rangeName;
+ public String serviceModel;
+ public String endPointPosition;
+ public String equipmentLevel;
+ public String equipmentExpression;
+ public List<Range> rangeList;
+}
diff --git a/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/ra/rule/data/ResourceRule.java b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/ra/rule/data/ResourceRule.java
new file mode 100644
index 000000000..17e0196b2
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/ra/rule/data/ResourceRule.java
@@ -0,0 +1,39 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.ra.rule.data;
+
+import java.util.List;
+
+public class ResourceRule {
+
+ public long id;
+ public String resourceName;
+ public String serviceModel;
+ public String endPointPosition;
+ public String serviceExpression;
+ public String equipmentLevel;
+ public String equipmentExpression;
+ public String allocationExpression;
+ public String softLimitExpression;
+ public String hardLimitExpression;
+ public List<ResourceThreshold> thresholdList;
+}
diff --git a/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/ra/rule/data/ResourceThreshold.java b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/ra/rule/data/ResourceThreshold.java
new file mode 100644
index 000000000..3f07d9f6b
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/ra/rule/data/ResourceThreshold.java
@@ -0,0 +1,28 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.ra.rule.data;
+
+public class ResourceThreshold {
+
+ public String expression;
+ public String message;
+}
diff --git a/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/ra/rule/data/ThresholdStatus.java b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/ra/rule/data/ThresholdStatus.java
new file mode 100644
index 000000000..5bc8d3450
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/ra/rule/data/ThresholdStatus.java
@@ -0,0 +1,32 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.ra.rule.data;
+
+public class ThresholdStatus {
+
+ public ResourceRule resourceRule;
+ public ResourceThreshold resourceThreshold;
+ public long limitValue;
+ public long thresholdValue;
+ public long used;
+ public long lastAdded;
+}
diff --git a/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/comp/AllocationFunction.java b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/comp/AllocationFunction.java
new file mode 100644
index 000000000..485010656
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/comp/AllocationFunction.java
@@ -0,0 +1,433 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Modifications Copyright (C) 2018 IBM.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.rm.comp;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
+import org.onap.ccsdk.sli.adaptors.lock.comp.LockHelper;
+import org.onap.ccsdk.sli.adaptors.lock.comp.ResourceLockedException;
+import org.onap.ccsdk.sli.adaptors.lock.comp.SynchronizedFunction;
+import org.onap.ccsdk.sli.adaptors.rm.dao.ResourceDao;
+import org.onap.ccsdk.sli.adaptors.rm.data.AllocationOutcome;
+import org.onap.ccsdk.sli.adaptors.rm.data.AllocationRequest;
+import org.onap.ccsdk.sli.adaptors.rm.data.AllocationStatus;
+import org.onap.ccsdk.sli.adaptors.rm.data.LabelAllocationOutcome;
+import org.onap.ccsdk.sli.adaptors.rm.data.LabelAllocationRequest;
+import org.onap.ccsdk.sli.adaptors.rm.data.LabelResource;
+import org.onap.ccsdk.sli.adaptors.rm.data.LimitAllocationOutcome;
+import org.onap.ccsdk.sli.adaptors.rm.data.LimitAllocationRequest;
+import org.onap.ccsdk.sli.adaptors.rm.data.LimitResource;
+import org.onap.ccsdk.sli.adaptors.rm.data.MultiAssetAllocationOutcome;
+import org.onap.ccsdk.sli.adaptors.rm.data.MultiAssetAllocationRequest;
+import org.onap.ccsdk.sli.adaptors.rm.data.MultiResourceAllocationOutcome;
+import org.onap.ccsdk.sli.adaptors.rm.data.MultiResourceAllocationRequest;
+import org.onap.ccsdk.sli.adaptors.rm.data.Range;
+import org.onap.ccsdk.sli.adaptors.rm.data.RangeAllocationOutcome;
+import org.onap.ccsdk.sli.adaptors.rm.data.RangeAllocationRequest;
+import org.onap.ccsdk.sli.adaptors.rm.data.RangeResource;
+import org.onap.ccsdk.sli.adaptors.rm.data.Resource;
+import org.onap.ccsdk.sli.adaptors.rm.data.ResourceKey;
+import org.onap.ccsdk.sli.adaptors.rm.data.ResourceType;
+import org.onap.ccsdk.sli.adaptors.rm.util.LabelUtil;
+import org.onap.ccsdk.sli.adaptors.rm.util.LimitUtil;
+import org.onap.ccsdk.sli.adaptors.rm.util.RangeUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+class AllocationFunction extends SynchronizedFunction {
+
+ @SuppressWarnings("unused")
+ private static final Logger log = LoggerFactory.getLogger(AllocationFunction.class);
+
+ private ResourceDao resourceDao;
+
+ private AllocationRequest request;
+ private AllocationOutcome outcome;
+
+ private List<Resource> updateList = new ArrayList<>();
+
+ public AllocationFunction(LockHelper lockHelper, ResourceDao resourceDao, AllocationRequest request,
+ int lockTimeout) {
+ super(lockHelper, getLockNames(request), lockTimeout);
+ this.resourceDao = resourceDao;
+ this.request = request;
+ }
+
+ private static Collection<String> getLockNames(AllocationRequest request) {
+ Set<String> lockResourceNames = new HashSet<>();
+ addLockNames(lockResourceNames, request);
+ return lockResourceNames;
+ }
+
+ private static void addLockNames(Set<String> lockResourceNames, AllocationRequest request) {
+ if (request instanceof MultiAssetAllocationRequest) {
+ MultiAssetAllocationRequest req = (MultiAssetAllocationRequest) request;
+ if (req.assetIdList != null) {
+ lockResourceNames.addAll(req.assetIdList);
+ }
+ } else if (request instanceof MultiResourceAllocationRequest) {
+ MultiResourceAllocationRequest req = (MultiResourceAllocationRequest) request;
+ if (req.allocationRequestList != null) {
+ for (AllocationRequest request1 : req.allocationRequestList) {
+ addLockNames(lockResourceNames, request1);
+ }
+ }
+ } else if (request.assetId != null) {
+ lockResourceNames.add(request.assetId);
+ }
+ }
+
+ @Override
+ public void _exec() throws ResourceLockedException {
+ outcome = allocate(request);
+
+ if (outcome!=null && outcome.status == AllocationStatus.Success) {
+ for (Resource r : updateList) {
+ resourceDao.saveResource(r);
+ }
+ }
+ }
+
+ private AllocationOutcome allocate(AllocationRequest allocationRequest) throws ResourceLockedException {
+ if (allocationRequest instanceof MultiAssetAllocationRequest) {
+ return allocateMultiAsset((MultiAssetAllocationRequest) allocationRequest);
+ }
+ if (allocationRequest instanceof MultiResourceAllocationRequest) {
+ return allocateMultiResource((MultiResourceAllocationRequest) allocationRequest);
+ }
+ if (allocationRequest instanceof LimitAllocationRequest) {
+ return allocateLimit((LimitAllocationRequest) allocationRequest);
+ }
+ if (allocationRequest instanceof LabelAllocationRequest) {
+ return allocateLabel((LabelAllocationRequest) allocationRequest);
+ }
+ if (allocationRequest instanceof RangeAllocationRequest) {
+ return allocateRange((RangeAllocationRequest) allocationRequest);
+ }
+ return null;
+ }
+
+ private MultiAssetAllocationOutcome allocateMultiAsset(MultiAssetAllocationRequest req) {
+
+ return null;
+ }
+
+ private MultiResourceAllocationOutcome allocateMultiResource(MultiResourceAllocationRequest req) {
+ MultiResourceAllocationOutcome out = new MultiResourceAllocationOutcome();
+ out.request = req;
+ out.allocationOutcomeList = new ArrayList<>();
+ out.status = AllocationStatus.Success;
+
+ if (req.allocationRequestList != null) {
+ for (AllocationRequest req1 : req.allocationRequestList) {
+ AllocationOutcome out1 = allocate(req1);
+ out.allocationOutcomeList.add(out1);
+ if (out1.status != AllocationStatus.Success) {
+ out.status = AllocationStatus.Failure;
+ }
+ }
+ }
+
+ return out;
+ }
+
+ private LimitAllocationOutcome allocateLimit(LimitAllocationRequest req) {
+ LimitAllocationOutcome out = new LimitAllocationOutcome();
+ out.request = req;
+
+ Resource r = resourceDao.getResource(req.assetId, req.resourceName);
+ if (r == null) {
+ r = new LimitResource();
+ r.resourceKey = new ResourceKey();
+ r.resourceKey.assetId = req.assetId;
+ r.resourceKey.resourceName = req.resourceName;
+ r.resourceType = ResourceType.Limit;
+ } else {
+ if (r.resourceType != ResourceType.Limit) {
+ out.status = AllocationStatus.ResourceNotFound;
+ return out;
+ }
+ LimitUtil.recalculate((LimitResource) r);
+ }
+
+ LimitResource l = (LimitResource) r;
+ if (LimitUtil.checkLimit(l, req)) {
+ out.status = AllocationStatus.Success;
+ if (req.allocateCount > 0) {
+ out.allocatedCount = LimitUtil.allocateLimit(l, req);
+ updateList.add(l);
+ }
+ } else {
+ out.status = AllocationStatus.Failure;
+ }
+
+ out.used = l.used;
+ out.limit = req.checkLimit;
+
+ return out;
+ }
+
+ private LabelAllocationOutcome allocateLabel(LabelAllocationRequest req) {
+ LabelAllocationOutcome out = new LabelAllocationOutcome();
+
+ out.request = req;
+
+ Resource r = resourceDao.getResource(req.assetId, req.resourceName);
+ if (r == null) {
+ r = new LabelResource();
+ r.resourceKey = new ResourceKey();
+ r.resourceKey.assetId = req.assetId;
+ r.resourceKey.resourceName = req.resourceName;
+ r.resourceType = ResourceType.Label;
+ } else {
+ if (r.resourceType != ResourceType.Label) {
+ out.status = AllocationStatus.ResourceNotFound;
+ return out;
+ }
+ LabelUtil.recalculate((LabelResource) r);
+ }
+
+ LabelResource l = (LabelResource) r;
+ if (LabelUtil.checkLabel(l, req)) {
+ out.status = AllocationStatus.Success;
+ out.currentLabel = l.label;
+ if (req.allocate) {
+ out.allocatedLabel = LabelUtil.allocateLabel(l, req);
+ updateList.add(l);
+ }
+ } else {
+ out.status = AllocationStatus.Failure;
+ }
+
+ return out;
+ }
+
+ private RangeAllocationOutcome allocateRange(RangeAllocationRequest req) {
+ RangeAllocationOutcome out = new RangeAllocationOutcome();
+
+ out.request = req;
+
+ Resource r = resourceDao.getResource(req.assetId, req.resourceName);
+ if (r == null) {
+ r = new RangeResource();
+ r.resourceKey = new ResourceKey();
+ r.resourceKey.assetId = req.assetId;
+ r.resourceKey.resourceName = req.resourceName;
+ r.resourceType = ResourceType.Range;
+ } else {
+ if (r.resourceType != ResourceType.Range) {
+ out.status = AllocationStatus.ResourceNotFound;
+ return out;
+ }
+ RangeUtil.recalculate((RangeResource) r);
+ }
+
+ RangeResource rr = (RangeResource) r;
+ SortedSet<Integer> foundNumbers = null;
+ if (!req.check) {
+ out.status = AllocationStatus.Success;
+ foundNumbers = req.requestedNumbers;
+ } else {
+ if (req.requestedNumbers != null && !req.requestedNumbers.isEmpty()) {
+ foundNumbers = req.requestedNumbers;
+ out.status = AllocationStatus.Success;
+ for (int n : foundNumbers) {
+ if (!RangeUtil.checkRange(rr, req, n)) {
+ out.status = AllocationStatus.Failure;
+ break;
+ }
+ }
+ } else {
+ foundNumbers = new TreeSet<>();
+ int foundCount = 0;
+
+ // First try to reuse the numbers already taken by the same resource union
+ SortedSet<Integer> uu = RangeUtil.getUsed(rr, req.resourceUnionId);
+ if (uu != null && !uu.isEmpty() && req.replace && !req.forceNewNumbers) {
+ if (uu.size() >= req.requestedCount) {
+ // Just take the first req.requestedCount numbers from uu
+ Iterator<Integer> i = uu.iterator();
+ while (foundCount < req.requestedCount) {
+ foundNumbers.add(i.next());
+ foundCount++;
+ }
+ } else {
+ // Additional numbers are requested. Try to find them starting from
+ // the minimum we have in uu (the first element) towards the min
+ // parameter, and then starting from the maximum in uu (the last
+ // element) towards the max parameter.
+ // NOTE: In case of request for sequential numbers, the parameters
+ // alignBlockSize and alignModulus are ignored. It would be harder
+ // to take them into account, and currently it is not needed.
+
+ // Request may contain multiple ranges. We will find the range from the request
+ // that contains the currently used numbers (the first one). We will only look
+ // for additional numbers in that range.
+
+ Range range = null;
+ if (req.rangeList != null) {
+ for (Range range1 : req.rangeList) {
+ if (uu.first() >= range1.min && uu.first() <= range1.max) {
+ range = range1;
+ break;
+ }
+ }
+ }
+
+ if (range != null) {
+ int uumin = uu.first() - 1;
+ int uumax = uu.last() + 1;
+ foundNumbers.addAll(uu);
+ foundCount = uu.size();
+ for (int n = uumin; foundCount < req.requestedCount && n >= range.min; n--) {
+ if (RangeUtil.checkRange(rr, req, n)) {
+ foundNumbers.add(n);
+ foundCount++;
+ } else if (req.sequential) {
+ break;
+ }
+ }
+ for (int n = uumax; foundCount < req.requestedCount && n <= range.max; n++) {
+ if (RangeUtil.checkRange(rr, req, n)) {
+ foundNumbers.add(n);
+ foundCount++;
+ } else if (req.sequential) {
+ break;
+ }
+ }
+ }
+
+ // If we could not find enough numbers trying to reuse currently
+ // allocated, reset foundNumbers and foundCount, continue with
+ // the normal allocation of new numbers.
+ if (foundCount < req.requestedCount) {
+ foundNumbers = new TreeSet<>();
+ foundCount = 0;
+ }
+ }
+ }
+
+ if (req.rangeList != null && !req.rangeList.isEmpty()) {
+ if (req.nextInSequence) {
+ // This means we allocate numbers in ascending sequence, not trying from the beginning
+ // of the range (leaving possible holes in the sequence of allocated numbers)
+ // To do that, we go through the ranges from the last towards the first (assuming
+ // ranges are ordered from smallest to the largest numbers), and within each range, from
+ // the max towards the min and find the first allocated number. Then we take the next numbers
+ // in the range (that we already checked are available).
+
+ int rangeIndex;
+ Range range = null;
+ int n = 0;
+ boolean foundAllocated = false;
+ for (rangeIndex = req.rangeList.size() - 1; !foundAllocated && rangeIndex >= 0; rangeIndex--) {
+ range = req.rangeList.get(rangeIndex);
+ for (n = range.max; n >= range.min; n--) {
+ if (!RangeUtil.checkRange(rr, req, n)) {
+ foundAllocated = true;
+ break;
+ }
+ }
+ if (foundAllocated) {
+ break;
+ }
+ }
+ n++;
+ for (; foundCount < req.requestedCount && n <= range.max; n++) {
+ foundNumbers.add(n);
+ foundCount++;
+ }
+ if (foundCount < req.requestedCount) {
+ rangeIndex++;
+ for (; rangeIndex < req.rangeList.size(); rangeIndex++) {
+ range = req.rangeList.get(rangeIndex);
+ for (n = range.min; foundCount < req.requestedCount && n <= range.max; n++) {
+ foundNumbers.add(n);
+ foundCount++;
+ }
+ }
+ }
+ // If we could not find enough numbers by going up in sequence,
+ // reset foundNumbers and foundCount, and go back to the holes
+ if (foundCount < req.requestedCount) {
+ foundNumbers = new TreeSet<>();
+ foundCount = 0;
+ }
+ }
+
+ if (req.reverseOrder) {
+ for (int i = req.rangeList.size() - 1; i >= 0; i--) {
+ Range range = req.rangeList.get(i);
+ for (int n = range.max; foundCount < req.requestedCount && n >= range.min; n--) {
+ if (RangeUtil.checkRange(rr, req, n)) {
+ foundNumbers.add(n);
+ foundCount++;
+ } else if (req.sequential) {
+ foundCount = 0;
+ }
+ }
+ }
+ } else {
+ for (Range range : req.rangeList) {
+ for (int n = range.min; foundCount < req.requestedCount && n <= range.max; n++) {
+ if (RangeUtil.checkRange(rr, req, n)) {
+ foundNumbers.add(n);
+ foundCount++;
+ } else if (req.sequential) {
+ foundCount = 0;
+ }
+ }
+ }
+ }
+ }
+
+ out.status = foundCount == req.requestedCount ? AllocationStatus.Success : AllocationStatus.Failure;
+ }
+ }
+
+ if (out.status == AllocationStatus.Success) {
+ out.allocated = foundNumbers;
+ if (req.allocate) {
+ RangeUtil.allocateRange(rr, out.allocated, req);
+ updateList.add(rr);
+ }
+ } else {
+ out.allocated = new TreeSet<>();
+ }
+
+ out.used = rr.used;
+
+ return out;
+ }
+
+ public AllocationOutcome getAllocationOutcome() {
+ return outcome;
+ }
+}
diff --git a/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/comp/ReleaseFunction.java b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/comp/ReleaseFunction.java
new file mode 100644
index 000000000..b466b164b
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/comp/ReleaseFunction.java
@@ -0,0 +1,149 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * Modifications Copyright © 2018 IBM.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.rm.comp;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+import org.onap.ccsdk.sli.adaptors.lock.comp.LockHelper;
+import org.onap.ccsdk.sli.adaptors.lock.comp.ResourceLockedException;
+import org.onap.ccsdk.sli.adaptors.lock.comp.SynchronizedFunction;
+import org.onap.ccsdk.sli.adaptors.rm.dao.ResourceDao;
+import org.onap.ccsdk.sli.adaptors.rm.data.AllocationItem;
+import org.onap.ccsdk.sli.adaptors.rm.data.LimitAllocationItem;
+import org.onap.ccsdk.sli.adaptors.rm.data.RangeAllocationItem;
+import org.onap.ccsdk.sli.adaptors.rm.data.ReleaseRequest;
+import org.onap.ccsdk.sli.adaptors.rm.data.Resource;
+import org.onap.ccsdk.sli.adaptors.rm.data.ResourceType;
+import org.onap.ccsdk.sli.adaptors.rm.util.ResourceUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+class ReleaseFunction extends SynchronizedFunction {
+
+ @SuppressWarnings("unused")
+ private static final Logger log = LoggerFactory.getLogger(ReleaseFunction.class);
+
+ private ResourceDao resourceDao;
+
+ private ReleaseRequest releaseRequest;
+
+ public ReleaseFunction(LockHelper lockHelper, ResourceDao resourceDao, ReleaseRequest releaseRequest,
+ Collection<String> lockNames, int lockTimeout) {
+ super(lockHelper, lockNames, lockTimeout);
+ this.resourceDao = resourceDao;
+ this.releaseRequest = releaseRequest;
+ }
+
+ @Override
+ public void _exec() throws ResourceLockedException {
+ List<Resource> resourceList = new ArrayList<>();
+ if (releaseRequest.assetId != null && releaseRequest.resourceName != null) {
+ Resource r = resourceDao.getResource(releaseRequest.assetId, releaseRequest.resourceName);
+ if (r != null) {
+ resourceList.add(r);
+ }
+ } else if (releaseRequest.assetId != null) {
+ if (releaseRequest.resourceSetId != null) {
+ resourceList = resourceDao.getResourceSetForAsset(releaseRequest.resourceSetId, releaseRequest.assetId);
+ } else {
+ resourceList =
+ resourceDao.getResourceUnionForAsset(releaseRequest.resourceUnionId, releaseRequest.assetId);
+ }
+ } else {
+ if (releaseRequest.resourceSetId != null) {
+ resourceList = resourceDao.getResourceSet(releaseRequest.resourceSetId);
+ } else {
+ resourceList = resourceDao.getResourceUnion(releaseRequest.resourceUnionId);
+ }
+ }
+
+ for (Resource r : resourceList) {
+ boolean updated = false;
+ if (r.allocationItems != null) {
+ Iterator<AllocationItem> i = r.allocationItems.iterator();
+ while (i.hasNext()) {
+ AllocationItem ai = i.next();
+ if (releaseRequest.resourceSetId != null) {
+
+ if (releaseRequest.resourceSetId.equals(ai.resourceSetId)) {
+ if (r.resourceType == ResourceType.Limit) {
+ LimitAllocationItem lai = (LimitAllocationItem) ai;
+ if (releaseRequest.releaseAmount > 0 && releaseRequest.releaseAmount < lai.used) {
+ lai.used -= releaseRequest.releaseAmount;
+ } else {
+ i.remove();
+ }
+ } else if (r.resourceType == ResourceType.Range) {
+ RangeAllocationItem rai = (RangeAllocationItem) ai;
+ if (releaseRequest.releaseNumbers != null && !releaseRequest.releaseNumbers.isEmpty()) {
+ rai.used.removeAll(releaseRequest.releaseNumbers);
+ if (rai.used.isEmpty()) {
+ i.remove();
+ }
+ } else {
+ i.remove();
+ }
+ } else {
+ i.remove();
+ }
+ updated = true;
+ }
+
+ } else if (releaseRequest.resourceUnionId != null) {
+
+ if (releaseRequest.resourceUnionId.equals(ai.resourceUnionId)) {
+ if (r.resourceType == ResourceType.Limit) {
+ LimitAllocationItem lai = (LimitAllocationItem) ai;
+ if (releaseRequest.releaseAmount > 0 && releaseRequest.releaseAmount < lai.used) {
+ lai.used -= releaseRequest.releaseAmount;
+ } else {
+ i.remove();
+ }
+ } else if (r.resourceType == ResourceType.Range) {
+ RangeAllocationItem rai = (RangeAllocationItem) ai;
+ if (releaseRequest.releaseNumbers != null && !releaseRequest.releaseNumbers.isEmpty()) {
+ rai.used.removeAll(releaseRequest.releaseNumbers);
+ if (rai.used.isEmpty()) {
+ i.remove();
+ }
+ } else {
+ i.remove();
+ }
+ } else {
+ i.remove();
+ }
+ updated = true;
+ }
+
+ }
+ }
+ }
+ if (updated) {
+ ResourceUtil.recalculate(r);
+ resourceDao.saveResource(r);
+ }
+ }
+ }
+}
diff --git a/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/comp/ResourceLoader.java b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/comp/ResourceLoader.java
new file mode 100644
index 000000000..2d4df68b5
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/comp/ResourceLoader.java
@@ -0,0 +1,39 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.rm.comp;
+
+import java.util.Collection;
+
+import org.onap.ccsdk.sli.adaptors.rm.data.Resource;
+
+public interface ResourceLoader {
+
+ void loadResource(String applicationId, Resource resource, boolean force);
+
+ void loadResources(String applicationId, Collection<Resource> resourceList, boolean force);
+
+ void loadResourcesForAsset(String applicationId, String assetId, Collection<Resource> resourceList, boolean force);
+
+ void deleteResource(String applicationId, String assetId, String resourceName);
+
+ void deleteResourcesForAsset(String applicationId, String assetId);
+}
diff --git a/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/comp/ResourceManager.java b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/comp/ResourceManager.java
new file mode 100644
index 000000000..9dd54cc39
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/comp/ResourceManager.java
@@ -0,0 +1,44 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.rm.comp;
+
+import java.util.List;
+import org.onap.ccsdk.sli.adaptors.rm.data.AllocationOutcome;
+import org.onap.ccsdk.sli.adaptors.rm.data.AllocationRequest;
+import org.onap.ccsdk.sli.adaptors.rm.data.ReleaseRequest;
+import org.onap.ccsdk.sli.adaptors.rm.data.Resource;
+
+public interface ResourceManager {
+
+ Resource getResource(String resourceName, String assetId);
+
+ List<Resource> getResourceUnion(String resourceUnionId);
+
+ AllocationOutcome allocateResources(AllocationRequest allocationRequest);
+
+ void releaseResources(ReleaseRequest releaseRequest);
+
+ Resource queryResource(String resourceName, String assetId, String resourceUnionFilter,
+ String resourceShareGroupFilter);
+
+ List<Resource> queryResources(String resourceName, String assetIdFilter);
+}
diff --git a/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/comp/ResourceManagerImpl.java b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/comp/ResourceManagerImpl.java
new file mode 100644
index 000000000..83da27071
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/comp/ResourceManagerImpl.java
@@ -0,0 +1,148 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.rm.comp;
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import org.onap.ccsdk.sli.adaptors.lock.comp.LockHelper;
+import org.onap.ccsdk.sli.adaptors.rm.dao.ResourceDao;
+import org.onap.ccsdk.sli.adaptors.rm.data.AllocationOutcome;
+import org.onap.ccsdk.sli.adaptors.rm.data.AllocationRequest;
+import org.onap.ccsdk.sli.adaptors.rm.data.ReleaseRequest;
+import org.onap.ccsdk.sli.adaptors.rm.data.Resource;
+import org.onap.ccsdk.sli.adaptors.rm.util.ResourceUtil;
+import org.onap.ccsdk.sli.adaptors.util.str.StrUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ResourceManagerImpl implements ResourceManager {
+
+ private static final Logger log = LoggerFactory.getLogger(ResourceManagerImpl.class);
+
+ private LockHelper lockHelper;
+ private ResourceDao resourceDao;
+
+ private int lockTimeout = 10 * 60; // Default 10 min
+
+ public ResourceManagerImpl() {
+ log.info("ResourceManager created.");
+ }
+
+ @Override
+ public Resource getResource(String resourceName, String assetId) {
+ Resource r = resourceDao.getResource(assetId, resourceName);
+ ResourceUtil.recalculate(r);
+ return r;
+ }
+
+ @Override
+ public List<Resource> getResourceUnion(String resourceUnionId) {
+ List<Resource> rlist = resourceDao.getResourceUnion(resourceUnionId);
+ for (Resource r : rlist) {
+ ResourceUtil.recalculate(r);
+ }
+ return rlist;
+ }
+
+ @Override
+ public AllocationOutcome allocateResources(AllocationRequest allocationRequest) {
+ if (allocationRequest == null) {
+ throw new IllegalArgumentException("allocateResources called with null argument");
+ }
+
+ AllocationFunction allocationFunction =
+ new AllocationFunction(lockHelper, resourceDao, allocationRequest, lockTimeout);
+ allocationFunction.exec();
+ AllocationOutcome allocationOutcome = allocationFunction.getAllocationOutcome();
+
+ StrUtil.info(log, allocationOutcome);
+
+ return allocationOutcome;
+ }
+
+ @Override
+ public void releaseResources(ReleaseRequest releaseRequest) {
+ if (releaseRequest.resourceSetId == null && releaseRequest.resourceUnionId == null) {
+ return;
+ }
+
+ Set<String> lockNames = new HashSet<>();
+ if (releaseRequest.assetId != null) {
+ lockNames.add(releaseRequest.assetId);
+ } else {
+ List<Resource> resourceList = null;
+ if (releaseRequest.resourceSetId != null) {
+ resourceList = resourceDao.getResourceSet(releaseRequest.resourceSetId);
+ } else {
+ resourceList = resourceDao.getResourceUnion(releaseRequest.resourceUnionId);
+ }
+
+ if (resourceList == null || resourceList.isEmpty()) {
+ return;
+ }
+
+ lockNames = getLockNames(resourceList);
+ }
+
+ ReleaseFunction releaseFunction =
+ new ReleaseFunction(lockHelper, resourceDao, releaseRequest, lockNames, lockTimeout);
+ releaseFunction.exec();
+ }
+
+ @Override
+ public Resource queryResource(String resourceName, String assetId, String resourceUnionFilter,
+ String resourceShareGroupFilter) {
+ Resource r = resourceDao.query(assetId, resourceName, resourceUnionFilter, resourceShareGroupFilter);
+ ResourceUtil.recalculate(r);
+ return r;
+ }
+
+ @Override
+ public List<Resource> queryResources(String resourceName, String assetIdFilter) {
+ List<Resource> rlist = resourceDao.query(assetIdFilter, resourceName);
+ for (Resource r : rlist) {
+ ResourceUtil.recalculate(r);
+ }
+ return rlist;
+ }
+
+ private Set<String> getLockNames(List<Resource> resourceList) {
+ Set<String> lockNames = new HashSet<>();
+ for (Resource r : resourceList) {
+ lockNames.add(r.resourceKey.assetId);
+ }
+ return lockNames;
+ }
+
+ public void setResourceDao(ResourceDao resourceDao) {
+ this.resourceDao = resourceDao;
+ }
+
+ public void setLockTimeout(int lockTimeout) {
+ this.lockTimeout = lockTimeout;
+ }
+
+ public void setLockHelper(LockHelper lockHelper) {
+ this.lockHelper = lockHelper;
+ }
+}
diff --git a/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/dao/ResourceDao.java b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/dao/ResourceDao.java
new file mode 100644
index 000000000..87baf26c1
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/dao/ResourceDao.java
@@ -0,0 +1,46 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.rm.dao;
+
+import java.util.List;
+import org.onap.ccsdk.sli.adaptors.rm.data.Resource;
+
+public interface ResourceDao {
+
+ Resource getResource(String assetId, String resourceName);
+
+ void saveResource(Resource resource);
+
+ void deleteResource(String assetId, String resourceName);
+
+ List<Resource> getResourceSet(String resourceSetId);
+
+ List<Resource> getResourceUnion(String resourceUnionId);
+
+ List<Resource> getResourceSetForAsset(String resourceSetId, String assetId);
+
+ List<Resource> getResourceUnionForAsset(String resourceUnionId, String assetId);
+
+ Resource query(String assetId, String resourceName, String resourceUnionFilter, String resourceShareGroupFilter);
+
+ List<Resource> query(String assetIdFilter, String resourceName);
+}
diff --git a/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/dao/jdbc/AllocationItem.java b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/dao/jdbc/AllocationItem.java
new file mode 100644
index 000000000..25d8bf97e
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/dao/jdbc/AllocationItem.java
@@ -0,0 +1,37 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.rm.dao.jdbc;
+
+import java.util.Date;
+
+public class AllocationItem {
+
+ public long id;
+ public long resourceId;
+ public String applicationId;
+ public String resourceSetId, resourceUnionId;
+ public String resourceShareGroupList;
+ public long ltUsed;
+ public String llLabel;
+ public String rrUsed;
+ public Date allocationTime;
+}
diff --git a/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/dao/jdbc/AllocationItemJdbcDao.java b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/dao/jdbc/AllocationItemJdbcDao.java
new file mode 100644
index 000000000..8e3a12988
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/dao/jdbc/AllocationItemJdbcDao.java
@@ -0,0 +1,37 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.rm.dao.jdbc;
+
+import java.util.List;
+
+public interface AllocationItemJdbcDao {
+
+ void add(AllocationItem ai);
+
+ List<AllocationItem> getAllocationItems(long resourceId);
+
+ void update(AllocationItem ai);
+
+ void delete(long id);
+
+ List<AllocationItem> queryAllocationItems(long resourceId, String resourceUnionFilter, String resourceShareGroupFilter);
+}
diff --git a/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/dao/jdbc/AllocationItemJdbcDaoImpl.java b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/dao/jdbc/AllocationItemJdbcDaoImpl.java
new file mode 100644
index 000000000..2a62c63a3
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/dao/jdbc/AllocationItemJdbcDaoImpl.java
@@ -0,0 +1,146 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * Modifications Copyright © 2018 IBM.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.rm.dao.jdbc;
+
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Timestamp;
+import java.util.Collections;
+import java.util.List;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.core.PreparedStatementCreator;
+import org.springframework.jdbc.core.RowMapper;
+import org.springframework.jdbc.support.GeneratedKeyHolder;
+import org.springframework.jdbc.support.KeyHolder;
+
+public class AllocationItemJdbcDaoImpl implements AllocationItemJdbcDao {
+
+ @SuppressWarnings("unused")
+ private static final Logger log = LoggerFactory.getLogger(ResourceJdbcDaoImpl.class);
+
+ private static final String INSERT_SQL = "INSERT INTO ALLOCATION_ITEM (\n"
+ + " resource_id, application_id, resource_set_id, resource_union_id, resource_share_group_list,\n"
+ + " lt_used, ll_label, rr_used, allocation_time)\nVALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)";
+
+ private static final String UPDATE_SQL = "UPDATE ALLOCATION_ITEM SET\n"
+ + " resource_share_group_list = ?, lt_used = ?, ll_label = ?, rr_used = ?, allocation_time = ?\n"
+ + "WHERE allocation_item_id = ?";
+
+ private static final String DELETE_SQL = "DELETE FROM ALLOCATION_ITEM WHERE allocation_item_id = ?";
+
+ private static final String GET_SQL = "SELECT * FROM ALLOCATION_ITEM WHERE resource_id = ?";
+
+ private JdbcTemplate jdbcTemplate;
+ private AllocationItemRowMapper allocationItemRowMapper = new AllocationItemRowMapper();
+
+ @Override
+ public void add(final AllocationItem ai) {
+ PreparedStatementCreator psc = dbc -> {
+ PreparedStatement ps = dbc.prepareStatement(INSERT_SQL, new String[] { "allocation_item_id" });
+ ps.setLong(1, ai.resourceId);
+ ps.setString(2, ai.applicationId);
+ ps.setString(3, ai.resourceSetId);
+ ps.setString(4, ai.resourceUnionId);
+ ps.setString(5, ai.resourceShareGroupList);
+ ps.setLong(6, ai.ltUsed);
+ ps.setString(7, ai.llLabel);
+ ps.setString(8, ai.rrUsed);
+ ps.setTimestamp(9, new Timestamp(ai.allocationTime.getTime()));
+ return ps;
+ };
+ KeyHolder keyHolder = new GeneratedKeyHolder();
+ jdbcTemplate.update(psc, keyHolder);
+ ai.id = keyHolder.getKey().longValue();
+ }
+
+ @Override
+ public void update(AllocationItem ai) {
+ Long ltUsed = ai.ltUsed <= 0 ? null : ai.ltUsed;
+ jdbcTemplate.update(UPDATE_SQL, ai.resourceShareGroupList, ltUsed, ai.llLabel, ai.rrUsed, ai.allocationTime,
+ ai.id);
+ }
+
+ @Override
+ public void delete(long id) {
+ jdbcTemplate.update(DELETE_SQL, id);
+ }
+
+ @Override
+ public List<AllocationItem> getAllocationItems(long resourceId) {
+ if (resourceId <= 0) {
+ return Collections.emptyList();
+ }
+
+ return jdbcTemplate.query(GET_SQL, new Object[] { resourceId }, allocationItemRowMapper);
+ }
+
+ @Override
+ public List<AllocationItem> queryAllocationItems(long resourceId, String resourceUnionFilter,
+ String resourceShareGroupFilter) {
+ if (resourceId <= 0) {
+ return Collections.emptyList();
+ }
+
+ String sql = GET_SQL;
+
+ if (resourceUnionFilter != null) {
+ sql += " AND resource_union_id LIKE '" + resourceUnionFilter + "'";
+ }
+
+ if (resourceShareGroupFilter != null) {
+ if (("null").equalsIgnoreCase(resourceShareGroupFilter)) {
+ sql += " AND resource_share_group_list IS NULL";
+ } else {
+ sql += " AND resource_share_group_list LIKE '" + resourceShareGroupFilter + "'";
+ }
+ }
+
+ return jdbcTemplate.query(sql, new Object[] { resourceId }, allocationItemRowMapper);
+ }
+
+ private static class AllocationItemRowMapper implements RowMapper<AllocationItem> {
+
+ @Override
+ public AllocationItem mapRow(ResultSet rs, int n) throws SQLException {
+ AllocationItem ai = new AllocationItem();
+ ai.id = rs.getLong("allocation_item_id");
+ ai.resourceId = rs.getLong("resource_id");
+ ai.applicationId = rs.getString("application_id");
+ ai.resourceSetId = rs.getString("resource_set_id");
+ ai.resourceUnionId = rs.getString("resource_union_id");
+ ai.resourceShareGroupList = rs.getString("resource_share_group_list");
+ ai.ltUsed = rs.getLong("lt_used");
+ ai.llLabel = rs.getString("ll_label");
+ ai.rrUsed = rs.getString("rr_used");
+ ai.allocationTime = rs.getTimestamp("allocation_time");
+ return ai;
+ }
+ }
+
+ public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
+ this.jdbcTemplate = jdbcTemplate;
+ }
+}
diff --git a/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/dao/jdbc/Resource.java b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/dao/jdbc/Resource.java
new file mode 100644
index 000000000..6b764a7e1
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/dao/jdbc/Resource.java
@@ -0,0 +1,34 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.rm.dao.jdbc;
+
+public class Resource {
+
+ public long id;
+ public String assetId;
+ public String name;
+ public String type;
+ public long ltUsed;
+ public String llLabel;
+ public int llReferenceCount;
+ public String rrUsed;
+}
diff --git a/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/dao/jdbc/ResourceDaoImpl.java b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/dao/jdbc/ResourceDaoImpl.java
new file mode 100644
index 000000000..21f5575fc
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/dao/jdbc/ResourceDaoImpl.java
@@ -0,0 +1,462 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.rm.dao.jdbc;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import org.onap.ccsdk.sli.adaptors.rm.dao.ResourceDao;
+import org.onap.ccsdk.sli.adaptors.rm.data.LabelAllocationItem;
+import org.onap.ccsdk.sli.adaptors.rm.data.LabelResource;
+import org.onap.ccsdk.sli.adaptors.rm.data.LimitAllocationItem;
+import org.onap.ccsdk.sli.adaptors.rm.data.LimitResource;
+import org.onap.ccsdk.sli.adaptors.rm.data.RangeAllocationItem;
+import org.onap.ccsdk.sli.adaptors.rm.data.RangeResource;
+import org.onap.ccsdk.sli.adaptors.rm.data.ResourceKey;
+import org.onap.ccsdk.sli.adaptors.rm.data.ResourceType;
+import org.onap.ccsdk.sli.adaptors.util.str.StrUtil;
+
+public class ResourceDaoImpl implements ResourceDao {
+
+ private ResourceJdbcDao resourceJdbcDao;
+ private ResourceLoadJdbcDao resourceLoadJdbcDao;
+ private AllocationItemJdbcDao allocationItemJdbcDao;
+
+ @Override
+ public org.onap.ccsdk.sli.adaptors.rm.data.Resource getResource(String assetId, String resourceName) {
+ Resource rEntity = resourceJdbcDao.getResource(assetId, resourceName);
+ return createResourceWithItems(rEntity);
+ }
+
+ @Override
+ public org.onap.ccsdk.sli.adaptors.rm.data.Resource query(String assetId, String resourceName,
+ String resourceUnionFilter, String resourceShareGroupFilter) {
+ Resource rEntity = resourceJdbcDao.getResource(assetId, resourceName);
+ org.onap.ccsdk.sli.adaptors.rm.data.Resource r = createResource(rEntity);
+
+ if (r != null) {
+ List<AllocationItem> aiEntityList = allocationItemJdbcDao.queryAllocationItems(rEntity.id,
+ resourceUnionFilter, resourceShareGroupFilter);
+ r.allocationItems = new ArrayList<>();
+ for (AllocationItem aiEntity : aiEntityList) {
+ org.onap.ccsdk.sli.adaptors.rm.data.AllocationItem ai = createAllocationItem(r, aiEntity);
+ r.allocationItems.add(ai);
+ }
+
+ List<ResourceLoad> rlEntityList = resourceLoadJdbcDao.getResourceLoads(rEntity.id);
+ r.resourceLoadList = new ArrayList<>();
+ for (ResourceLoad rlEntity : rlEntityList) {
+ org.onap.ccsdk.sli.adaptors.rm.data.ResourceLoad rl = createResourceLoad(r, rlEntity);
+ r.resourceLoadList.add(rl);
+ }
+ }
+
+ return r;
+ }
+
+ @Override
+ public List<org.onap.ccsdk.sli.adaptors.rm.data.Resource> query(String assetIdFilter, String resourceName) {
+ List<Resource> rEntityList = resourceJdbcDao.queryResources(assetIdFilter, resourceName);
+ List<org.onap.ccsdk.sli.adaptors.rm.data.Resource> rlist = new ArrayList<>();
+ for (Resource rEntity : rEntityList) {
+ org.onap.ccsdk.sli.adaptors.rm.data.Resource r = createResourceWithItems(rEntity);
+ rlist.add(r);
+ }
+ return rlist;
+ }
+
+ @Override
+ public void saveResource(org.onap.ccsdk.sli.adaptors.rm.data.Resource resource) {
+ if (resource == null) {
+ return;
+ }
+
+ org.onap.ccsdk.sli.adaptors.rm.dao.jdbc.Resource resourceEntity =
+ resourceJdbcDao.getResource(resource.resourceKey.assetId, resource.resourceKey.resourceName);
+ if (resourceEntity == null) {
+ resourceEntity = createResourceEntity(resource);
+ resourceJdbcDao.add(resourceEntity);
+ if (resource.allocationItems != null) {
+ for (org.onap.ccsdk.sli.adaptors.rm.data.AllocationItem ai : resource.allocationItems) {
+ AllocationItem aiEntity = createAllocationItemEntity(resourceEntity.id, ai);
+ allocationItemJdbcDao.add(aiEntity);
+ }
+ }
+ if (resource.resourceLoadList != null) {
+ for (org.onap.ccsdk.sli.adaptors.rm.data.ResourceLoad rl : resource.resourceLoadList) {
+ ResourceLoad rlEntity = createResourceLoadEntity(resourceEntity.id, rl);
+ resourceLoadJdbcDao.add(rlEntity);
+ }
+ }
+ } else {
+ updateResourceEntity(resourceEntity, resource);
+ resourceJdbcDao.update(resourceEntity);
+
+ List<AllocationItem> oldAiEntityList = allocationItemJdbcDao.getAllocationItems(resourceEntity.id);
+ if (resource.allocationItems != null) {
+ for (org.onap.ccsdk.sli.adaptors.rm.data.AllocationItem newai : resource.allocationItems) {
+ AllocationItem foundAiEntity = null;
+ for (AllocationItem oldAiEntity : oldAiEntityList) {
+ if (oldAiEntity.resourceSetId.equals(newai.resourceSetId)) {
+ foundAiEntity = oldAiEntity;
+ break;
+ }
+ }
+ if (foundAiEntity != null) {
+ if (allocationItemChanged(foundAiEntity, newai)) {
+ updateAllocationItemEntity(foundAiEntity, newai);
+ allocationItemJdbcDao.update(foundAiEntity);
+ }
+ } else {
+ AllocationItem newAiEntity = createAllocationItemEntity(resourceEntity.id, newai);
+ allocationItemJdbcDao.add(newAiEntity);
+ }
+ }
+ }
+ for (AllocationItem oldAiEntity : oldAiEntityList) {
+ boolean found = false;
+ if (resource.allocationItems != null) {
+ for (org.onap.ccsdk.sli.adaptors.rm.data.AllocationItem newai : resource.allocationItems) {
+ if (oldAiEntity.resourceSetId.equals(newai.resourceSetId)) {
+ found = true;
+ break;
+ }
+ }
+ }
+ if (!found) {
+ allocationItemJdbcDao.delete(oldAiEntity.id);
+ }
+ }
+
+ List<ResourceLoad> oldRlEntityList = resourceLoadJdbcDao.getResourceLoads(resourceEntity.id);
+ if (resource.resourceLoadList != null) {
+ for (org.onap.ccsdk.sli.adaptors.rm.data.ResourceLoad newrl : resource.resourceLoadList) {
+ ResourceLoad foundRlEntity = null;
+ for (ResourceLoad oldRlEntity : oldRlEntityList) {
+ if (oldRlEntity.applicationId.equals(newrl.applicationId)) {
+ foundRlEntity = oldRlEntity;
+ break;
+ }
+ }
+ if (foundRlEntity != null) {
+ updateResourceLoadEntity(foundRlEntity, newrl);
+ resourceLoadJdbcDao.update(foundRlEntity);
+ } else {
+ ResourceLoad newRlEntity = createResourceLoadEntity(resourceEntity.id, newrl);
+ resourceLoadJdbcDao.add(newRlEntity);
+ }
+ }
+ }
+ for (ResourceLoad oldRlEntity : oldRlEntityList) {
+ boolean found = false;
+ if (resource.resourceLoadList != null) {
+ for (org.onap.ccsdk.sli.adaptors.rm.data.ResourceLoad newrl : resource.resourceLoadList) {
+ if (oldRlEntity.applicationId.equals(newrl.applicationId)) {
+ found = true;
+ break;
+ }
+ }
+ }
+ if (!found) {
+ resourceLoadJdbcDao.delete(oldRlEntity.id);
+ }
+ }
+ }
+ }
+
+ private boolean allocationItemChanged(AllocationItem aiEntity,
+ org.onap.ccsdk.sli.adaptors.rm.data.AllocationItem newai) {
+ String newShareGroupList = StrUtil.listStr(newai.resourceShareGroupList);
+ if (!eq(aiEntity.resourceShareGroupList, newShareGroupList)) {
+ return true;
+ }
+
+ if (newai.resourceType == ResourceType.Limit) {
+ if (aiEntity.ltUsed != ((LimitAllocationItem) newai).used) {
+ return true;
+ }
+ } else if (newai.resourceType == ResourceType.Label) {
+ if (!eq(aiEntity.llLabel, ((LabelAllocationItem) newai).label)) {
+ return true;
+ }
+ } else if (newai.resourceType == ResourceType.Range) {
+ String newRrUsed = StrUtil.listInt(((RangeAllocationItem) newai).used);
+ if (!eq(aiEntity.rrUsed, newRrUsed)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ @Override
+ public void deleteResource(String assetId, String resourceName) {
+ org.onap.ccsdk.sli.adaptors.rm.dao.jdbc.Resource resourceEntity =
+ resourceJdbcDao.getResource(assetId, resourceName);
+ if (resourceEntity != null) {
+ resourceJdbcDao.delete(resourceEntity.id);
+ }
+ }
+
+ @Override
+ public List<org.onap.ccsdk.sli.adaptors.rm.data.Resource> getResourceSet(String resourceSetId) {
+ List<Resource> rEntityList = resourceJdbcDao.getResourceSet(resourceSetId);
+ List<org.onap.ccsdk.sli.adaptors.rm.data.Resource> rlist = new ArrayList<>();
+ for (Resource rEntity : rEntityList) {
+ org.onap.ccsdk.sli.adaptors.rm.data.Resource r = createResourceWithItems(rEntity);
+ rlist.add(r);
+ }
+ return rlist;
+ }
+
+ @Override
+ public List<org.onap.ccsdk.sli.adaptors.rm.data.Resource> getResourceUnion(String resourceUnionId) {
+ List<Resource> rEntityList = resourceJdbcDao.getResourceUnion(resourceUnionId);
+ List<org.onap.ccsdk.sli.adaptors.rm.data.Resource> rlist = new ArrayList<>();
+ for (Resource rEntity : rEntityList) {
+ org.onap.ccsdk.sli.adaptors.rm.data.Resource r = createResourceWithItems(rEntity);
+ rlist.add(r);
+ }
+ return rlist;
+ }
+
+ @Override
+ public List<org.onap.ccsdk.sli.adaptors.rm.data.Resource> getResourceSetForAsset(String resourceSetId,
+ String assetId) {
+ List<Resource> rEntityList = resourceJdbcDao.getResourceSetForAsset(resourceSetId, assetId);
+ List<org.onap.ccsdk.sli.adaptors.rm.data.Resource> rlist = new ArrayList<>();
+ for (Resource rEntity : rEntityList) {
+ org.onap.ccsdk.sli.adaptors.rm.data.Resource r = createResourceWithItems(rEntity);
+ rlist.add(r);
+ }
+ return rlist;
+ }
+
+ @Override
+ public List<org.onap.ccsdk.sli.adaptors.rm.data.Resource> getResourceUnionForAsset(String resourceUnionId,
+ String assetId) {
+ List<Resource> rEntityList = resourceJdbcDao.getResourceUnionForAsset(resourceUnionId, assetId);
+ List<org.onap.ccsdk.sli.adaptors.rm.data.Resource> rlist = new ArrayList<>();
+ for (Resource rEntity : rEntityList) {
+ org.onap.ccsdk.sli.adaptors.rm.data.Resource r = createResourceWithItems(rEntity);
+ rlist.add(r);
+ }
+ return rlist;
+ }
+
+ private Resource createResourceEntity(org.onap.ccsdk.sli.adaptors.rm.data.Resource resource) {
+ Resource resourceEntity = new Resource();
+ resourceEntity.assetId = resource.resourceKey.assetId;
+ resourceEntity.name = resource.resourceKey.resourceName;
+ resourceEntity.type = resource.resourceType.toString();
+ if (resource.resourceType == ResourceType.Limit) {
+ resourceEntity.ltUsed = ((LimitResource) resource).used;
+ } else if (resource.resourceType == ResourceType.Label) {
+ resourceEntity.llLabel = ((LabelResource) resource).label;
+ resourceEntity.llReferenceCount = ((LabelResource) resource).referenceCount;
+ } else if (resource.resourceType == ResourceType.Range) {
+ resourceEntity.rrUsed = StrUtil.listInt(((RangeResource) resource).used);
+ }
+
+ return resourceEntity;
+ }
+
+ private ResourceLoad createResourceLoadEntity(long resourceId,
+ org.onap.ccsdk.sli.adaptors.rm.data.ResourceLoad rl) {
+ ResourceLoad rlEntity = new ResourceLoad();
+ rlEntity.resourceId = resourceId;
+ rlEntity.applicationId = rl.applicationId;
+ rlEntity.loadTime = rl.resourceLoadTime;
+ rlEntity.expirationTime = rl.resourceExpirationTime;
+ return rlEntity;
+ }
+
+ private void updateResourceLoadEntity(ResourceLoad rlEntity, org.onap.ccsdk.sli.adaptors.rm.data.ResourceLoad rl) {
+ rlEntity.loadTime = rl.resourceLoadTime;
+ rlEntity.expirationTime = rl.resourceExpirationTime;
+ }
+
+ private AllocationItem createAllocationItemEntity(long resourceId,
+ org.onap.ccsdk.sli.adaptors.rm.data.AllocationItem ai) {
+ AllocationItem aiEntity = new AllocationItem();
+ aiEntity.resourceId = resourceId;
+ aiEntity.resourceSetId = ai.resourceSetId;
+ aiEntity.resourceUnionId = ai.resourceUnionId;
+ aiEntity.resourceShareGroupList = StrUtil.listStr(ai.resourceShareGroupList);
+ aiEntity.applicationId = ai.applicationId;
+ aiEntity.allocationTime = ai.allocationTime;
+ if (ai.resourceType == ResourceType.Limit) {
+ aiEntity.ltUsed = ((LimitAllocationItem) ai).used;
+ } else if (ai.resourceType == ResourceType.Label) {
+ aiEntity.llLabel = ((LabelAllocationItem) ai).label;
+ } else if (ai.resourceType == ResourceType.Range) {
+ aiEntity.rrUsed = StrUtil.listInt(((RangeAllocationItem) ai).used);
+ }
+ return aiEntity;
+ }
+
+ private void updateAllocationItemEntity(AllocationItem aiEntity,
+ org.onap.ccsdk.sli.adaptors.rm.data.AllocationItem ai) {
+ aiEntity.resourceShareGroupList = StrUtil.listStr(ai.resourceShareGroupList);
+ aiEntity.allocationTime = ai.allocationTime;
+ if (ai.resourceType == ResourceType.Limit) {
+ aiEntity.ltUsed = ((LimitAllocationItem) ai).used;
+ } else if (ai.resourceType == ResourceType.Label) {
+ aiEntity.llLabel = ((LabelAllocationItem) ai).label;
+ } else if (ai.resourceType == ResourceType.Range) {
+ aiEntity.rrUsed = StrUtil.listInt(((RangeAllocationItem) ai).used);
+ }
+ }
+
+ private void updateResourceEntity(Resource resourceEntity, org.onap.ccsdk.sli.adaptors.rm.data.Resource resource) {
+ if (resource.resourceType == ResourceType.Limit) {
+ resourceEntity.ltUsed = ((LimitResource) resource).used;
+ } else if (resource.resourceType == ResourceType.Label) {
+ resourceEntity.llLabel = ((LabelResource) resource).label;
+ resourceEntity.llReferenceCount = ((LabelResource) resource).referenceCount;
+ } else if (resource.resourceType == ResourceType.Range) {
+ resourceEntity.rrUsed = StrUtil.listInt(((RangeResource) resource).used);
+ }
+ }
+
+ private org.onap.ccsdk.sli.adaptors.rm.data.Resource createResourceWithItems(Resource rEntity) {
+ org.onap.ccsdk.sli.adaptors.rm.data.Resource r = createResource(rEntity);
+
+ if (r != null) {
+ List<AllocationItem> aiEntityList = allocationItemJdbcDao.getAllocationItems(rEntity.id);
+ r.allocationItems = new ArrayList<>();
+ for (AllocationItem aiEntity : aiEntityList) {
+ org.onap.ccsdk.sli.adaptors.rm.data.AllocationItem ai = createAllocationItem(r, aiEntity);
+ r.allocationItems.add(ai);
+ }
+
+ List<ResourceLoad> rlEntityList = resourceLoadJdbcDao.getResourceLoads(rEntity.id);
+ r.resourceLoadList = new ArrayList<>();
+ for (ResourceLoad rlEntity : rlEntityList) {
+ org.onap.ccsdk.sli.adaptors.rm.data.ResourceLoad rl = createResourceLoad(r, rlEntity);
+ r.resourceLoadList.add(rl);
+ }
+ }
+ return r;
+ }
+
+ private org.onap.ccsdk.sli.adaptors.rm.data.Resource createResource(Resource resourceEntity) {
+ if (resourceEntity == null) {
+ return null;
+ }
+
+ org.onap.ccsdk.sli.adaptors.rm.data.Resource r = null;
+ ResourceType type = ResourceType.valueOf(resourceEntity.type);
+ if (type == ResourceType.Limit) {
+ LimitResource l = new LimitResource();
+ l.used = resourceEntity.ltUsed;
+ r = l;
+ } else if (type == ResourceType.Label) {
+ LabelResource l = new LabelResource();
+ l.label = resourceEntity.llLabel;
+ l.referenceCount = resourceEntity.llReferenceCount;
+ r = l;
+ } else if (type == ResourceType.Range) {
+ RangeResource rr = new RangeResource();
+ rr.used = StrUtil.listInt(resourceEntity.rrUsed, "Invalid data found in DB in for Resource Id: "
+ + resourceEntity.id + ": RESOURCE.RR_USED: " + resourceEntity.rrUsed);
+ r = rr;
+ }
+
+ if (r != null) {
+ r.resourceType = type;
+ r.resourceKey = new ResourceKey();
+ r.resourceKey.assetId = resourceEntity.assetId;
+ r.resourceKey.resourceName = resourceEntity.name;
+ }
+
+ return r;
+ }
+
+ private org.onap.ccsdk.sli.adaptors.rm.data.AllocationItem createAllocationItem(
+ org.onap.ccsdk.sli.adaptors.rm.data.Resource r, AllocationItem aiEntity) {
+ if (r == null || aiEntity == null) {
+ return null;
+ }
+
+ org.onap.ccsdk.sli.adaptors.rm.data.AllocationItem ai = null;
+ if (r.resourceType == ResourceType.Limit) {
+ LimitAllocationItem lai = new LimitAllocationItem();
+ lai.used = aiEntity.ltUsed;
+ ai = lai;
+ } else if (r.resourceType == ResourceType.Label) {
+ LabelAllocationItem lai = new LabelAllocationItem();
+ lai.label = aiEntity.llLabel;
+ ai = lai;
+ } else if (r.resourceType == ResourceType.Range) {
+ RangeAllocationItem rai = new RangeAllocationItem();
+ rai.used = StrUtil.listInt(aiEntity.rrUsed, "Invalid data found in DB in for Allocation Item Id: "
+ + aiEntity.id + ": ALLOCATION_ITEM.RR_USED: " + aiEntity.rrUsed);
+ ai = rai;
+ }
+
+ if (ai != null) {
+ ai.resourceType = r.resourceType;
+ ai.resourceKey = r.resourceKey;
+ ai.resourceSetId = aiEntity.resourceSetId;
+ ai.resourceUnionId = aiEntity.resourceUnionId;
+ if (aiEntity.resourceShareGroupList != null) {
+ ai.resourceShareGroupList = new HashSet<>(StrUtil.listStr(aiEntity.resourceShareGroupList));
+ }
+ ai.applicationId = aiEntity.applicationId;
+ ai.allocationTime = aiEntity.allocationTime;
+ }
+
+ return ai;
+ }
+
+ private org.onap.ccsdk.sli.adaptors.rm.data.ResourceLoad createResourceLoad(
+ org.onap.ccsdk.sli.adaptors.rm.data.Resource r, ResourceLoad rlEntity) {
+ if (rlEntity == null) {
+ return null;
+ }
+
+ org.onap.ccsdk.sli.adaptors.rm.data.ResourceLoad rl = new org.onap.ccsdk.sli.adaptors.rm.data.ResourceLoad();
+ rl.resourceKey = r.resourceKey;
+ rl.applicationId = rlEntity.applicationId;
+ rl.resourceLoadTime = rlEntity.loadTime;
+ rl.resourceExpirationTime = rlEntity.expirationTime;
+
+ return rl;
+ }
+
+ private static boolean eq(Object o1, Object o2) {
+ return o1 == null ? o2 == null : o1.equals(o2);
+ }
+
+ public void setResourceJdbcDao(ResourceJdbcDao resourceJdbcDao) {
+ this.resourceJdbcDao = resourceJdbcDao;
+ }
+
+ public void setResourceLoadJdbcDao(ResourceLoadJdbcDao resourceLoadJdbcDao) {
+ this.resourceLoadJdbcDao = resourceLoadJdbcDao;
+ }
+
+ public void setAllocationItemJdbcDao(AllocationItemJdbcDao allocationItemJdbcDao) {
+ this.allocationItemJdbcDao = allocationItemJdbcDao;
+ }
+}
diff --git a/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/dao/jdbc/ResourceJdbcDao.java b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/dao/jdbc/ResourceJdbcDao.java
new file mode 100644
index 000000000..d4d9a0543
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/dao/jdbc/ResourceJdbcDao.java
@@ -0,0 +1,45 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.rm.dao.jdbc;
+
+import java.util.List;
+
+public interface ResourceJdbcDao {
+
+ Resource getResource(String assetId, String resourceName);
+
+ List<Resource> queryResources(String assetIdFilter, String resourceName);
+
+ List<Resource> getResourceSet(String resourceSetId);
+
+ List<Resource> getResourceUnion(String resourceUnionId);
+
+ List<Resource> getResourceSetForAsset(String resourceSetId, String assetId);
+
+ List<Resource> getResourceUnionForAsset(String resourceUnionId, String assetId);
+
+ void add(Resource r);
+
+ void delete(long id);
+
+ void update(Resource r);
+}
diff --git a/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/dao/jdbc/ResourceJdbcDaoImpl.java b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/dao/jdbc/ResourceJdbcDaoImpl.java
new file mode 100644
index 000000000..f9de42802
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/dao/jdbc/ResourceJdbcDaoImpl.java
@@ -0,0 +1,183 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * Modifications Copyright (C) 2018 IBM.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.rm.dao.jdbc;
+
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.Collections;
+import java.util.List;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.core.PreparedStatementCreator;
+import org.springframework.jdbc.core.RowMapper;
+import org.springframework.jdbc.support.GeneratedKeyHolder;
+import org.springframework.jdbc.support.KeyHolder;
+
+public class ResourceJdbcDaoImpl implements ResourceJdbcDao {
+
+ private static final String baseSelectResourceQuery = "SELECT * FROM RESOURCE WHERE resource_id IN (\n";
+
+ @SuppressWarnings("unused")
+ private static final Logger log = LoggerFactory.getLogger(ResourceJdbcDaoImpl.class);
+
+ private static final String RESOURCE_SQL = "SELECT * FROM RESOURCE WHERE asset_id = ? AND resource_name = ?";
+
+ private static final String RESOURCE_QUERY_1_SQL =
+ "SELECT * FROM RESOURCE WHERE asset_id LIKE ? AND resource_name = ?";
+
+ private static final String RESOURCE_SET_SQL = baseSelectResourceQuery
+ + "SELECT DISTINCT resource_id FROM ALLOCATION_ITEM WHERE resource_set_id = ?)";
+
+ private static final String RESOURCE_UNION_SQL = baseSelectResourceQuery
+ + "SELECT DISTINCT resource_id FROM ALLOCATION_ITEM WHERE resource_union_id = ?)";
+
+ private static final String RESOURCE_SET_FOR_ASSET_SQL = baseSelectResourceQuery
+ + "SELECT DISTINCT resource_id FROM ALLOCATION_ITEM WHERE resource_set_id = ?) AND asset_id = ?";
+
+ private static final String RESOURCE_UNION_FOR_ASSET_SQL = baseSelectResourceQuery
+ + "SELECT DISTINCT resource_id FROM ALLOCATION_ITEM WHERE resource_union_id = ?) AND asset_id = ?";
+
+ private static final String INSERT_SQL = "INSERT INTO RESOURCE (\n"
+ + " asset_id, resource_name, resource_type, lt_used, ll_label, ll_reference_count, rr_used)\n"
+ + "VALUES (?, ?, ?, ?, ?, ?, ?)";
+
+ private static final String UPDATE_SQL = "UPDATE RESOURCE SET\n"
+ + " lt_used = ?, ll_label = ?, ll_reference_count = ?, rr_used = ?\nWHERE resource_id = ?";
+
+ private static final String DELETE_SQL = "DELETE FROM RESOURCE WHERE resource_id = ?";
+
+ private JdbcTemplate jdbcTemplate;
+ private ResourceRowMapper resourceRowMapper = new ResourceRowMapper();
+
+ @Override
+ public Resource getResource(String assetId, String resourceName) {
+ if (assetId == null || assetId.trim().length() == 0 || resourceName == null
+ || resourceName.trim().length() == 0) {
+ return null;
+ }
+
+ List<Resource> ll = jdbcTemplate.query(RESOURCE_SQL, new Object[] {assetId, resourceName}, resourceRowMapper);
+ return ll.isEmpty() ? null : ll.get(0);
+ }
+
+ @Override
+ public List<Resource> queryResources(String assetIdFilter, String resourceName) {
+ if (assetIdFilter == null || assetIdFilter.trim().length() == 0 || resourceName == null
+ || resourceName.trim().length() == 0) {
+ return Collections.emptyList();
+ }
+
+
+ return jdbcTemplate.query(RESOURCE_QUERY_1_SQL, new Object[] {assetIdFilter, resourceName}, resourceRowMapper);
+ }
+
+ @Override
+ public List<Resource> getResourceSet(String resourceSetId) {
+ if (resourceSetId == null) {
+ return Collections.emptyList();
+ }
+
+ return jdbcTemplate.query(RESOURCE_SET_SQL, new Object[] {resourceSetId}, resourceRowMapper);
+ }
+
+ @Override
+ public List<Resource> getResourceUnion(String resourceUnionId) {
+ if (resourceUnionId == null) {
+ return Collections.emptyList();
+ }
+
+ return jdbcTemplate.query(RESOURCE_UNION_SQL, new Object[] {resourceUnionId}, resourceRowMapper);
+ }
+
+ @Override
+ public List<Resource> getResourceSetForAsset(String resourceSetId, String assetId) {
+ if (resourceSetId == null) {
+ return Collections.emptyList();
+ }
+
+ return jdbcTemplate.query(RESOURCE_SET_FOR_ASSET_SQL, new Object[] {resourceSetId, assetId}, resourceRowMapper);
+ }
+
+ @Override
+ public List<Resource> getResourceUnionForAsset(String resourceUnionId, String assetId) {
+ if (resourceUnionId == null) {
+ return Collections.emptyList();
+ }
+
+ return jdbcTemplate.query(RESOURCE_UNION_FOR_ASSET_SQL, new Object[] {resourceUnionId, assetId},
+ resourceRowMapper);
+ }
+
+ @Override
+ public void add(final Resource r) {
+ PreparedStatementCreator psc = dbc -> {
+ PreparedStatement ps = dbc.prepareStatement(INSERT_SQL, new String[] {"resource_id"});
+ ps.setString(1, r.assetId);
+ ps.setString(2, r.name);
+ ps.setString(3, r.type);
+ ps.setLong(4, r.ltUsed);
+ ps.setString(5, r.llLabel);
+ ps.setInt(6, r.llReferenceCount);
+ ps.setString(7, r.rrUsed);
+ return ps;
+ };
+ KeyHolder keyHolder = new GeneratedKeyHolder();
+ jdbcTemplate.update(psc, keyHolder);
+ r.id = keyHolder.getKey().longValue();
+ }
+
+ @Override
+ public void update(Resource r) {
+ Long ltUsed = r.ltUsed <= 0 ? null : r.ltUsed;
+ Integer llRefCount = r.llReferenceCount <= 0 ? null : r.llReferenceCount;
+ jdbcTemplate.update(UPDATE_SQL, ltUsed, r.llLabel, llRefCount, r.rrUsed, r.id);
+ }
+
+ @Override
+ public void delete(long id) {
+ jdbcTemplate.update(DELETE_SQL, id);
+ }
+
+ private static class ResourceRowMapper implements RowMapper<Resource> {
+
+ @Override
+ public Resource mapRow(ResultSet rs, int arg1) throws SQLException {
+ Resource r = new Resource();
+ r.id = rs.getLong("resource_id");
+ r.assetId = rs.getString("asset_id");
+ r.name = rs.getString("resource_name");
+ r.type = rs.getString("resource_type");
+ r.ltUsed = rs.getLong("lt_used");
+ r.llLabel = rs.getString("ll_label");
+ r.llReferenceCount = rs.getInt("ll_reference_count");
+ r.rrUsed = rs.getString("rr_used");
+ return r;
+ }
+ }
+
+ public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
+ this.jdbcTemplate = jdbcTemplate;
+ }
+}
diff --git a/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/dao/jdbc/ResourceLoad.java b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/dao/jdbc/ResourceLoad.java
new file mode 100644
index 000000000..0f45bbfcb
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/dao/jdbc/ResourceLoad.java
@@ -0,0 +1,33 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.rm.dao.jdbc;
+
+import java.util.Date;
+
+public class ResourceLoad {
+
+ public long id;
+ public long resourceId;
+ public String applicationId;
+ public Date loadTime;
+ public Date expirationTime;
+}
diff --git a/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/dao/jdbc/ResourceLoadJdbcDao.java b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/dao/jdbc/ResourceLoadJdbcDao.java
new file mode 100644
index 000000000..789670c4b
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/dao/jdbc/ResourceLoadJdbcDao.java
@@ -0,0 +1,36 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.rm.dao.jdbc;
+
+import java.util.List;
+
+public interface ResourceLoadJdbcDao {
+
+ void add(ResourceLoad rl);
+
+ List<ResourceLoad> getResourceLoads(long resourceId);
+
+ void update(ResourceLoad rl);
+
+ void delete(long id);
+
+}
diff --git a/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/dao/jdbc/ResourceLoadJdbcDaoImpl.java b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/dao/jdbc/ResourceLoadJdbcDaoImpl.java
new file mode 100644
index 000000000..632a5fbec
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/dao/jdbc/ResourceLoadJdbcDaoImpl.java
@@ -0,0 +1,112 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.rm.dao.jdbc;
+
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Timestamp;
+import java.util.Collections;
+import java.util.List;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.core.PreparedStatementCreator;
+import org.springframework.jdbc.core.RowMapper;
+import org.springframework.jdbc.support.GeneratedKeyHolder;
+import org.springframework.jdbc.support.KeyHolder;
+
+public class ResourceLoadJdbcDaoImpl implements ResourceLoadJdbcDao {
+
+ @SuppressWarnings("unused")
+ private static final Logger log = LoggerFactory.getLogger(ResourceJdbcDaoImpl.class);
+
+ private static final String INSERT_SQL = "INSERT INTO RESOURCE_LOAD (\n"
+ + " resource_id, application_id, resource_load_time, resource_expiration_time)\nVALUES (?, ?, ?, ?)";
+
+ private static final String UPDATE_SQL = "UPDATE RESOURCE_LOAD SET\n"
+ + " resource_load_time = ?, resource_expiration_time = ?\nWHERE resource_id = ?";
+
+ private static final String DELETE_SQL = "DELETE FROM RESOURCE_LOAD WHERE resource_load_id = ?";
+
+ private static final String GET_SQL = "SELECT * FROM RESOURCE_LOAD WHERE resource_id = ?";
+
+ private JdbcTemplate jdbcTemplate;
+ private ResourceLoadRowMapper resourceLoadRowMapper = new ResourceLoadRowMapper();
+
+ @Override
+ public void add(final ResourceLoad rl) {
+ PreparedStatementCreator psc = new PreparedStatementCreator() {
+
+ @Override
+ public PreparedStatement createPreparedStatement(Connection dbc) throws SQLException {
+ PreparedStatement ps = dbc.prepareStatement(INSERT_SQL, new String[] { "resource_load_id" });
+ ps.setLong(1, rl.resourceId);
+ ps.setString(2, rl.applicationId);
+ ps.setTimestamp(3, new Timestamp(rl.loadTime.getTime()));
+ ps.setTimestamp(4, new Timestamp(rl.expirationTime.getTime()));
+ return ps;
+ }
+ };
+ KeyHolder keyHolder = new GeneratedKeyHolder();
+ jdbcTemplate.update(psc, keyHolder);
+ rl.id = keyHolder.getKey().longValue();
+ }
+
+ @Override
+ public void update(ResourceLoad rl) {
+ jdbcTemplate.update(UPDATE_SQL, rl.loadTime, rl.expirationTime, rl.id);
+ }
+
+ @Override
+ public void delete(long id) {
+ jdbcTemplate.update(DELETE_SQL, id);
+ }
+
+ @Override
+ public List<ResourceLoad> getResourceLoads(long resourceId) {
+ if (resourceId <= 0)
+ return Collections.emptyList();
+
+ return jdbcTemplate.query(GET_SQL, new Object[] { resourceId }, resourceLoadRowMapper);
+ }
+
+ private static class ResourceLoadRowMapper implements RowMapper<ResourceLoad> {
+
+ @Override
+ public ResourceLoad mapRow(ResultSet rs, int n) throws SQLException {
+ ResourceLoad rl = new ResourceLoad();
+ rl.id = rs.getLong("allocation_item_id");
+ rl.resourceId = rs.getLong("resource_id");
+ rl.applicationId = rs.getString("application_id");
+ rl.loadTime = rs.getTimestamp("resource_load_time");
+ rl.expirationTime = rs.getTimestamp("resource_expiration_time");
+ return rl;
+ }
+ }
+
+ public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
+ this.jdbcTemplate = jdbcTemplate;
+ }
+}
diff --git a/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/AllocationAction.java b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/AllocationAction.java
new file mode 100644
index 000000000..edc1916b5
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/AllocationAction.java
@@ -0,0 +1,26 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.rm.data;
+
+public enum AllocationAction {
+ Fail, Succeed_DoNothing, Succeed_Allocate
+}
diff --git a/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/AllocationItem.java b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/AllocationItem.java
new file mode 100644
index 000000000..f8e6a75a1
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/AllocationItem.java
@@ -0,0 +1,36 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.rm.data;
+
+import java.util.Date;
+import java.util.Set;
+
+public abstract class AllocationItem {
+
+ public ResourceKey resourceKey;
+ public ResourceType resourceType;
+ public String resourceSetId;
+ public String resourceUnionId;
+ public Set<String> resourceShareGroupList;
+ public String applicationId;
+ public Date allocationTime;
+}
diff --git a/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/AllocationOutcome.java b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/AllocationOutcome.java
new file mode 100644
index 000000000..048f4f4ac
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/AllocationOutcome.java
@@ -0,0 +1,28 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.rm.data;
+
+public class AllocationOutcome {
+
+ public AllocationStatus status = null;
+ public AllocationRequest request = null;
+}
diff --git a/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/AllocationRequest.java b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/AllocationRequest.java
new file mode 100644
index 000000000..29b493683
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/AllocationRequest.java
@@ -0,0 +1,37 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.rm.data;
+
+import java.util.Set;
+
+public class AllocationRequest {
+
+ public String applicationId = null;
+ public String resourceUnionId = null;
+ public String resourceSetId = null;
+ public Set<String> resourceShareGroupList = null;
+ public String resourceName = null;
+ public String assetId = null;
+ public AllocationAction missingResourceAction = AllocationAction.Succeed_Allocate;
+ public AllocationAction expiredResourceAction = AllocationAction.Succeed_Allocate;
+ public String endPointPosition = null;
+}
diff --git a/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/AllocationStatus.java b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/AllocationStatus.java
new file mode 100644
index 000000000..bef9a1114
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/AllocationStatus.java
@@ -0,0 +1,27 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.rm.data;
+
+public enum AllocationStatus {
+
+ Success, Failure, NotTried, ResourceNotFound, ResourceExpired
+}
diff --git a/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/InitAction.java b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/InitAction.java
new file mode 100644
index 000000000..f6fc7c9b3
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/InitAction.java
@@ -0,0 +1,36 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.rm.data;
+
+public enum InitAction {
+ CheckInit("Initialize if needed"), ForceInit("Always Initialize"), NoInit("No initialization");
+
+ private String str;
+
+ private InitAction(String str) {
+ this.str = str;
+ }
+
+ public String getInitActionStr() {
+ return str;
+ }
+}
diff --git a/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/LabelAllocationItem.java b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/LabelAllocationItem.java
new file mode 100644
index 000000000..d41bfd62a
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/LabelAllocationItem.java
@@ -0,0 +1,27 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.rm.data;
+
+public class LabelAllocationItem extends AllocationItem {
+
+ public String label;
+}
diff --git a/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/LabelAllocationOutcome.java b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/LabelAllocationOutcome.java
new file mode 100644
index 000000000..9c9f9145d
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/LabelAllocationOutcome.java
@@ -0,0 +1,28 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.rm.data;
+
+public class LabelAllocationOutcome extends AllocationOutcome {
+
+ public String allocatedLabel = null;
+ public String currentLabel = null;
+}
diff --git a/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/LabelAllocationRequest.java b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/LabelAllocationRequest.java
new file mode 100644
index 000000000..97751fc01
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/LabelAllocationRequest.java
@@ -0,0 +1,29 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.rm.data;
+
+public class LabelAllocationRequest extends AllocationRequest {
+
+ public String label = null;
+ public boolean check = false;
+ public boolean allocate = false;
+}
diff --git a/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/LabelResource.java b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/LabelResource.java
new file mode 100644
index 000000000..d09dba267
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/LabelResource.java
@@ -0,0 +1,30 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.rm.data;
+
+public class LabelResource extends Resource {
+
+ public static final String BLOCKED = "__BLOCKED__";
+
+ public String label;
+ public int referenceCount;
+}
diff --git a/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/LimitAllocationItem.java b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/LimitAllocationItem.java
new file mode 100644
index 000000000..ad1674f7b
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/LimitAllocationItem.java
@@ -0,0 +1,27 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.rm.data;
+
+public class LimitAllocationItem extends AllocationItem {
+
+ public long used;
+}
diff --git a/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/LimitAllocationOutcome.java b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/LimitAllocationOutcome.java
new file mode 100644
index 000000000..d635e3605
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/LimitAllocationOutcome.java
@@ -0,0 +1,29 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.rm.data;
+
+public class LimitAllocationOutcome extends AllocationOutcome {
+
+ public long allocatedCount = 0;
+ public long used = 0;
+ public long limit = 0;
+}
diff --git a/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/LimitAllocationRequest.java b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/LimitAllocationRequest.java
new file mode 100644
index 000000000..06c0e8393
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/LimitAllocationRequest.java
@@ -0,0 +1,31 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.rm.data;
+
+public class LimitAllocationRequest extends AllocationRequest {
+
+ public long checkCount = 0;
+ public long allocateCount = 0;
+ public long checkLimit = -1;
+ public boolean replace = false;
+ public boolean strict = false;
+}
diff --git a/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/LimitResource.java b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/LimitResource.java
new file mode 100644
index 000000000..2fd9b6cae
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/LimitResource.java
@@ -0,0 +1,27 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.rm.data;
+
+public class LimitResource extends Resource {
+
+ public long used = 0;
+}
diff --git a/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/MultiAssetAllocationOutcome.java b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/MultiAssetAllocationOutcome.java
new file mode 100644
index 000000000..2d7b11c31
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/MultiAssetAllocationOutcome.java
@@ -0,0 +1,30 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.rm.data;
+
+import java.util.List;
+
+public class MultiAssetAllocationOutcome extends AllocationOutcome {
+
+ public List<String> goodAssetIdList;
+ public List<AllocationOutcome> allocationOutcomeList;
+}
diff --git a/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/MultiAssetAllocationRequest.java b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/MultiAssetAllocationRequest.java
new file mode 100644
index 000000000..366201f35
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/MultiAssetAllocationRequest.java
@@ -0,0 +1,32 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.rm.data;
+
+import java.util.List;
+
+public class MultiAssetAllocationRequest extends AllocationRequest {
+
+ public List<String> assetIdList = null;
+ public AllocationRequest allocationRequest = null;
+ public int requestedCount = 0;
+ public boolean sequential = false;
+}
diff --git a/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/MultiResourceAllocationOutcome.java b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/MultiResourceAllocationOutcome.java
new file mode 100644
index 000000000..f71c247da
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/MultiResourceAllocationOutcome.java
@@ -0,0 +1,29 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.rm.data;
+
+import java.util.List;
+
+public class MultiResourceAllocationOutcome extends AllocationOutcome {
+
+ public List<AllocationOutcome> allocationOutcomeList;
+}
diff --git a/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/MultiResourceAllocationRequest.java b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/MultiResourceAllocationRequest.java
new file mode 100644
index 000000000..3244c2340
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/MultiResourceAllocationRequest.java
@@ -0,0 +1,30 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.rm.data;
+
+import java.util.List;
+
+public class MultiResourceAllocationRequest extends AllocationRequest {
+
+ public List<AllocationRequest> allocationRequestList = null;
+ public boolean stopOnFirstFailure = true;
+}
diff --git a/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/Range.java b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/Range.java
new file mode 100644
index 000000000..16be77f5b
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/Range.java
@@ -0,0 +1,28 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.rm.data;
+
+public class Range {
+
+ public int min = 0;
+ public int max = 0;
+}
diff --git a/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/RangeAllocationItem.java b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/RangeAllocationItem.java
new file mode 100644
index 000000000..8e62ef653
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/RangeAllocationItem.java
@@ -0,0 +1,29 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.rm.data;
+
+import java.util.SortedSet;
+
+public class RangeAllocationItem extends AllocationItem {
+
+ public SortedSet<Integer> used;
+}
diff --git a/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/RangeAllocationOutcome.java b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/RangeAllocationOutcome.java
new file mode 100644
index 000000000..3b675c221
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/RangeAllocationOutcome.java
@@ -0,0 +1,30 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.rm.data;
+
+import java.util.SortedSet;
+
+public class RangeAllocationOutcome extends AllocationOutcome {
+
+ public SortedSet<Integer> allocated = null;
+ public SortedSet<Integer> used = null;
+}
diff --git a/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/RangeAllocationRequest.java b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/RangeAllocationRequest.java
new file mode 100644
index 000000000..a7948b02c
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/RangeAllocationRequest.java
@@ -0,0 +1,40 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.rm.data;
+
+import java.util.List;
+import java.util.SortedSet;
+
+public class RangeAllocationRequest extends AllocationRequest {
+
+ public List<Range> rangeList = null;
+ public boolean check = false;
+ public boolean allocate = false;
+ public boolean replace = false;
+ public SortedSet<Integer> requestedNumbers = null;
+ public SortedSet<Integer> excludeNumbers = null;
+ public int requestedCount = 1;
+ public boolean sequential = false;
+ public boolean reverseOrder = false;
+ public boolean forceNewNumbers = false;
+ public boolean nextInSequence = false;
+}
diff --git a/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/RangeResource.java b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/RangeResource.java
new file mode 100644
index 000000000..c39cb37ea
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/RangeResource.java
@@ -0,0 +1,29 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.rm.data;
+
+import java.util.SortedSet;
+
+public class RangeResource extends Resource {
+
+ public SortedSet<Integer> used;
+}
diff --git a/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/ReleaseRequest.java b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/ReleaseRequest.java
new file mode 100644
index 000000000..dba6a172f
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/ReleaseRequest.java
@@ -0,0 +1,46 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.rm.data;
+
+import java.util.Set;
+
+public class ReleaseRequest {
+
+ public String resourceUnionId = null;
+ public String resourceSetId = null;
+ public String assetId = null;
+ public String resourceName = null;
+ public int releaseAmount = 0;
+ public Set<Integer> releaseNumbers = null;
+
+ public static ReleaseRequest resourceSet(String resourceSetId) {
+ ReleaseRequest rr = new ReleaseRequest();
+ rr.resourceSetId = resourceSetId;
+ return rr;
+ }
+
+ public static ReleaseRequest resourceUnion(String resourceUnionId) {
+ ReleaseRequest rr = new ReleaseRequest();
+ rr.resourceUnionId = resourceUnionId;
+ return rr;
+ }
+}
diff --git a/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/Resource.java b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/Resource.java
new file mode 100644
index 000000000..59706f4d5
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/Resource.java
@@ -0,0 +1,32 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.rm.data;
+
+import java.util.Collection;
+
+public abstract class Resource {
+
+ public ResourceKey resourceKey;
+ public ResourceType resourceType;
+ public Collection<AllocationItem> allocationItems;
+ public Collection<ResourceLoad> resourceLoadList;
+}
diff --git a/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/ResourceKey.java b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/ResourceKey.java
new file mode 100644
index 000000000..b1f8d5910
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/ResourceKey.java
@@ -0,0 +1,50 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.rm.data;
+
+public class ResourceKey {
+
+ public String assetId;
+ public String resourceName;
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o)
+ return true;
+ if (o == null || !(o instanceof ResourceKey))
+ return false;
+ ResourceKey rk = (ResourceKey) o;
+ if (assetId == null || resourceName == null)
+ return false;
+ return assetId.equals(rk.assetId) && resourceName.equals(rk.resourceName);
+ }
+
+ @Override
+ public int hashCode() {
+ return (int) ((long) System.identityHashCode(assetId) + (long) System.identityHashCode(resourceName));
+ }
+
+ @Override
+ public String toString() {
+ return "(" + assetId + ", " + resourceName + ")";
+ }
+}
diff --git a/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/ResourceLoad.java b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/ResourceLoad.java
new file mode 100644
index 000000000..1ff1962af
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/ResourceLoad.java
@@ -0,0 +1,32 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.rm.data;
+
+import java.util.Date;
+
+public class ResourceLoad {
+
+ public ResourceKey resourceKey;
+ public String applicationId;
+ public Date resourceLoadTime;
+ public Date resourceExpirationTime;
+}
diff --git a/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/ResourceType.java b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/ResourceType.java
new file mode 100644
index 000000000..60896e492
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/data/ResourceType.java
@@ -0,0 +1,26 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.rm.data;
+
+public enum ResourceType {
+ Limit, Label, Range
+}
diff --git a/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/util/LabelUtil.java b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/util/LabelUtil.java
new file mode 100644
index 000000000..a67a50b31
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/util/LabelUtil.java
@@ -0,0 +1,99 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.rm.util;
+
+import java.util.ArrayList;
+import java.util.Date;
+import org.onap.ccsdk.sli.adaptors.rm.data.AllocationItem;
+import org.onap.ccsdk.sli.adaptors.rm.data.LabelAllocationItem;
+import org.onap.ccsdk.sli.adaptors.rm.data.LabelAllocationRequest;
+import org.onap.ccsdk.sli.adaptors.rm.data.LabelResource;
+import org.onap.ccsdk.sli.adaptors.rm.data.ResourceKey;
+import org.onap.ccsdk.sli.adaptors.rm.data.ResourceType;
+
+public class LabelUtil {
+
+ public static boolean checkLabel(LabelResource l, LabelAllocationRequest req) {
+ if (req.check && req.label != null && l.allocationItems != null && !l.allocationItems.isEmpty()) {
+ for (AllocationItem ai : l.allocationItems) {
+ LabelAllocationItem lai = (LabelAllocationItem) ai;
+ if (!eq(req.resourceUnionId, lai.resourceUnionId) && !eq(req.label, lai.label)) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ public static String allocateLabel(LabelResource l, LabelAllocationRequest req) {
+ if (!req.allocate) {
+ return null;
+ }
+
+ LabelAllocationItem lai = (LabelAllocationItem) ResourceUtil.getAllocationItem(l, req.resourceSetId);
+ if (lai == null) {
+ lai = new LabelAllocationItem();
+ lai.resourceType = ResourceType.Label;
+ lai.resourceKey = new ResourceKey();
+ lai.resourceKey.assetId = req.assetId;
+ lai.resourceKey.resourceName = req.resourceName;
+ lai.applicationId = req.applicationId;
+ lai.resourceSetId = req.resourceSetId;
+ lai.resourceUnionId = req.resourceUnionId;
+ lai.resourceShareGroupList = req.resourceShareGroupList;
+
+ if (l.allocationItems == null) {
+ l.allocationItems = new ArrayList<>();
+ }
+ l.allocationItems.add(lai);
+ }
+
+ lai.label = req.label;
+ lai.allocationTime = new Date();
+
+ recalculate(l);
+
+ return lai.label;
+ }
+
+ public static void recalculate(LabelResource l) {
+ l.label = null;
+ l.referenceCount = 0;
+ if (l.allocationItems != null) {
+ for (AllocationItem ai : l.allocationItems) {
+ LabelAllocationItem lai = (LabelAllocationItem) ai;
+ if (lai.label != null) {
+ l.referenceCount++;
+ if (l.label == null) {
+ l.label = lai.label;
+ } else if (!l.label.equals(lai.label)) {
+ l.label = "__BLOCKED__";
+ }
+ }
+ }
+ }
+ }
+
+ private static boolean eq(Object o1, Object o2) {
+ return o1 == null ? o2 == null : o1.equals(o2);
+ }
+}
diff --git a/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/util/LimitUtil.java b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/util/LimitUtil.java
new file mode 100644
index 000000000..2e36c9661
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/util/LimitUtil.java
@@ -0,0 +1,355 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.rm.util;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import org.onap.ccsdk.sli.adaptors.rm.data.AllocationItem;
+import org.onap.ccsdk.sli.adaptors.rm.data.LimitAllocationItem;
+import org.onap.ccsdk.sli.adaptors.rm.data.LimitAllocationRequest;
+import org.onap.ccsdk.sli.adaptors.rm.data.LimitResource;
+import org.onap.ccsdk.sli.adaptors.rm.data.ResourceKey;
+import org.onap.ccsdk.sli.adaptors.rm.data.ResourceType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class LimitUtil {
+
+ private static final Logger log = LoggerFactory.getLogger(LimitUtil.class);
+
+ public static boolean checkLimit(LimitResource l, LimitAllocationRequest req) {
+ if (req.checkCount <= 0) {
+ return true;
+ }
+
+ long checkCount = req.checkCount;
+ long currentUsage = 0;
+ if (req.resourceSetId != null) {
+ LimitAllocationItem lai = (LimitAllocationItem) ResourceUtil.getAllocationItem(l, req.resourceSetId);
+ if (lai != null) {
+ currentUsage = lai.used;
+ }
+ }
+ if (!req.replace) {
+ checkCount += currentUsage;
+ }
+
+ long used = calculateLimitUsage(l, 0, null, null);
+ long wouldUse = calculateLimitUsage(l, checkCount, req.resourceUnionId, req.resourceShareGroupList);
+
+ // If usage is not increasing by this request, only check the limit if
+ // strictCheck is true.
+ if (wouldUse <= used && !req.strict) {
+ return true;
+ }
+
+ return wouldUse <= req.checkLimit;
+ }
+
+ private static long calculateLimitUsage(
+ LimitResource l,
+ long checkCount,
+ String resourceUnionId,
+ Set<String> resourceShareGroupList) {
+ if ((l.allocationItems == null || l.allocationItems.isEmpty()) &&
+ (resourceUnionId == null || resourceUnionId.length() == 0)) {
+ return 0;
+ }
+
+ long t1 = System.currentTimeMillis();
+ boolean logit = false;
+ String rn = "Resource: " + l.resourceKey.resourceName + " - " + l.resourceKey.assetId;
+
+ // In order to best utilize the resource, we need to take not the sum of all allocation items, but
+ // instead the maximum usage that could happen at any moment of time (given not all allocation items are active
+ // at the same time), also taking into account possible resource sharing.
+ // Thus we need to find all combinations of allocation items that can be active at the same time (allocation
+ // items with the same first union cannot be active at the same time), compute the usage for each (again,
+ // taking into account resource sharing), and take the maximum.
+ //
+ // Example:
+ // Let's have the following allocation items:
+ // ai1: sdid1, vrf1 - usage 5
+ // ai2: sdid2, vrf1 - usage 10
+ // ai3: sdid3, vrf2 - usage 15
+ // ai4: sdid1, vrf3 - usage 20
+ // ai5: sdid3, vrf1 - usage 25
+ // The following combinations of active allocation items are possible:
+ // 1) ai1, ai2, ai3
+ // 2) ai1, ai2, ai5
+ // 3) ai2, ai3, ai4
+ // 4) ai2, ai3, ai5
+ // Here is how we calculate the usage for combination 1:
+ // ai1 and ai2 contain the same resource union vrf1, so they share the resource - we take the max of usage,
+ // so we have:
+ // max(5, 10) + 15 = 25
+ // Similarly, we calculate the usage of the other combinations:
+ // 2) max(5, 10, 25) = 25
+ // 3) 10 + 15 + 20 = 45
+ // 4) max(10, 25) + 15 = 40
+ // So, the result in this case is:
+ // max(25, 25, 45, 40) = 45
+ //
+ // We might have a problem with this approach, if we have a lot of combinations. Assuming we have at most 2
+ // allocation items with the same resource union (sdid), the number of combinations would be
+ // 2 ^ n
+ // where n is the number of allocation items that have the same resource union (sdid). That would be
+ // the number of change orders currently in progress.
+ //
+ // Here is one optimization that we can do:
+ // If we have allocation items that have all resource unions the same, we don't need to generate combinations
+ // with each of them, we can just take the one of them with the maximum usage, as it is clear that the others
+ // will not lead to a bigger usage.
+ // For example, if we had the following allocation items:
+ // ai1: sdid1, vrf1 - usage 10
+ // ai2: sdid1, vrf1 - usage 20
+ // We only need to take the combinations with ai2, as they will always lead to bigger usage than the remaining
+ // combinations with ai1.
+
+ // First, group the allocation items by the first resource union, using the LimitUsage structure
+ int regularChangeCount = 0;
+ Map<String/* resourceUnionId */, List<LimitUsage>> limitUsageMap = new HashMap<>();
+ if (l.allocationItems != null) {
+ for (AllocationItem ai : l.allocationItems) {
+ LimitAllocationItem lai = (LimitAllocationItem) ai;
+ boolean regularChange =
+ addLimitUsage(limitUsageMap, lai.resourceUnionId, lai.resourceShareGroupList, lai.used);
+ if (regularChange) {
+ regularChangeCount++;
+ }
+ }
+ }
+ if (checkCount > 0 && resourceUnionId != null) {
+ boolean regularChange = addLimitUsage(limitUsageMap, resourceUnionId, resourceShareGroupList, checkCount);
+ if (regularChange) {
+ regularChangeCount++;
+ }
+ }
+
+ // Generate all the combinations, containing one LimitUsage object for each firstResourceUnion
+ int significantChangeCount = 0;
+ List<List<LimitUsage>> allCombinations = new ArrayList<>();
+ for (String firstResourceUnion : limitUsageMap.keySet()) {
+ List<LimitUsage> limitUsageList = limitUsageMap.get(firstResourceUnion);
+ if (limitUsageList.size() > 1) {
+ significantChangeCount++;
+ }
+ if (allCombinations.isEmpty()) {
+ for (LimitUsage limitUsage : limitUsageList) {
+ List<LimitUsage> newCombination = new ArrayList<>();
+ newCombination.add(limitUsage);
+ allCombinations.add(newCombination);
+ }
+ } else {
+ if (limitUsageList.size() == 1) {
+ // No new combinations are generated - just add this one to all combinations we have until now
+ for (List<LimitUsage> combination : allCombinations) {
+ combination.add(limitUsageList.get(0));
+ }
+ } else {
+ // We have to duplicate each of the current combinations for each element of limitUsageList
+ List<List<LimitUsage>> newAllCombinations = new ArrayList<>();
+ for (List<LimitUsage> combination : allCombinations) {
+ for (LimitUsage limitUsage : limitUsageList) {
+ List<LimitUsage> newCombination = new ArrayList<>(combination);
+ newCombination.add(limitUsage);
+ newAllCombinations.add(newCombination);
+ }
+ }
+ allCombinations = newAllCombinations;
+ }
+ }
+ }
+
+ // Now, go through all combinations and calculate its usage, get the maximum
+ long maxUsage = 0;
+ for (List<LimitUsage> combination : allCombinations) {
+ long usage = calculateUsage(combination);
+ if (usage > maxUsage) {
+ maxUsage = usage;
+ }
+ }
+
+ long t2 = System.currentTimeMillis();
+ if (logit) {
+ log.debug(rn + ": Calculating usage completed:");
+ log.debug(rn + ": Regular changes: " + regularChangeCount);
+ log.debug(rn + ": Significant changes: " + significantChangeCount);
+ log.debug(rn + ": Combinations: " + allCombinations.size());
+ log.debug(rn + ": Usage: " + maxUsage);
+ log.debug(rn + ": Time: " + (t2 - t1));
+ }
+
+ return maxUsage;
+ }
+
+ private static boolean addLimitUsage(
+ Map<String/* resourceUnionId */, List<LimitUsage>> limitUsageMap,
+ String resourceUnionId,
+ Set<String> resourceShareGroupList,
+ long used) {
+ List<LimitUsage> limitUsageList = limitUsageMap.get(resourceUnionId);
+ if (limitUsageList == null) {
+ limitUsageList = new ArrayList<>();
+ limitUsageMap.put(resourceUnionId, limitUsageList);
+ }
+ // See if we already have the same shareResourceUnionSet in the list. In such case just update the usage
+ // to the bigger value.
+ LimitUsage limitUsage = null;
+ for (LimitUsage limitUsage1 : limitUsageList) {
+ if ((limitUsage1.resourceShareGroupList == null || limitUsage1.resourceShareGroupList.isEmpty()) &&
+ (resourceShareGroupList == null || resourceShareGroupList.isEmpty())) {
+ limitUsage = limitUsage1;
+ break;
+ }
+ if (limitUsage1.resourceShareGroupList != null &&
+ limitUsage1.resourceShareGroupList.equals(resourceShareGroupList)) {
+ limitUsage = limitUsage1;
+ break;
+ }
+ }
+ if (limitUsage != null) {
+ if (limitUsage.usage < used) {
+ limitUsage.usage = used;
+ }
+ return true;
+ }
+
+ limitUsage = new LimitUsage();
+ limitUsage.resourceUnion = resourceUnionId;
+ limitUsage.resourceShareGroupList = resourceShareGroupList;
+ limitUsage.usage = used;
+ limitUsageList.add(limitUsage);
+ return false;
+ }
+
+ private static class LimitUsage {
+
+ @SuppressWarnings("unused")
+ public String resourceUnion;
+ public Set<String> resourceShareGroupList;
+ public long usage;
+ }
+
+ private static boolean hasCommonSharedResource(LimitUsage limitUsage1, LimitUsage limitUsage2) {
+ if (limitUsage1.resourceShareGroupList == null || limitUsage1.resourceShareGroupList.isEmpty()) {
+ return false;
+ }
+ if (limitUsage2.resourceShareGroupList == null || limitUsage2.resourceShareGroupList.isEmpty()) {
+ return false;
+ }
+
+ for (String resourceUnion : limitUsage1.resourceShareGroupList) {
+ if (limitUsage2.resourceShareGroupList.contains(resourceUnion)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ private static long calculateUsage(List<LimitUsage> combination) {
+ // All LimitUsage objects that have a common value in their sharedResourceUnionSet reuse the resource, so
+ // split the combination in sets that have common value. Then the usage of each set will be the maximum of
+ // the usages of the LimitUsage objects in the set. The usage of the combination will be the sum of the usages
+ // of all sets.
+ List<List<LimitUsage>> sharedSets = new ArrayList<>();
+ for (LimitUsage limitUsage : combination) {
+ // See if we can put limitUsage in any of the existing sets - is it has a common resource union with
+ // any of the LimitUsage objects in a set.
+ boolean found = false;
+ for (List<LimitUsage> sharedSet : sharedSets) {
+ for (LimitUsage limitUsage1 : sharedSet) {
+ if (hasCommonSharedResource(limitUsage, limitUsage1)) {
+ found = true;
+ break;
+ }
+ }
+ if (found) {
+ sharedSet.add(limitUsage);
+ break;
+ }
+ }
+ if (!found) {
+ // Start a new set
+ List<LimitUsage> newSharedSet = new ArrayList<>();
+ newSharedSet.add(limitUsage);
+ sharedSets.add(newSharedSet);
+ }
+ }
+
+ long sum = 0;
+ for (List<LimitUsage> sharedSet : sharedSets) {
+ float max = 0;
+ for (LimitUsage limitUsage : sharedSet) {
+ if (max < limitUsage.usage) {
+ max = limitUsage.usage;
+ }
+ }
+ sum += max;
+ }
+
+ return sum;
+ }
+
+ public static long allocateLimit(LimitResource l, LimitAllocationRequest req) {
+ if (req.allocateCount <= 0) {
+ return 0;
+ }
+ long uu = l.used;
+
+ LimitAllocationItem lai = (LimitAllocationItem) ResourceUtil.getAllocationItem(l, req.resourceSetId);
+ if (lai == null) {
+ lai = new LimitAllocationItem();
+ lai.resourceType = ResourceType.Limit;
+ lai.resourceKey = new ResourceKey();
+ lai.resourceKey.assetId = req.assetId;
+ lai.resourceKey.resourceName = req.resourceName;
+ lai.applicationId = req.applicationId;
+ lai.resourceSetId = req.resourceSetId;
+ lai.resourceUnionId = req.resourceUnionId;
+ lai.resourceShareGroupList = req.resourceShareGroupList;
+ lai.used = req.allocateCount;
+
+ if (l.allocationItems == null) {
+ l.allocationItems = new ArrayList<>();
+ }
+ l.allocationItems.add(lai);
+ } else {
+ lai.used = req.replace ? req.allocateCount : lai.used + req.allocateCount;
+ }
+
+ lai.allocationTime = new Date();
+
+ recalculate(l);
+
+ return l.used - uu;
+ }
+
+ public static void recalculate(LimitResource l) {
+ l.used = calculateLimitUsage(l, 0, null, null);
+ }
+}
diff --git a/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/util/RangeUtil.java b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/util/RangeUtil.java
new file mode 100644
index 000000000..2e378f1aa
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/util/RangeUtil.java
@@ -0,0 +1,160 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.rm.util;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
+import org.onap.ccsdk.sli.adaptors.rm.data.AllocationItem;
+import org.onap.ccsdk.sli.adaptors.rm.data.Range;
+import org.onap.ccsdk.sli.adaptors.rm.data.RangeAllocationItem;
+import org.onap.ccsdk.sli.adaptors.rm.data.RangeAllocationRequest;
+import org.onap.ccsdk.sli.adaptors.rm.data.RangeResource;
+import org.onap.ccsdk.sli.adaptors.rm.data.ResourceKey;
+import org.onap.ccsdk.sli.adaptors.rm.data.ResourceType;
+
+public class RangeUtil {
+
+ public static void recalculate(RangeResource r) {
+ r.used = new TreeSet<>();
+ if (r.allocationItems != null) {
+ for (AllocationItem ai : r.allocationItems) {
+ RangeAllocationItem rai = (RangeAllocationItem) ai;
+ if (rai.used != null) {
+ r.used.addAll(rai.used);
+ }
+ }
+ }
+ }
+
+ public static boolean checkRange(RangeResource r, RangeAllocationRequest req, int num) {
+ if (req.excludeNumbers != null && req.excludeNumbers.contains(num)) {
+ return false;
+ }
+
+ if (req.rangeList != null && !req.rangeList.isEmpty()) {
+ boolean good = false;
+ for (Range range : req.rangeList) {
+ if (num < range.min || num > range.max) {
+ continue;
+ }
+
+ boolean found = false;
+ if (r.allocationItems != null) {
+ for (AllocationItem ai : r.allocationItems) {
+ RangeAllocationItem rai = (RangeAllocationItem) ai;
+ if (!eq(req.resourceUnionId, rai.resourceUnionId) && rai.used != null
+ && rai.used.contains(num)) {
+ if (!overlap(rai.resourceShareGroupList, req.resourceShareGroupList)) {
+ found = true;
+ break;
+ }
+ }
+ if (!req.replace && eq(req.resourceSetId, rai.resourceSetId) && rai.used != null
+ && rai.used.contains(num)) {
+ found = true;
+ break;
+ }
+ if (req.forceNewNumbers && rai.used.contains(num)) {
+ found = true;
+ break;
+ }
+ }
+ }
+
+ if (!found) {
+ good = true;
+ break;
+ }
+ }
+
+ return good;
+ }
+
+ return true;
+ }
+
+ public static SortedSet<Integer> getUsed(RangeResource r, String resourceUnionId) {
+ SortedSet<Integer> used = new TreeSet<>();
+ if (r.allocationItems != null) {
+ for (AllocationItem ai : r.allocationItems) {
+ RangeAllocationItem rai = (RangeAllocationItem) ai;
+ if (eq(resourceUnionId, rai.resourceUnionId) && rai.used != null) {
+ used.addAll(rai.used);
+ }
+ }
+ }
+ return used;
+ }
+
+ public static void allocateRange(RangeResource rr, SortedSet<Integer> requestedNumbers,
+ RangeAllocationRequest req) {
+ if (!req.allocate) {
+ return;
+ }
+
+ RangeAllocationItem rai = (RangeAllocationItem) ResourceUtil.getAllocationItem(rr, req.resourceSetId);
+ if (rai == null) {
+ rai = new RangeAllocationItem();
+ rai.resourceType = ResourceType.Range;
+ rai.resourceKey = new ResourceKey();
+ rai.resourceKey.assetId = req.assetId;
+ rai.resourceKey.resourceName = req.resourceName;
+ rai.applicationId = req.applicationId;
+ rai.resourceSetId = req.resourceSetId;
+ rai.resourceUnionId = req.resourceUnionId;
+ rai.resourceShareGroupList = req.resourceShareGroupList;
+ rai.used = requestedNumbers;
+
+ if (rr.allocationItems == null) {
+ rr.allocationItems = new ArrayList<>();
+ }
+ rr.allocationItems.add(rai);
+ } else if (req.replace) {
+ rai.used = requestedNumbers;
+ } else {
+ rai.used.addAll(requestedNumbers);
+ }
+
+ rai.allocationTime = new Date();
+
+ recalculate(rr);
+ }
+
+ private static boolean eq(Object o1, Object o2) {
+ return o1 == null ? o2 == null : o1.equals(o2);
+ }
+
+ private static boolean overlap(Set<String> s1, Set<String> s2) {
+ if (s1 == null || s1.isEmpty() || s2 == null || s2.isEmpty()) {
+ return false;
+ }
+ for (String ss1 : s1) {
+ if (s2.contains(ss1)) {
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/util/ResourceUtil.java b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/util/ResourceUtil.java
new file mode 100644
index 000000000..3db63804b
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/rm/util/ResourceUtil.java
@@ -0,0 +1,57 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.rm.util;
+
+import org.onap.ccsdk.sli.adaptors.rm.data.AllocationItem;
+import org.onap.ccsdk.sli.adaptors.rm.data.LabelResource;
+import org.onap.ccsdk.sli.adaptors.rm.data.LimitResource;
+import org.onap.ccsdk.sli.adaptors.rm.data.RangeResource;
+import org.onap.ccsdk.sli.adaptors.rm.data.Resource;
+import org.onap.ccsdk.sli.adaptors.rm.data.ResourceType;
+
+public class ResourceUtil {
+
+ public static AllocationItem getAllocationItem(Resource r, String resourceSetId) {
+ if (r.allocationItems != null) {
+ for (AllocationItem ai : r.allocationItems) {
+ if (ai.resourceSetId != null && ai.resourceSetId.equals(resourceSetId)) {
+ return ai;
+ }
+ }
+ }
+ return null;
+ }
+
+ public static void recalculate(Resource r) {
+ if (r == null) {
+ return;
+ }
+
+ if (r.resourceType == ResourceType.Limit) {
+ LimitUtil.recalculate((LimitResource) r);
+ } else if (r.resourceType == ResourceType.Range) {
+ RangeUtil.recalculate((RangeResource) r);
+ } else if (r.resourceType == ResourceType.Label) {
+ LabelUtil.recalculate((LabelResource) r);
+ }
+ }
+}
diff --git a/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/util/db/CachedDataSourceWrap.java b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/util/db/CachedDataSourceWrap.java
new file mode 100644
index 000000000..3fa3952f2
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/util/db/CachedDataSourceWrap.java
@@ -0,0 +1,156 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.util.db;
+
+import java.io.PrintWriter;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.sql.SQLFeatureNotSupportedException;
+import javax.sql.DataSource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class CachedDataSourceWrap implements DataSource {
+
+ private static final Logger log = LoggerFactory.getLogger(CachedDataSourceWrap.class);
+
+ private ThreadLocal<ConnectionWrap> con = new ThreadLocal<>();
+ private ThreadLocal<Boolean> autoCommit = new ThreadLocal<>();
+
+ private DataSource dataSource;
+
+ @Override
+ public PrintWriter getLogWriter() throws SQLException {
+ return dataSource.getLogWriter();
+ }
+
+ @Override
+ public void setLogWriter(PrintWriter out) throws SQLException {
+ dataSource.setLogWriter(out);
+ }
+
+ @Override
+ public void setLoginTimeout(int seconds) throws SQLException {
+ dataSource.setLoginTimeout(seconds);
+ }
+
+ @Override
+ public int getLoginTimeout() throws SQLException {
+ return dataSource.getLoginTimeout();
+ }
+
+ @Override
+ public java.util.logging.Logger getParentLogger() throws SQLFeatureNotSupportedException {
+ return dataSource.getParentLogger();
+ }
+
+ @Override
+ public <T> T unwrap(Class<T> iface) throws SQLException {
+ return dataSource.unwrap(iface);
+ }
+
+ @Override
+ public boolean isWrapperFor(Class<?> iface) throws SQLException {
+ return dataSource.isWrapperFor(iface);
+ }
+
+ @Override
+ public Connection getConnection() throws SQLException {
+ if (con.get() == null) {
+ Connection c = dataSource.getConnection();
+
+ ConnectionWrap cc = new ConnectionWrap(c);
+ con.set(cc);
+
+ autoCommit.set(c.getAutoCommit());
+ c.setAutoCommit(false);
+
+ log.info("Got new DB connection: " + c);
+ } else {
+ log.info("Using thread DB connection: " + con.get().getCon());
+ }
+
+ return con.get();
+ }
+
+ @Override
+ public Connection getConnection(String username, String password) throws SQLException {
+ if (con.get() == null) {
+ Connection c = dataSource.getConnection(username, password);
+
+ ConnectionWrap cc = new ConnectionWrap(c);
+ con.set(cc);
+
+ autoCommit.set(c.getAutoCommit());
+ c.setAutoCommit(false);
+
+ log.info("Got new DB connection: " + c);
+ } else {
+ log.info("Using thread DB connection: " + con.get().getCon());
+ }
+
+ return con.get();
+ }
+
+ public void releaseConnection() {
+ if (con.get() != null) {
+ try {
+ con.get().setAutoCommit(autoCommit.get());
+ con.get().realClose();
+
+ log.info("DB Connection released: " + con.get().getCon());
+ } catch (SQLException e) {
+ log.warn("Failed to release DB connection", e);
+ } finally {
+ con.remove();
+ }
+ }
+ }
+
+ public void commit() {
+ if (con.get() != null) {
+ try {
+ con.get().commit();
+
+ log.info("DB Connection committed: " + con.get().getCon());
+ } catch (Exception e) {
+ log.warn("Failed to commit DB connection", e);
+ }
+ }
+ }
+
+ public void rollback() {
+ if (con.get() != null) {
+ try {
+ con.get().rollback();
+
+ log.info("DB Connection rolled back: " + con.get().getCon());
+ } catch (Exception e) {
+ log.warn("Failed to roll back DB connection", e);
+ }
+ }
+ }
+
+ public void setDataSource(DataSource dataSource) {
+ this.dataSource = dataSource;
+ }
+}
diff --git a/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/util/db/ConnectionWrap.java b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/util/db/ConnectionWrap.java
new file mode 100644
index 000000000..7d2554806
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/util/db/ConnectionWrap.java
@@ -0,0 +1,338 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.util.db;
+
+import java.sql.Array;
+import java.sql.Blob;
+import java.sql.CallableStatement;
+import java.sql.Clob;
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.NClob;
+import java.sql.PreparedStatement;
+import java.sql.SQLClientInfoException;
+import java.sql.SQLException;
+import java.sql.SQLWarning;
+import java.sql.SQLXML;
+import java.sql.Savepoint;
+import java.sql.Statement;
+import java.sql.Struct;
+import java.util.Map;
+import java.util.Properties;
+import java.util.concurrent.Executor;
+
+public class ConnectionWrap implements Connection {
+
+ private Connection cc;
+
+ public ConnectionWrap(Connection cc) {
+ super();
+ this.cc = cc;
+ }
+
+ public Connection getCon() {
+ return cc;
+ }
+
+ public void realClose() throws SQLException {
+ cc.close();
+ }
+
+ @Override
+ public <T> T unwrap(Class<T> iface) throws SQLException {
+ return cc.unwrap(iface);
+ }
+
+ @Override
+ public boolean isWrapperFor(Class<?> iface) throws SQLException {
+ return cc.isWrapperFor(iface);
+ }
+
+ @Override
+ public Statement createStatement() throws SQLException {
+ return cc.createStatement();
+ }
+
+ @Override
+ public PreparedStatement prepareStatement(String sql) throws SQLException {
+ return cc.prepareStatement(sql);
+ }
+
+ @Override
+ public CallableStatement prepareCall(String sql) throws SQLException {
+ return cc.prepareCall(sql);
+ }
+
+ @Override
+ public String nativeSQL(String sql) throws SQLException {
+ return cc.nativeSQL(sql);
+ }
+
+ @Override
+ public void setAutoCommit(boolean autoCommit) throws SQLException {
+ cc.setAutoCommit(autoCommit);
+ }
+
+ @Override
+ public boolean getAutoCommit() throws SQLException {
+ return cc.getAutoCommit();
+ }
+
+ @Override
+ public void commit() throws SQLException {
+ cc.commit();
+ }
+
+ @Override
+ public void rollback() throws SQLException {
+ cc.rollback();
+ }
+
+ @Override
+ public void close() throws SQLException {
+ }
+
+ @Override
+ public boolean isClosed() throws SQLException {
+ return cc.isClosed();
+ }
+
+ @Override
+ public DatabaseMetaData getMetaData() throws SQLException {
+ return cc.getMetaData();
+ }
+
+ @Override
+ public void setReadOnly(boolean readOnly) throws SQLException {
+ cc.setReadOnly(readOnly);
+ }
+
+ @Override
+ public boolean isReadOnly() throws SQLException {
+ return cc.isReadOnly();
+ }
+
+ @Override
+ public void setCatalog(String catalog) throws SQLException {
+ cc.setCatalog(catalog);
+ }
+
+ @Override
+ public String getCatalog() throws SQLException {
+ return cc.getCatalog();
+ }
+
+ @Override
+ public void setTransactionIsolation(int level) throws SQLException {
+ cc.setTransactionIsolation(level);
+ }
+
+ @Override
+ public int getTransactionIsolation() throws SQLException {
+ return cc.getTransactionIsolation();
+ }
+
+ @Override
+ public SQLWarning getWarnings() throws SQLException {
+ return cc.getWarnings();
+ }
+
+ @Override
+ public void clearWarnings() throws SQLException {
+ cc.clearWarnings();
+ }
+
+ @Override
+ public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException {
+ return cc.createStatement(resultSetType, resultSetConcurrency);
+ }
+
+ @Override
+ public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency)
+ throws SQLException {
+ return cc.prepareStatement(sql, resultSetType, resultSetConcurrency);
+ }
+
+ @Override
+ public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
+ return cc.prepareCall(sql, resultSetType, resultSetConcurrency);
+ }
+
+ @Override
+ public Map<String, Class<?>> getTypeMap() throws SQLException {
+ return cc.getTypeMap();
+ }
+
+ @Override
+ public void setTypeMap(Map<String, Class<?>> map) throws SQLException {
+ cc.setTypeMap(map);
+ }
+
+ @Override
+ public void setHoldability(int holdability) throws SQLException {
+ cc.setHoldability(holdability);
+ }
+
+ @Override
+ public int getHoldability() throws SQLException {
+ return cc.getHoldability();
+ }
+
+ @Override
+ public Savepoint setSavepoint() throws SQLException {
+ return cc.setSavepoint();
+ }
+
+ @Override
+ public Savepoint setSavepoint(String name) throws SQLException {
+ return cc.setSavepoint(name);
+ }
+
+ @Override
+ public void rollback(Savepoint savepoint) throws SQLException {
+ cc.rollback(savepoint);
+ }
+
+ @Override
+ public void releaseSavepoint(Savepoint savepoint) throws SQLException {
+ cc.releaseSavepoint(savepoint);
+ }
+
+ @Override
+ public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability)
+ throws SQLException {
+ return cc.createStatement(resultSetType, resultSetConcurrency, resultSetHoldability);
+ }
+
+ @Override
+ public PreparedStatement prepareStatement(
+ String sql,
+ int resultSetType,
+ int resultSetConcurrency,
+ int resultSetHoldability) throws SQLException {
+ return cc.prepareStatement(sql, resultSetType, resultSetConcurrency, resultSetHoldability);
+ }
+
+ @Override
+ public CallableStatement prepareCall(
+ String sql,
+ int resultSetType,
+ int resultSetConcurrency,
+ int resultSetHoldability) throws SQLException {
+ return cc.prepareCall(sql, resultSetType, resultSetConcurrency, resultSetHoldability);
+ }
+
+ @Override
+ public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException {
+ return cc.prepareStatement(sql, autoGeneratedKeys);
+ }
+
+ @Override
+ public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException {
+ return cc.prepareStatement(sql, columnIndexes);
+ }
+
+ @Override
+ public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException {
+ return cc.prepareStatement(sql, columnNames);
+ }
+
+ @Override
+ public Clob createClob() throws SQLException {
+ return cc.createClob();
+ }
+
+ @Override
+ public Blob createBlob() throws SQLException {
+ return cc.createBlob();
+ }
+
+ @Override
+ public NClob createNClob() throws SQLException {
+ return cc.createNClob();
+ }
+
+ @Override
+ public SQLXML createSQLXML() throws SQLException {
+ return cc.createSQLXML();
+ }
+
+ @Override
+ public boolean isValid(int timeout) throws SQLException {
+ return cc.isValid(timeout);
+ }
+
+ @Override
+ public void setClientInfo(String name, String value) throws SQLClientInfoException {
+ cc.setClientInfo(name, value);
+ }
+
+ @Override
+ public void setClientInfo(Properties properties) throws SQLClientInfoException {
+ cc.setClientInfo(properties);
+ }
+
+ @Override
+ public String getClientInfo(String name) throws SQLException {
+ return cc.getClientInfo(name);
+ }
+
+ @Override
+ public Properties getClientInfo() throws SQLException {
+ return cc.getClientInfo();
+ }
+
+ @Override
+ public Array createArrayOf(String typeName, Object[] elements) throws SQLException {
+ return cc.createArrayOf(typeName, elements);
+ }
+
+ @Override
+ public Struct createStruct(String typeName, Object[] attributes) throws SQLException {
+ return cc.createStruct(typeName, attributes);
+ }
+
+ @Override
+ public void setSchema(String schema) throws SQLException {
+ cc.setSchema(schema);
+ }
+
+ @Override
+ public String getSchema() throws SQLException {
+ return cc.getSchema();
+ }
+
+ @Override
+ public void abort(Executor executor) throws SQLException {
+ cc.abort(executor);
+ }
+
+ @Override
+ public void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException {
+ cc.setNetworkTimeout(executor, milliseconds);
+ }
+
+ @Override
+ public int getNetworkTimeout() throws SQLException {
+ return cc.getNetworkTimeout();
+ }
+}
diff --git a/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/util/db/DataSourceWrap.java b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/util/db/DataSourceWrap.java
new file mode 100644
index 000000000..2aebb83e3
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/util/db/DataSourceWrap.java
@@ -0,0 +1,98 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.util.db;
+
+import java.io.PrintWriter;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.sql.SQLFeatureNotSupportedException;
+
+import javax.sql.DataSource;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class DataSourceWrap implements DataSource {
+
+ private static final Logger log = LoggerFactory.getLogger(DataSourceWrap.class);
+
+ private DataSource dataSource;
+
+ @Override
+ public PrintWriter getLogWriter() throws SQLException {
+ return dataSource.getLogWriter();
+ }
+
+ @Override
+ public void setLogWriter(PrintWriter out) throws SQLException {
+ dataSource.setLogWriter(out);
+ }
+
+ @Override
+ public void setLoginTimeout(int seconds) throws SQLException {
+ dataSource.setLoginTimeout(seconds);
+ }
+
+ @Override
+ public int getLoginTimeout() throws SQLException {
+ return dataSource.getLoginTimeout();
+ }
+
+ @Override
+ public java.util.logging.Logger getParentLogger() throws SQLFeatureNotSupportedException {
+ return dataSource.getParentLogger();
+ }
+
+ @Override
+ public <T> T unwrap(Class<T> iface) throws SQLException {
+ return dataSource.unwrap(iface);
+ }
+
+ @Override
+ public boolean isWrapperFor(Class<?> iface) throws SQLException {
+ return dataSource.isWrapperFor(iface);
+ }
+
+ @Override
+ public Connection getConnection() throws SQLException {
+ Connection c = dataSource.getConnection();
+
+ log.debug("getConnection: " + c.getClass().getName());
+
+ c.setAutoCommit(true);
+ return c;
+ }
+
+ @Override
+ public Connection getConnection(String username, String password) throws SQLException {
+ Connection c = dataSource.getConnection(username, password);
+
+ log.debug("getConnection: " + c.getClass().getName());
+
+ c.setAutoCommit(true);
+ return c;
+ }
+
+ public void setDataSource(DataSource dataSource) {
+ this.dataSource = dataSource;
+ }
+}
diff --git a/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/util/expr/ExpressionEvaluator.java b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/util/expr/ExpressionEvaluator.java
new file mode 100644
index 000000000..8092a7515
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/util/expr/ExpressionEvaluator.java
@@ -0,0 +1,271 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.util.expr;
+
+import java.util.Map;
+
+public class ExpressionEvaluator {
+
+ public static long evalLong(String expr, Map<String, String> vars) {
+ return (long) evalFloat(expr, vars);
+ }
+
+ public static float evalFloat(String expr, Map<String, String> vars) {
+ expr = expr.trim();
+ int sl = expr.length();
+ if (sl == 0) {
+ throw new IllegalArgumentException("Cannot interpret empty string.");
+ }
+
+ // Remove parentheses if any
+ if (expr.charAt(0) == '(' && expr.charAt(sl - 1) == ')') {
+ return evalFloat(expr.substring(1, sl - 1), vars);
+ }
+
+ // Look for operators in the order of least priority
+ String[] sss = findOperator(expr, "-", true);
+ if (sss != null) {
+ return evalFloat(sss[0], vars) - evalFloat(sss[1], vars);
+ }
+
+ sss = findOperator(expr, "+", true);
+ if (sss != null) {
+ return evalFloat(sss[0], vars) + evalFloat(sss[1], vars);
+ }
+
+ sss = findOperator(expr, "/", true);
+ if (sss != null) {
+ return evalFloat(sss[0], vars) / evalFloat(sss[1], vars);
+ }
+
+ sss = findOperator(expr, "*", true);
+ if (sss != null) {
+ return evalFloat(sss[0], vars) * evalFloat(sss[1], vars);
+ }
+
+ // Check if expr is a number
+ try {
+ return Float.valueOf(expr);
+ } catch (Exception e) {
+ }
+
+ // Must be a variable
+ String v = vars.get(expr);
+ try {
+ return Float.valueOf(v);
+ } catch (Exception e) {
+ }
+ return 0;
+ }
+
+ public static String evalString(String expr, Map<String, String> vars) {
+ expr = expr.trim();
+ int sl = expr.length();
+ if (sl == 0) {
+ throw new IllegalArgumentException("Cannot interpret empty string.");
+ }
+
+ // Remove parentheses if any
+ if (expr.charAt(0) == '(' && expr.charAt(sl - 1) == ')') {
+ return evalString(expr.substring(1, sl - 1), vars);
+ }
+
+ // Look for operators in the order of least priority
+ String[] sss = findOperator(expr, "+", true);
+ if (sss != null) {
+ return evalString(sss[0], vars) + evalString(sss[1], vars);
+ }
+
+ // Check if expr is a number
+ try {
+ return Float.valueOf(expr).toString();
+ } catch (Exception e) {
+ }
+
+ // Check for quotes
+ if (expr.charAt(0) == '"' && expr.charAt(sl - 1) == '"') {
+ return expr.substring(1, sl - 1);
+ }
+ if (expr.charAt(0) == '\'' && expr.charAt(sl - 1) == '\'') {
+ return expr.substring(1, sl - 1);
+ }
+
+ // Must be a variable
+ String v = vars.get(expr);
+ return v != null ? v : "";
+ }
+
+ public static boolean evalBoolean(String expr, Map<String, String> vars) {
+ expr = expr.trim();
+ int sl = expr.length();
+ if (sl == 0) {
+ throw new IllegalArgumentException("Cannot interpret empty string.");
+ }
+
+ if (expr.equalsIgnoreCase("true")) {
+ return true;
+ }
+
+ if (expr.equalsIgnoreCase("false")) {
+ return false;
+ }
+
+ // Remove parentheses if any
+ if (expr.charAt(0) == '(' && expr.charAt(sl - 1) == ')') {
+ return evalBoolean(expr.substring(1, sl - 1), vars);
+ }
+
+ // Look for operators in the order of least priority
+ String[] sss = findOperator(expr, "or", true);
+ if (sss != null) {
+ return evalBoolean(sss[0], vars) || evalBoolean(sss[1], vars);
+ }
+
+ sss = findOperator(expr, "and", true);
+ if (sss != null) {
+ return evalBoolean(sss[0], vars) && evalBoolean(sss[1], vars);
+ }
+
+ sss = findOperator(expr, "not", true);
+ if (sss != null) {
+ return !evalBoolean(sss[1], vars);
+ }
+
+ sss = findOperator(expr, "!=", false);
+ if (sss == null) {
+ sss = findOperator(expr, "<>", false);
+ }
+ if (sss != null) {
+ return !evalString(sss[0], vars).equals(evalString(sss[1], vars));
+ }
+
+ sss = findOperator(expr, "==", false);
+ if (sss == null) {
+ sss = findOperator(expr, "=", false);
+ }
+ if (sss != null) {
+ return evalString(sss[0], vars).equals(evalString(sss[1], vars));
+ }
+
+ sss = findOperator(expr, ">=", false);
+ if (sss != null) {
+ return evalLong(sss[0], vars) >= evalLong(sss[1], vars);
+ }
+
+ sss = findOperator(expr, ">", false);
+ if (sss != null) {
+ return evalLong(sss[0], vars) > evalLong(sss[1], vars);
+ }
+
+ sss = findOperator(expr, "<=", false);
+ if (sss != null) {
+ return evalLong(sss[0], vars) <= evalLong(sss[1], vars);
+ }
+
+ sss = findOperator(expr, "<", false);
+ if (sss != null) {
+ return evalLong(sss[0], vars) < evalLong(sss[1], vars);
+ }
+
+ throw new IllegalArgumentException("Cannot interpret '" + expr + "': Invalid expression.");
+ }
+
+ private static String[] findOperator(String s, String op, boolean delimiterRequired) {
+ int opl = op.length();
+ int sl = s.length();
+ String delimiters = " \0\t\r\n()";
+ int pcount = 0;
+ int qcount = 0;
+ for (int i = 0; i < sl; i++) {
+ char c = s.charAt(i);
+ if (c == '(' && qcount == 0) {
+ pcount++;
+ } else if (c == ')' && qcount == 0) {
+ pcount--;
+ if (pcount < 0) {
+ throw new IllegalArgumentException("Cannot interpret '" + s + "': Parentheses do not match.");
+ }
+ } else if (c == '\'') {
+ qcount = (qcount + 1) % 2;
+ } else if (i <= sl - opl && pcount == 0 && qcount == 0) {
+ String ss = s.substring(i, i + opl);
+ if (ss.equalsIgnoreCase(op)) {
+ boolean found = true;
+ if (delimiterRequired) {
+ // Check for delimiter before and after to make sure it is not part of another word
+ char chbefore = '\0';
+ if (i > 0) {
+ chbefore = s.charAt(i - 1);
+ }
+ char chafter = '\0';
+ if (i < sl - opl) {
+ chafter = s.charAt(i + opl);
+ }
+ found = delimiters.indexOf(chbefore) >= 0 && delimiters.indexOf(chafter) >= 0;
+ }
+ if (found) {
+ // We've found the operator, split the string
+ String[] sss = new String[2];
+ sss[0] = s.substring(0, i);
+ sss[1] = s.substring(i + opl);
+ return sss;
+ }
+ }
+ }
+ }
+ if (pcount > 0) {
+ throw new IllegalArgumentException("Cannot interpret '" + s + "': Parentheses do not match.");
+ }
+ if (qcount > 0) {
+ throw new IllegalArgumentException("Cannot interpret '" + s + "': No closing '.");
+ }
+ return null;
+ }
+
+ @SuppressWarnings("unused")
+ private static Object parseObject(String s) {
+ s = s.trim();
+ int sl = s.length();
+ if (sl == 0) {
+ throw new IllegalArgumentException("Cannot interpret empty string.");
+ }
+ if (s.equalsIgnoreCase("null")) {
+ return null;
+ }
+ if (s.charAt(0) == '\'') {
+ if (sl < 2 || s.charAt(sl - 1) != '\'') {
+ throw new IllegalArgumentException("Cannot interpret '" + s + "': No closing '.");
+ }
+ return s.substring(1, sl - 1);
+ }
+ // Not in quotes - must be a number
+ try {
+ return Long.valueOf(s);
+ } catch (Exception e) {
+ }
+ try {
+ return Double.valueOf(s);
+ } catch (Exception e) {
+ throw new IllegalArgumentException("Cannot interpret '" + s + "': Invalid number.");
+ }
+ }
+}
diff --git a/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/util/speed/SpeedUtil.java b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/util/speed/SpeedUtil.java
new file mode 100644
index 000000000..0d1359cf3
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/util/speed/SpeedUtil.java
@@ -0,0 +1,57 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.util.speed;
+
+public class SpeedUtil {
+
+ private long unitFactor = 1000;
+
+ public long convertToKbps(long maxSpeed, String unit) {
+ if (unit.equalsIgnoreCase("kbps")) {
+ return maxSpeed;
+ }
+ if (unit.equalsIgnoreCase("Mbps")) {
+ return maxSpeed * unitFactor;
+ }
+ if (unit.equalsIgnoreCase("Gbps")) {
+ return maxSpeed * unitFactor * unitFactor;
+ }
+ return 0;
+ }
+
+ public long convertToMbps(long maxSpeed, String unit) {
+ if (unit.equalsIgnoreCase("kbps")) {
+ return maxSpeed / unitFactor;
+ }
+ if (unit.equalsIgnoreCase("Mbps")) {
+ return maxSpeed;
+ }
+ if (unit.equalsIgnoreCase("Gbps")) {
+ return maxSpeed * unitFactor;
+ }
+ return 0;
+ }
+
+ public void setUnitFactor(long unitFactor) {
+ this.unitFactor = unitFactor;
+ }
+}
diff --git a/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/util/str/StrUtil.java b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/util/str/StrUtil.java
new file mode 100644
index 000000000..126ec94e5
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/java/org/onap/ccsdk/sli/adaptors/util/str/StrUtil.java
@@ -0,0 +1,306 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.util.str;
+
+import java.lang.reflect.Array;
+import java.lang.reflect.Field;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class StrUtil {
+
+ private static final Logger log = LoggerFactory.getLogger(StrUtil.class);
+
+ public static final String INDENT_STR = " ";
+
+ public static void indent(StringBuilder ss, int ind) {
+ for (int i = 0; i < ind; i++)
+ ss.append(INDENT_STR);
+ }
+
+ public static void info(Logger log, Object o) {
+ if (log.isInfoEnabled()) {
+ StringBuilder ss = new StringBuilder();
+ struct(ss, o);
+ log.info(ss.toString());
+ }
+ }
+
+ public static void debug(Logger log, Object o) {
+ if (log.isDebugEnabled()) {
+ StringBuilder ss = new StringBuilder();
+ struct(ss, o);
+ log.debug(ss.toString());
+ }
+ }
+
+ public static void struct(StringBuilder ss, Object o) {
+ struct(ss, o, 0);
+ }
+
+ public static void struct(StringBuilder ss, Object o, int ind) {
+ if (o == null) {
+ ss.append("null");
+ return;
+ }
+
+ if (isSimple(o)) {
+ ss.append(o);
+ return;
+ }
+
+ Class<? extends Object> cls = o.getClass();
+
+ if (cls.isEnum()) {
+ ss.append(o);
+ return;
+ }
+
+ if (cls.isArray()) {
+ int n = Array.getLength(o);
+ if (n == 0) {
+ ss.append("[]");
+ return;
+ }
+
+ Object o1 = Array.get(o, 0);
+ if (isSimple(o1)) {
+ ss.append('[').append(o1);
+ for (int i = 1; i < n; i++) {
+ o1 = Array.get(o, i);
+ ss.append(", ").append(o1);
+ }
+ ss.append(']');
+ return;
+ }
+
+ ss.append('\n');
+ indent(ss, ind + 1);
+ ss.append('[');
+ struct(ss, o1, ind + 1);
+ for (int i = 1; i < n; i++) {
+ o1 = Array.get(o, i);
+ struct(ss, o1, ind + 1);
+ }
+ ss.append('\n');
+ indent(ss, ind + 1);
+ ss.append(']');
+ return;
+ }
+
+ if (o instanceof Collection<?>) {
+ Collection<?> ll = (Collection<?>) o;
+
+ int n = ll.size();
+ if (n == 0) {
+ ss.append("[]");
+ return;
+ }
+
+ Iterator<?> ii = ll.iterator();
+ Object o1 = ii.next();
+ if (isSimple(o1)) {
+ ss.append('[').append(o1);
+ while (ii.hasNext()) {
+ o1 = ii.next();
+ ss.append(", ").append(o1);
+ }
+ ss.append(']');
+ return;
+ }
+
+ ss.append('\n');
+ indent(ss, ind + 1);
+ ss.append('[');
+ struct(ss, o1, ind + 1);
+ while (ii.hasNext()) {
+ o1 = ii.next();
+ struct(ss, o1, ind + 1);
+ }
+ ss.append('\n');
+ indent(ss, ind + 1);
+ ss.append(']');
+ return;
+
+ }
+
+ if (o instanceof Map<?, ?>) {
+ Map<?, ?> mm = (Map<?, ?>) o;
+
+ int n = mm.size();
+ if (n == 0) {
+ ss.append("{}");
+ return;
+ }
+
+ ss.append('{');
+
+ for (Object k : mm.keySet()) {
+ ss.append('\n');
+ indent(ss, ind + 1);
+ ss.append(k).append(": ");
+
+ Object o1 = mm.get(k);
+ struct(ss, o1, ind + 2);
+ }
+
+ ss.append('\n');
+ indent(ss, ind);
+ ss.append('}');
+
+ return;
+ }
+
+ Field[] fields = cls.getFields();
+
+ if (fields.length == 0) {
+ ss.append(o);
+ return;
+ }
+
+ ss.append('\n');
+ indent(ss, ind + 1);
+ ss.append('<').append(cls.getSimpleName()).append("> {");
+ for (Field f : fields) {
+ ss.append('\n');
+ indent(ss, ind + 2);
+ ss.append(f.getName()).append(": ");
+ Object v = null;
+ try {
+ v = f.get(o);
+ } catch (IllegalAccessException e) {
+ v = "*** Cannot obtain value *** : " + e.getMessage();
+ }
+ struct(ss, v, ind + 2);
+ }
+ ss.append('\n');
+ indent(ss, ind + 1);
+ ss.append('}');
+ }
+
+ public static SortedSet<Integer> listInt(String ss, String warning) {
+ if (ss == null || ss.length() == 0)
+ return null;
+
+ SortedSet<Integer> ll = new TreeSet<Integer>();
+ String[] str = ss.split(",");
+ for (String s : str) {
+ try {
+ int i1 = s.indexOf('-');
+ int start;
+ int end;
+ if (i1 > 0) {
+ String s1 = s.substring(0, i1);
+ String s2 = s.substring(i1 + 1);
+ start = Integer.parseInt(s1);
+ end = Integer.parseInt(s2);
+ } else
+ start = end = Integer.parseInt(s);
+ for (int i = start; i <= end; i++)
+ ll.add(i);
+ } catch (NumberFormatException e) {
+ // Skip this - bad data in DB
+ log.warn(warning + " [" + s + "].", e);
+ }
+ }
+ return ll;
+ }
+
+ public static String listInt(SortedSet<Integer> ll) {
+ if (ll == null || ll.size() == 0)
+ return null;
+
+ StringBuilder sb = new StringBuilder(2000);
+ Iterator<Integer> i = ll.iterator();
+ int n = i.next();
+ int start = n;
+ int end = n;
+ boolean first = true;
+ while (i.hasNext()) {
+ n = i.next();
+ if (n != end + 1) {
+ if (!first)
+ sb.append(',');
+ first = false;
+
+ if (start == end)
+ sb.append(start);
+ else if (start == end - 1)
+ sb.append(start).append(',').append(end);
+ else
+ sb.append(start).append('-').append(end);
+
+ start = n;
+ }
+ end = n;
+ }
+
+ if (!first)
+ sb.append(',');
+
+ if (start == end)
+ sb.append(start);
+ else if (start == end - 1)
+ sb.append(start).append(',').append(end);
+ else
+ sb.append(start).append('-').append(end);
+
+ return sb.toString();
+ }
+
+ public static List<String> listStr(String s) {
+ if (s == null || s.length() == 0)
+ return null;
+ String[] ss = s.split(",");
+ return Arrays.asList(ss);
+ }
+
+ public static String listStr(Collection<String> ll) {
+ if (ll == null || ll.isEmpty())
+ return null;
+ StringBuilder ss = new StringBuilder(1000);
+ Iterator<String> i = ll.iterator();
+ ss.append(i.next());
+ while (i.hasNext())
+ ss.append(',').append(i.next());
+ return ss.toString();
+ }
+
+ private static boolean isSimple(Object o) {
+ if (o == null)
+ return true;
+
+ if (o instanceof Number || o instanceof String || o instanceof Boolean || o instanceof Date)
+ return true;
+
+ return false;
+ }
+}
diff --git a/adaptors/resource-assignment/provider/src/main/resources/OSGI-INF/blueprint/resource-assignment-blueprint.xml b/adaptors/resource-assignment/provider/src/main/resources/OSGI-INF/blueprint/resource-assignment-blueprint.xml
new file mode 100755
index 000000000..77c316d2a
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/resources/OSGI-INF/blueprint/resource-assignment-blueprint.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ============LICENSE_START=======================================================
+ openECOMP : SDN-C
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property. All rights
+ reserved.
+ ================================================================================
+ 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.
+ ============LICENSE_END=========================================================
+ -->
+
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+ xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0"
+ odl:use-default-for-reference-types="true">
+
+ <reference id="dblib.dataSource" interface="javax.sql.DataSource" filter="(objectClass=org.onap.ccsdk.sli.core.dblib.DbLibService)"/>
+
+ <service ref="resourceAllocator" interface="org.onap.ccsdk.sli.adaptors.ra.ResourceAllocator"/>
+
+ <service ref="resourceLockNode" interface="org.onap.ccsdk.sli.adaptors.ra.ResourceLockNode"/>
+
+</blueprint>
diff --git a/adaptors/resource-assignment/provider/src/main/resources/OSGI-INF/blueprint/resource-assignment.xml b/adaptors/resource-assignment/provider/src/main/resources/OSGI-INF/blueprint/resource-assignment.xml
new file mode 100755
index 000000000..7fcc70c54
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/resources/OSGI-INF/blueprint/resource-assignment.xml
@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ============LICENSE_START=======================================================
+ openECOMP : SDN-C
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property. All rights
+ reserved.
+ ================================================================================
+ 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.
+ ============LICENSE_END=========================================================
+ -->
+
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+ xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0"
+ odl:use-default-for-reference-types="true">
+
+ <!-- JDBC setup -->
+
+ <bean id="rm.dataSource" class="org.onap.ccsdk.sli.adaptors.util.db.DataSourceWrap">
+ <property name="dataSource" ref="dblib.dataSource" />
+ </bean>
+
+ <bean id="lock.dataSource" class="org.onap.ccsdk.sli.adaptors.util.db.CachedDataSourceWrap">
+ <property name="dataSource" ref="rm.dataSource" />
+ </bean>
+
+ <bean id="rm.jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
+ <property name="dataSource" ref="rm.dataSource" />
+ </bean>
+
+ <bean id="lock.jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
+ <property name="dataSource" ref="lock.dataSource" />
+ </bean>
+
+ <!-- Resource Lock Configuration -->
+
+ <bean id="resourceLockDao" class="org.onap.ccsdk.sli.adaptors.lock.dao.ResourceLockDaoImpl">
+ <property name="jdbcTemplate" ref="lock.jdbcTemplate" />
+ </bean>
+
+ <bean id="lockHelper" class="org.onap.ccsdk.sli.adaptors.lock.comp.LockHelperImpl">
+ <property name="resourceLockDao" ref="resourceLockDao" />
+ <property name="retryCount" value="10" />
+ <property name="lockWait" value="5" /> <!-- Seconds -->
+ </bean>
+
+ <!-- RM Configuration -->
+
+ <bean id="resourceJdbcDao" class="org.onap.ccsdk.sli.adaptors.rm.dao.jdbc.ResourceJdbcDaoImpl">
+ <property name="jdbcTemplate" ref="rm.jdbcTemplate" />
+ </bean>
+
+ <bean id="allocationItemJdbcDao" class="org.onap.ccsdk.sli.adaptors.rm.dao.jdbc.AllocationItemJdbcDaoImpl">
+ <property name="jdbcTemplate" ref="rm.jdbcTemplate" />
+ </bean>
+
+ <bean id="resourceLoadJdbcDao" class="org.onap.ccsdk.sli.adaptors.rm.dao.jdbc.ResourceLoadJdbcDaoImpl">
+ <property name="jdbcTemplate" ref="rm.jdbcTemplate" />
+ </bean>
+
+ <bean id="resourceDao" class="org.onap.ccsdk.sli.adaptors.rm.dao.jdbc.ResourceDaoImpl">
+ <property name="resourceJdbcDao" ref="resourceJdbcDao" />
+ <property name="allocationItemJdbcDao" ref="allocationItemJdbcDao" />
+ <property name="resourceLoadJdbcDao" ref="resourceLoadJdbcDao" />
+ </bean>
+
+ <bean id="resourceManager" class="org.onap.ccsdk.sli.adaptors.rm.comp.ResourceManagerImpl">
+ <property name="lockHelper" ref="lockHelper" />
+ <property name="resourceDao" ref="resourceDao" />
+ <property name="lockTimeout" value="600" /> <!-- Seconds -->
+ </bean>
+
+ <!-- Rule DAO Configuration -->
+
+ <bean id="resourceRuleDao" class="org.onap.ccsdk.sli.adaptors.ra.rule.dao.ResourceRuleDaoImpl">
+ <property name="jdbcTemplate" ref="rm.jdbcTemplate" />
+ </bean>
+
+ <bean id="rangeRuleDao" class="org.onap.ccsdk.sli.adaptors.ra.rule.dao.RangeRuleDaoImpl">
+ <property name="jdbcTemplate" ref="rm.jdbcTemplate" />
+ </bean>
+
+ <!-- ResourceAllocator Configuration -->
+
+ <bean id="resourceAllocator" class="org.onap.ccsdk.sli.adaptors.ra.ResourceAllocator">
+ <property name="resourceManager" ref="resourceManager" />
+ <property name="endPointAllocator" ref="endPointAllocator" />
+ <property name="speedUtil" ref="speedUtil" />
+ </bean>
+
+ <bean id="resourceLockNode" class="org.onap.ccsdk.sli.adaptors.ra.ResourceLockNode">
+ <property name="lockHelper" ref="lockHelper" />
+ </bean>
+
+ <bean id="speedUtil" class="org.onap.ccsdk.sli.adaptors.util.speed.SpeedUtil" />
+
+ <!-- EndPointAllocator Configuration -->
+
+ <bean id="endPointAllocator" class="org.onap.ccsdk.sli.adaptors.ra.comp.EndPointAllocatorImpl">
+ <property name="resourceManager" ref="resourceManager" />
+ <property name="allocationRuleMap">
+ <map>
+ <entry key="DEFAULT">
+ <list>
+ <ref component-id="dbAllocationRule" />
+ </list>
+ </entry>
+ </map>
+ </property>
+ </bean>
+
+ <!-- Resource Allocation Rule Configuration -->
+
+ <bean id="dbAllocationRule" class="org.onap.ccsdk.sli.adaptors.ra.alloc.DbAllocationRule">
+ <property name="resourceRuleDao" ref="resourceRuleDao" />
+ <property name="rangeRuleDao" ref="rangeRuleDao" />
+ </bean>
+
+</blueprint>
diff --git a/adaptors/resource-assignment/provider/src/main/resources/org/opendaylight/blueprint/resource-assignment-blueprint.xml b/adaptors/resource-assignment/provider/src/main/resources/org/opendaylight/blueprint/resource-assignment-blueprint.xml
new file mode 100755
index 000000000..77c316d2a
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/resources/org/opendaylight/blueprint/resource-assignment-blueprint.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ============LICENSE_START=======================================================
+ openECOMP : SDN-C
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property. All rights
+ reserved.
+ ================================================================================
+ 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.
+ ============LICENSE_END=========================================================
+ -->
+
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+ xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0"
+ odl:use-default-for-reference-types="true">
+
+ <reference id="dblib.dataSource" interface="javax.sql.DataSource" filter="(objectClass=org.onap.ccsdk.sli.core.dblib.DbLibService)"/>
+
+ <service ref="resourceAllocator" interface="org.onap.ccsdk.sli.adaptors.ra.ResourceAllocator"/>
+
+ <service ref="resourceLockNode" interface="org.onap.ccsdk.sli.adaptors.ra.ResourceLockNode"/>
+
+</blueprint>
diff --git a/adaptors/resource-assignment/provider/src/main/resources/org/opendaylight/blueprint/resource-assignment.xml b/adaptors/resource-assignment/provider/src/main/resources/org/opendaylight/blueprint/resource-assignment.xml
new file mode 100755
index 000000000..7fcc70c54
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/main/resources/org/opendaylight/blueprint/resource-assignment.xml
@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ============LICENSE_START=======================================================
+ openECOMP : SDN-C
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property. All rights
+ reserved.
+ ================================================================================
+ 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.
+ ============LICENSE_END=========================================================
+ -->
+
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+ xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0"
+ odl:use-default-for-reference-types="true">
+
+ <!-- JDBC setup -->
+
+ <bean id="rm.dataSource" class="org.onap.ccsdk.sli.adaptors.util.db.DataSourceWrap">
+ <property name="dataSource" ref="dblib.dataSource" />
+ </bean>
+
+ <bean id="lock.dataSource" class="org.onap.ccsdk.sli.adaptors.util.db.CachedDataSourceWrap">
+ <property name="dataSource" ref="rm.dataSource" />
+ </bean>
+
+ <bean id="rm.jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
+ <property name="dataSource" ref="rm.dataSource" />
+ </bean>
+
+ <bean id="lock.jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
+ <property name="dataSource" ref="lock.dataSource" />
+ </bean>
+
+ <!-- Resource Lock Configuration -->
+
+ <bean id="resourceLockDao" class="org.onap.ccsdk.sli.adaptors.lock.dao.ResourceLockDaoImpl">
+ <property name="jdbcTemplate" ref="lock.jdbcTemplate" />
+ </bean>
+
+ <bean id="lockHelper" class="org.onap.ccsdk.sli.adaptors.lock.comp.LockHelperImpl">
+ <property name="resourceLockDao" ref="resourceLockDao" />
+ <property name="retryCount" value="10" />
+ <property name="lockWait" value="5" /> <!-- Seconds -->
+ </bean>
+
+ <!-- RM Configuration -->
+
+ <bean id="resourceJdbcDao" class="org.onap.ccsdk.sli.adaptors.rm.dao.jdbc.ResourceJdbcDaoImpl">
+ <property name="jdbcTemplate" ref="rm.jdbcTemplate" />
+ </bean>
+
+ <bean id="allocationItemJdbcDao" class="org.onap.ccsdk.sli.adaptors.rm.dao.jdbc.AllocationItemJdbcDaoImpl">
+ <property name="jdbcTemplate" ref="rm.jdbcTemplate" />
+ </bean>
+
+ <bean id="resourceLoadJdbcDao" class="org.onap.ccsdk.sli.adaptors.rm.dao.jdbc.ResourceLoadJdbcDaoImpl">
+ <property name="jdbcTemplate" ref="rm.jdbcTemplate" />
+ </bean>
+
+ <bean id="resourceDao" class="org.onap.ccsdk.sli.adaptors.rm.dao.jdbc.ResourceDaoImpl">
+ <property name="resourceJdbcDao" ref="resourceJdbcDao" />
+ <property name="allocationItemJdbcDao" ref="allocationItemJdbcDao" />
+ <property name="resourceLoadJdbcDao" ref="resourceLoadJdbcDao" />
+ </bean>
+
+ <bean id="resourceManager" class="org.onap.ccsdk.sli.adaptors.rm.comp.ResourceManagerImpl">
+ <property name="lockHelper" ref="lockHelper" />
+ <property name="resourceDao" ref="resourceDao" />
+ <property name="lockTimeout" value="600" /> <!-- Seconds -->
+ </bean>
+
+ <!-- Rule DAO Configuration -->
+
+ <bean id="resourceRuleDao" class="org.onap.ccsdk.sli.adaptors.ra.rule.dao.ResourceRuleDaoImpl">
+ <property name="jdbcTemplate" ref="rm.jdbcTemplate" />
+ </bean>
+
+ <bean id="rangeRuleDao" class="org.onap.ccsdk.sli.adaptors.ra.rule.dao.RangeRuleDaoImpl">
+ <property name="jdbcTemplate" ref="rm.jdbcTemplate" />
+ </bean>
+
+ <!-- ResourceAllocator Configuration -->
+
+ <bean id="resourceAllocator" class="org.onap.ccsdk.sli.adaptors.ra.ResourceAllocator">
+ <property name="resourceManager" ref="resourceManager" />
+ <property name="endPointAllocator" ref="endPointAllocator" />
+ <property name="speedUtil" ref="speedUtil" />
+ </bean>
+
+ <bean id="resourceLockNode" class="org.onap.ccsdk.sli.adaptors.ra.ResourceLockNode">
+ <property name="lockHelper" ref="lockHelper" />
+ </bean>
+
+ <bean id="speedUtil" class="org.onap.ccsdk.sli.adaptors.util.speed.SpeedUtil" />
+
+ <!-- EndPointAllocator Configuration -->
+
+ <bean id="endPointAllocator" class="org.onap.ccsdk.sli.adaptors.ra.comp.EndPointAllocatorImpl">
+ <property name="resourceManager" ref="resourceManager" />
+ <property name="allocationRuleMap">
+ <map>
+ <entry key="DEFAULT">
+ <list>
+ <ref component-id="dbAllocationRule" />
+ </list>
+ </entry>
+ </map>
+ </property>
+ </bean>
+
+ <!-- Resource Allocation Rule Configuration -->
+
+ <bean id="dbAllocationRule" class="org.onap.ccsdk.sli.adaptors.ra.alloc.DbAllocationRule">
+ <property name="resourceRuleDao" ref="resourceRuleDao" />
+ <property name="rangeRuleDao" ref="rangeRuleDao" />
+ </bean>
+
+</blueprint>
diff --git a/adaptors/resource-assignment/provider/src/test/java/jtest/org/onap/ccsdk/sli/adaptors/ra/DataSetup.java b/adaptors/resource-assignment/provider/src/test/java/jtest/org/onap/ccsdk/sli/adaptors/ra/DataSetup.java
new file mode 100644
index 000000000..9aa3f26c4
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/test/java/jtest/org/onap/ccsdk/sli/adaptors/ra/DataSetup.java
@@ -0,0 +1,108 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package jtest.org.onap.ccsdk.sli.adaptors.ra;
+
+import java.util.Date;
+import jtest.util.org.onap.ccsdk.sli.adaptors.ra.TestDb;
+import jtest.util.org.onap.ccsdk.sli.adaptors.ra.TestTable;
+
+public class DataSetup {
+
+ private TestDb testDb;
+
+ private TestTable resource = null;
+ private TestTable allocationItem = null;
+
+ private static final String[] RESOURCE_COLUMNS =
+ {"asset_id", "resource_name", "resource_type", "lt_used", "rr_used"};
+
+ private static final String[] ALLOCATION_ITEM_COLUMNS = {"resource_id", "application_id", "resource_set_id",
+ "resource_union_id", "resource_share_group_list", "lt_used", "rr_used", "allocation_time"};
+
+ private void initTables() {
+ if (resource == null) {
+ resource = testDb.table("RESOURCE", "resource_id", RESOURCE_COLUMNS);
+ }
+ if (allocationItem == null) {
+ allocationItem = testDb.table("ALLOCATION_ITEM", "allocation_item_id", ALLOCATION_ITEM_COLUMNS);
+ }
+ }
+
+ public void cleanup() {
+ initTables();
+ allocationItem.delete("true");
+ resource.delete("true");
+ }
+
+ public void setupLimitItem(String resourceName, String assetId, String resourceSetId, String resourceUnionId,
+ long used) {
+ initTables();
+
+ Long rid = resource.getId("asset_id = '" + assetId + "' AND resource_name = '" + resourceName + "'");
+ if (rid == null) {
+ resource.add(assetId, resourceName, "Limit", used, null);
+ rid = resource.getLastId();
+ }
+ allocationItem.add(rid, "SDNC", resourceSetId, resourceUnionId, null, used, null, new Date());
+ }
+
+ public void setupRangeItem(String resourceName, String assetId, String resourceSetId, String resourceUnionId,
+ String resourceShareGroup, String used) {
+ initTables();
+
+ Long rid = resource.getId("asset_id = '" + assetId + "' AND resource_name = '" + resourceName + "'");
+ if (rid == null) {
+ resource.add(assetId, resourceName, "Range", null, used);
+ rid = resource.getLastId();
+ }
+ allocationItem.add(rid, "SDNC", resourceSetId, resourceUnionId, resourceShareGroup, null, used, new Date());
+ }
+
+ public void setupRangeItem(String resourceName, String assetId, String resourceSetId, String resourceUnionId,
+ String used) {
+ setupRangeItem(resourceName, assetId, resourceSetId, resourceUnionId, null, used);
+ }
+
+ public boolean checkRangeItem(String resourceName, String assetId, String resourceSetId, String used) {
+ String where = "resource_id = (SELECT resource_id FROM RESOURCE WHERE resource_name = '" + resourceName
+ + "' AND asset_id = '" + assetId + "') AND resource_set_id = '" + resourceSetId + "'";
+ Object usedInDb = allocationItem.getColumn("rr_used", where);
+ return used.equals(usedInDb);
+ }
+
+ public boolean checkLimitItem(String resourceName, String assetId, String resourceSetId, int used) {
+ String where = "resource_id = (SELECT resource_id FROM RESOURCE WHERE resource_name = '" + resourceName
+ + "' AND asset_id = '" + assetId + "') AND resource_set_id = '" + resourceSetId + "' AND lt_used = "
+ + used;
+ return allocationItem.exists(where);
+ }
+
+ public boolean checkItemNotThere(String resourceName, String assetId, String resourceSetId) {
+ String where = "resource_id = (SELECT resource_id FROM RESOURCE WHERE resource_name = '" + resourceName
+ + "' AND asset_id = '" + assetId + "') AND resource_set_id = '" + resourceSetId + "'";
+ return !allocationItem.exists(where);
+ }
+
+ public void setTestDb(TestDb testDb) {
+ this.testDb = testDb;
+ }
+}
diff --git a/adaptors/resource-assignment/provider/src/test/java/jtest/org/onap/ccsdk/sli/adaptors/ra/TestGetResource.java b/adaptors/resource-assignment/provider/src/test/java/jtest/org/onap/ccsdk/sli/adaptors/ra/TestGetResource.java
new file mode 100644
index 000000000..04ee38115
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/test/java/jtest/org/onap/ccsdk/sli/adaptors/ra/TestGetResource.java
@@ -0,0 +1,222 @@
+package jtest.org.onap.ccsdk.sli.adaptors.ra;
+
+import org.junit.Assert;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.MethodSorters;
+import org.onap.ccsdk.sli.adaptors.ra.ResourceAllocator;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicResource.QueryStatus;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(locations = {"classpath:test-context.xml"})
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestGetResource {
+
+ private static final Logger log = LoggerFactory.getLogger(TestGetResource.class);
+
+ @Autowired(required = true)
+ private ResourceAllocator resourceAllocator;
+
+ @Autowired(required = true)
+ private DataSetup dataSetup;
+
+ private void setupResourceData() {
+ dataSetup.cleanup();
+
+ String targetId = "GBLOND2025MG2";
+ String assetId = "Device::" + targetId;
+ String resourceName = "internal-vlan";
+
+ for (int i = 0; i < 5; i++) {
+ String entityId = "TEST" + i;
+
+ String resourceUnion = "EVC::" + entityId;
+ String resourceSet = resourceUnion + "::1";
+
+ dataSetup.setupRangeItem(resourceName, assetId, resourceSet, resourceUnion, String.valueOf(i));
+ }
+
+ for (int i = 0; i < 5; i++) {
+ String entityId = "TEST" + (i + 10);
+
+ String resourceUnion = "EVC::SVLAN::" + entityId;
+ String resourceSet = resourceUnion + "::1";
+
+ dataSetup.setupRangeItem(resourceName, assetId, resourceSet, resourceUnion, String.valueOf(10 + i));
+ }
+
+ for (int i = 0; i < 5; i++) {
+ String entityId = "TEST" + (i + 20);
+
+ String resourceUnion = "EVC::" + entityId;
+ String resourceSet = resourceUnion + "::1";
+ String resourceShareGroup = "SHARE1";
+
+ dataSetup.setupRangeItem(resourceName, assetId, resourceSet, resourceUnion, resourceShareGroup,
+ String.valueOf(20 + i));
+ }
+
+ for (int i = 0; i < 5; i++) {
+ String entityId = "TEST" + (i + 30);
+
+ String resourceUnion = "EVC::SVLAN::" + entityId;
+ String resourceSet = resourceUnion + "::1";
+ String resourceShareGroup = "SHARE1";
+
+ dataSetup.setupRangeItem(resourceName, assetId, resourceSet, resourceUnion, resourceShareGroup,
+ String.valueOf(30 + i));
+ }
+ }
+
+ @Test
+ public void test001() throws Exception {
+
+ String t = "001";
+ log.info("============== get-resource node " + t + " ================================");
+ log.info("=== Test query for resource target - no additional criteria");
+
+ setupResourceData();
+
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute("ra-input.resource-target-id", "GBLOND2025MG2");
+ ctx.setAttribute("ra-input.resource-target-type", "Device");
+
+ ctx.setAttribute("ra-input.resource-name", "internal-vlan");
+
+ QueryStatus st = resourceAllocator.query("NetworkCapacity", false, null, null, "ra-output", null, ctx);
+
+ Assert.assertTrue(st == QueryStatus.SUCCESS);
+
+ Assert.assertEquals(ctx.getAttribute("ra-output.resource-list_length"), "1");
+ Assert.assertEquals(ctx.getAttribute("ra-output.resource-list[0].resource-name"), "internal-vlan");
+ Assert.assertEquals(ctx.getAttribute("ra-output.resource-list[0].resource-target-type"), "Device");
+ Assert.assertEquals(ctx.getAttribute("ra-output.resource-list[0].resource-target-id"), "GBLOND2025MG2");
+ Assert.assertEquals(ctx.getAttribute("ra-output.resource-list[0].allocated"),
+ "0, 1, 2, 3, 4, 10, 11, 12, 13, 14, 20, 21, 22, 23, 24, 30, 31, 32, 33, 34");
+ }
+
+ @Test
+ public void test002() throws Exception {
+
+ String t = "002";
+ log.info("============== get-resource node " + t + " ================================");
+ log.info("=== Test query for resource target - with resource entity condition");
+
+ setupResourceData();
+
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute("ra-input.resource-target-id", "GBLOND2025MG2");
+ ctx.setAttribute("ra-input.resource-target-type", "Device");
+
+ ctx.setAttribute("ra-input.resource-name", "internal-vlan");
+
+ ctx.setAttribute("ra-input.resource-entity-type-filter", "EVC");
+ ctx.setAttribute("ra-input.resource-entity-id-filter", "SVLAN%");
+
+ QueryStatus st = resourceAllocator.query("NetworkCapacity", false, null, null, "ra-output", null, ctx);
+
+ Assert.assertTrue(st == QueryStatus.SUCCESS);
+
+ Assert.assertEquals(ctx.getAttribute("ra-output.resource-list_length"), "1");
+ Assert.assertEquals(ctx.getAttribute("ra-output.resource-list[0].resource-name"), "internal-vlan");
+ Assert.assertEquals(ctx.getAttribute("ra-output.resource-list[0].resource-target-type"), "Device");
+ Assert.assertEquals(ctx.getAttribute("ra-output.resource-list[0].resource-target-id"), "GBLOND2025MG2");
+ Assert.assertEquals(ctx.getAttribute("ra-output.resource-list[0].allocated"),
+ "10, 11, 12, 13, 14, 30, 31, 32, 33, 34");
+ }
+
+ @Test
+ public void test003() throws Exception {
+
+ String t = "003";
+ log.info("============== get-resource node " + t + " ================================");
+ log.info("=== Test query for resource target - with resource share group condition");
+
+ setupResourceData();
+
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute("ra-input.resource-target-id", "GBLOND2025MG2");
+ ctx.setAttribute("ra-input.resource-target-type", "Device");
+
+ ctx.setAttribute("ra-input.resource-name", "internal-vlan");
+
+ ctx.setAttribute("ra-input.resource-share-group-filter", "SHARE1");
+
+ QueryStatus st = resourceAllocator.query("NetworkCapacity", false, null, null, "ra-output", null, ctx);
+
+ Assert.assertTrue(st == QueryStatus.SUCCESS);
+
+ Assert.assertEquals(ctx.getAttribute("ra-output.resource-list_length"), "1");
+ Assert.assertEquals(ctx.getAttribute("ra-output.resource-list[0].resource-name"), "internal-vlan");
+ Assert.assertEquals(ctx.getAttribute("ra-output.resource-list[0].resource-target-type"), "Device");
+ Assert.assertEquals(ctx.getAttribute("ra-output.resource-list[0].resource-target-id"), "GBLOND2025MG2");
+ Assert.assertEquals(ctx.getAttribute("ra-output.resource-list[0].allocated"),
+ "20, 21, 22, 23, 24, 30, 31, 32, 33, 34");
+ }
+
+ @Test
+ public void test004() throws Exception {
+
+ String t = "004";
+ log.info("============== get-resource node " + t + " ================================");
+ log.info("=== Test query for resource target - with resource share group condition NULL");
+
+ setupResourceData();
+
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute("ra-input.resource-target-id", "GBLOND2025MG2");
+ ctx.setAttribute("ra-input.resource-target-type", "Device");
+
+ ctx.setAttribute("ra-input.resource-name", "internal-vlan");
+
+ ctx.setAttribute("ra-input.resource-share-group-filter", "null");
+
+ QueryStatus st = resourceAllocator.query("NetworkCapacity", false, null, null, "ra-output", null, ctx);
+
+ Assert.assertTrue(st == QueryStatus.SUCCESS);
+
+ Assert.assertEquals(ctx.getAttribute("ra-output.resource-list_length"), "1");
+ Assert.assertEquals(ctx.getAttribute("ra-output.resource-list[0].resource-name"), "internal-vlan");
+ Assert.assertEquals(ctx.getAttribute("ra-output.resource-list[0].resource-target-type"), "Device");
+ Assert.assertEquals(ctx.getAttribute("ra-output.resource-list[0].resource-target-id"), "GBLOND2025MG2");
+ Assert.assertEquals(ctx.getAttribute("ra-output.resource-list[0].allocated"),
+ "0, 1, 2, 3, 4, 10, 11, 12, 13, 14");
+ }
+
+ @Test
+ public void test005() throws Exception {
+
+ String t = "005";
+ log.info("============== get-resource node " + t + " ================================");
+ log.info("=== Test query for resource target - with both resource entity and resource share group conditions");
+
+ setupResourceData();
+
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute("ra-input.resource-target-id", "GBLOND2025MG2");
+ ctx.setAttribute("ra-input.resource-target-type", "Device");
+
+ ctx.setAttribute("ra-input.resource-name", "internal-vlan");
+
+ ctx.setAttribute("ra-input.resource-entity-type-filter", "EVC");
+ ctx.setAttribute("ra-input.resource-entity-id-filter", "SVLAN%");
+ ctx.setAttribute("ra-input.resource-share-group-filter", "null");
+
+ QueryStatus st = resourceAllocator.query("NetworkCapacity", false, null, null, "ra-output", null, ctx);
+
+ Assert.assertTrue(st == QueryStatus.SUCCESS);
+
+ Assert.assertEquals(ctx.getAttribute("ra-output.resource-list_length"), "1");
+ Assert.assertEquals(ctx.getAttribute("ra-output.resource-list[0].resource-name"), "internal-vlan");
+ Assert.assertEquals(ctx.getAttribute("ra-output.resource-list[0].resource-target-type"), "Device");
+ Assert.assertEquals(ctx.getAttribute("ra-output.resource-list[0].resource-target-id"), "GBLOND2025MG2");
+ Assert.assertEquals(ctx.getAttribute("ra-output.resource-list[0].allocated"), "10, 11, 12, 13, 14");
+ }
+}
diff --git a/adaptors/resource-assignment/provider/src/test/java/jtest/org/onap/ccsdk/sli/adaptors/ra/TestLockHelper.java b/adaptors/resource-assignment/provider/src/test/java/jtest/org/onap/ccsdk/sli/adaptors/ra/TestLockHelper.java
new file mode 100644
index 000000000..a9389b279
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/test/java/jtest/org/onap/ccsdk/sli/adaptors/ra/TestLockHelper.java
@@ -0,0 +1,61 @@
+package jtest.org.onap.ccsdk.sli.adaptors.ra;
+
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.MethodSorters;
+import org.onap.ccsdk.sli.adaptors.lock.comp.LockHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import static org.junit.Assert.assertNotNull;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(locations = { "classpath:test-context.xml" })
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestLockHelper {
+
+ private static final Logger log = LoggerFactory.getLogger(TestLockHelper.class);
+
+ @Autowired
+ private LockHelper lockHelper;
+
+ @Test
+ public void test1() throws Exception {
+ LockThread t1 = new LockThread("req1");
+ LockThread t2 = new LockThread("req2");
+ LockThread t3 = new LockThread("req3");
+
+ t1.start();
+ t2.start();
+ t3.start();
+
+ t1.join();
+ t2.join();
+ t3.join();
+ assertNotNull(t1);
+ }
+
+ private class LockThread extends Thread {
+ private String requester;
+
+ public LockThread(String requester) {
+ this.requester = requester;
+ }
+
+ @Override
+ public void run() {
+ lockHelper.lock("resource1", requester, 20);
+
+ try {
+ Thread.sleep(500);
+ } catch (InterruptedException e) {
+ log.warn("Thread interrupted: " + e.getMessage(), e);
+ }
+
+ lockHelper.unlock("resource1", false);
+ }
+ }
+}
diff --git a/adaptors/resource-assignment/provider/src/test/java/jtest/org/onap/ccsdk/sli/adaptors/ra/TestQueryResource.java b/adaptors/resource-assignment/provider/src/test/java/jtest/org/onap/ccsdk/sli/adaptors/ra/TestQueryResource.java
new file mode 100644
index 000000000..f31a3859a
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/test/java/jtest/org/onap/ccsdk/sli/adaptors/ra/TestQueryResource.java
@@ -0,0 +1,157 @@
+package jtest.org.onap.ccsdk.sli.adaptors.ra;
+
+import org.junit.Assert;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.MethodSorters;
+import org.onap.ccsdk.sli.adaptors.ra.ResourceAllocator;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicResource.QueryStatus;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(locations = {"classpath:test-context.xml"})
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestQueryResource {
+
+ private static final Logger log = LoggerFactory.getLogger(TestQueryResource.class);
+
+ @Autowired(required = true)
+ private ResourceAllocator resourceAllocator;
+
+ @Autowired(required = true)
+ private DataSetup dataSetup;
+
+ private void setupResourceData() {
+ dataSetup.cleanup();
+
+ for (int k = 0; k < 6; k++) {
+ String assetId = "Port::TESTPORT-" + (k / 2 + 1) + "-" + (k + 1);
+
+ for (int i = 0; i < 5; i++) {
+ String entityId = "TEST-" + i + "-" + (k / 2 + 1);
+
+ String resourceUnion = "EVC::" + entityId;
+ String resourceSet = resourceUnion + "::1";
+
+ dataSetup.setupRangeItem("test-range-1", assetId, resourceSet, resourceUnion, String.valueOf(i));
+ }
+ }
+
+ for (int k = 0; k < 6; k++) {
+ String assetId = "Port::TESTPORT-" + (k / 2 + 1) + "-" + (k + 1);
+
+ for (int i = 0; i < 5; i++) {
+ String entityId = "TEST-" + i + "-" + (k / 2 + 1);
+
+ String resourceUnion = "EVC::" + entityId;
+ String resourceSet = resourceUnion + "::1";
+
+ dataSetup.setupLimitItem("test-limit-1", assetId, resourceSet, resourceUnion, (i + 1) * 100);
+ }
+ }
+ }
+
+ @Test
+ public void test001() throws Exception {
+
+ String t = "001";
+ log.info("============== query node " + t + " ================================");
+ log.info("=== Test query for resources - with resource target condition - range");
+
+ setupResourceData();
+
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute("ra-input.resource-target-id-filter", "TESTPORT-1-%");
+ ctx.setAttribute("ra-input.resource-target-type-filter", "Port");
+
+ ctx.setAttribute("ra-input.resource-name", "test-range-1");
+
+ QueryStatus st = resourceAllocator.query("NetworkCapacity", false, null, null, "ra-output", null, ctx);
+
+ Assert.assertTrue(st == QueryStatus.SUCCESS);
+
+ Assert.assertEquals(ctx.getAttribute("ra-output.resource-list_length"), "2");
+ Assert.assertEquals(ctx.getAttribute("ra-output.resource-list[0].resource-name"), "test-range-1");
+ Assert.assertEquals(ctx.getAttribute("ra-output.resource-list[0].resource-target-type"), "Port");
+ Assert.assertEquals(ctx.getAttribute("ra-output.resource-list[0].resource-target-id"), "TESTPORT-1-1");
+ Assert.assertEquals(ctx.getAttribute("ra-output.resource-list[0].allocated"), "0, 1, 2, 3, 4");
+ Assert.assertEquals(ctx.getAttribute("ra-output.resource-list[1].resource-name"), "test-range-1");
+ Assert.assertEquals(ctx.getAttribute("ra-output.resource-list[1].resource-target-type"), "Port");
+ Assert.assertEquals(ctx.getAttribute("ra-output.resource-list[1].resource-target-id"), "TESTPORT-1-2");
+ Assert.assertEquals(ctx.getAttribute("ra-output.resource-list[1].allocated"), "0, 1, 2, 3, 4");
+ Assert.assertEquals(ctx.getAttribute("ra-output.resource-list[1].allocation-data-list_length"), "5");
+ Assert.assertEquals(ctx.getAttribute("ra-output.resource-list[1].allocation-data-list[0].resource-entity-type"), "EVC");
+ Assert.assertEquals(ctx.getAttribute("ra-output.resource-list[1].allocation-data-list[0].resource-entity-id"), "TEST-0-1");
+ Assert.assertEquals(ctx.getAttribute("ra-output.resource-list[1].allocation-data-list[0].resource-entity-version"), "1");
+ Assert.assertEquals(ctx.getAttribute("ra-output.resource-list[1].allocation-data-list[0].allocated"), "0");
+ Assert.assertEquals(ctx.getAttribute("ra-output.resource-list[1].allocation-data-list[1].resource-entity-type"), "EVC");
+ Assert.assertEquals(ctx.getAttribute("ra-output.resource-list[1].allocation-data-list[1].resource-entity-id"), "TEST-1-1");
+ Assert.assertEquals(ctx.getAttribute("ra-output.resource-list[1].allocation-data-list[1].resource-entity-version"), "1");
+ Assert.assertEquals(ctx.getAttribute("ra-output.resource-list[1].allocation-data-list[1].allocated"), "1");
+ Assert.assertEquals(ctx.getAttribute("ra-output.resource-list[1].allocation-data-list[2].resource-entity-type"), "EVC");
+ Assert.assertEquals(ctx.getAttribute("ra-output.resource-list[1].allocation-data-list[2].resource-entity-id"), "TEST-2-1");
+ Assert.assertEquals(ctx.getAttribute("ra-output.resource-list[1].allocation-data-list[2].resource-entity-version"), "1");
+ Assert.assertEquals(ctx.getAttribute("ra-output.resource-list[1].allocation-data-list[2].allocated"), "2");
+ Assert.assertEquals(ctx.getAttribute("ra-output.resource-list[1].allocation-data-list[3].resource-entity-type"), "EVC");
+ Assert.assertEquals(ctx.getAttribute("ra-output.resource-list[1].allocation-data-list[3].resource-entity-id"), "TEST-3-1");
+ Assert.assertEquals(ctx.getAttribute("ra-output.resource-list[1].allocation-data-list[3].resource-entity-version"), "1");
+ Assert.assertEquals(ctx.getAttribute("ra-output.resource-list[1].allocation-data-list[3].allocated"), "3");
+ Assert.assertEquals(ctx.getAttribute("ra-output.resource-list[1].allocation-data-list[4].resource-entity-type"), "EVC");
+ Assert.assertEquals(ctx.getAttribute("ra-output.resource-list[1].allocation-data-list[4].resource-entity-id"), "TEST-4-1");
+ Assert.assertEquals(ctx.getAttribute("ra-output.resource-list[1].allocation-data-list[4].resource-entity-version"), "1");
+ Assert.assertEquals(ctx.getAttribute("ra-output.resource-list[1].allocation-data-list[4].allocated"), "4");
+ }
+
+ @Test
+ public void test002() throws Exception {
+
+ String t = "002";
+ log.info("============== query node " + t + " ================================");
+ log.info("=== Test query for resources - with resource target condition - limit");
+
+ setupResourceData();
+
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute("ra-input.resource-target-id-filter", "TESTPORT-%-1");
+ ctx.setAttribute("ra-input.resource-target-type-filter", "Port");
+
+ ctx.setAttribute("ra-input.resource-name", "test-limit-1");
+
+ QueryStatus st = resourceAllocator.query("NetworkCapacity", false, null, null, "ra-output", null, ctx);
+
+ Assert.assertTrue(st == QueryStatus.SUCCESS);
+
+ Assert.assertEquals(ctx.getAttribute("ra-output.resource-list_length"), "1");
+ Assert.assertEquals(ctx.getAttribute("ra-output.resource-list[0].resource-name"), "test-limit-1");
+ Assert.assertEquals(ctx.getAttribute("ra-output.resource-list[0].resource-target-type"), "Port");
+ Assert.assertEquals(ctx.getAttribute("ra-output.resource-list[0].resource-target-id"), "TESTPORT-1-1");
+ Assert.assertEquals(ctx.getAttribute("ra-output.resource-list[0].allocated"), "1500");
+ Assert.assertEquals(ctx.getAttribute("ra-output.resource-list[0].allocation-data-list_length"), "5");
+ Assert.assertEquals(ctx.getAttribute("ra-output.resource-list[0].allocation-data-list[0].resource-entity-type"), "EVC");
+ Assert.assertEquals(ctx.getAttribute("ra-output.resource-list[0].allocation-data-list[0].resource-entity-id"), "TEST-0-1");
+ Assert.assertEquals(ctx.getAttribute("ra-output.resource-list[0].allocation-data-list[0].resource-entity-version"), "1");
+ Assert.assertEquals(ctx.getAttribute("ra-output.resource-list[0].allocation-data-list[0].allocated"), "100");
+ Assert.assertEquals(ctx.getAttribute("ra-output.resource-list[0].allocation-data-list[1].resource-entity-type"), "EVC");
+ Assert.assertEquals(ctx.getAttribute("ra-output.resource-list[0].allocation-data-list[1].resource-entity-id"), "TEST-1-1");
+ Assert.assertEquals(ctx.getAttribute("ra-output.resource-list[0].allocation-data-list[1].resource-entity-version"), "1");
+ Assert.assertEquals(ctx.getAttribute("ra-output.resource-list[0].allocation-data-list[1].allocated"), "200");
+ Assert.assertEquals(ctx.getAttribute("ra-output.resource-list[0].allocation-data-list[2].resource-entity-type"), "EVC");
+ Assert.assertEquals(ctx.getAttribute("ra-output.resource-list[0].allocation-data-list[2].resource-entity-id"), "TEST-2-1");
+ Assert.assertEquals(ctx.getAttribute("ra-output.resource-list[0].allocation-data-list[2].resource-entity-version"), "1");
+ Assert.assertEquals(ctx.getAttribute("ra-output.resource-list[0].allocation-data-list[2].allocated"), "300");
+ Assert.assertEquals(ctx.getAttribute("ra-output.resource-list[0].allocation-data-list[3].resource-entity-type"), "EVC");
+ Assert.assertEquals(ctx.getAttribute("ra-output.resource-list[0].allocation-data-list[3].resource-entity-id"), "TEST-3-1");
+ Assert.assertEquals(ctx.getAttribute("ra-output.resource-list[0].allocation-data-list[3].resource-entity-version"), "1");
+ Assert.assertEquals(ctx.getAttribute("ra-output.resource-list[0].allocation-data-list[3].allocated"), "400");
+ Assert.assertEquals(ctx.getAttribute("ra-output.resource-list[0].allocation-data-list[4].resource-entity-type"), "EVC");
+ Assert.assertEquals(ctx.getAttribute("ra-output.resource-list[0].allocation-data-list[4].resource-entity-id"), "TEST-4-1");
+ Assert.assertEquals(ctx.getAttribute("ra-output.resource-list[0].allocation-data-list[4].resource-entity-version"), "1");
+ Assert.assertEquals(ctx.getAttribute("ra-output.resource-list[0].allocation-data-list[4].allocated"), "500");
+ }
+}
diff --git a/adaptors/resource-assignment/provider/src/test/java/jtest/org/onap/ccsdk/sli/adaptors/ra/TestRelease.java b/adaptors/resource-assignment/provider/src/test/java/jtest/org/onap/ccsdk/sli/adaptors/ra/TestRelease.java
new file mode 100644
index 000000000..88ec586e8
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/test/java/jtest/org/onap/ccsdk/sli/adaptors/ra/TestRelease.java
@@ -0,0 +1,420 @@
+package jtest.org.onap.ccsdk.sli.adaptors.ra;
+
+import org.junit.Assert;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.MethodSorters;
+import org.onap.ccsdk.sli.adaptors.ra.ResourceAllocator;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicResource.QueryStatus;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(locations = {"classpath:test-context.xml"})
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestRelease {
+
+ private static final Logger log = LoggerFactory.getLogger(TestRelease.class);
+
+ @Autowired(required = true)
+ private ResourceAllocator resourceAllocator;
+
+ @Autowired(required = true)
+ private DataSetup dataSetup;
+
+ private void setupResourceData() {
+ dataSetup.cleanup();
+
+ dataSetup.setupRangeItem("test-range-1", "Port::TESTPORT-1", "EVC::TEST-1::1", "EVC::TEST-1", "1");
+
+ dataSetup.setupRangeItem("test-range-1", "Port::TESTPORT-1", "EVC::TEST-2::1", "EVC::TEST-2", "2");
+ dataSetup.setupRangeItem("test-range-1", "Port::TESTPORT-1", "EVC::TEST-2::2", "EVC::TEST-2", "2");
+
+ dataSetup.setupRangeItem("test-range-1", "Port::TESTPORT-1", "EVC::TEST-3::1", "EVC::TEST-3", "3");
+ dataSetup.setupRangeItem("test-range-1", "Port::TESTPORT-1", "EVC::TEST-3::2", "EVC::TEST-3", "4");
+
+ dataSetup.setupRangeItem("test-range-1", "Port::TESTPORT-1", "EVC::TEST-4::1", "EVC::TEST-4", "5");
+ dataSetup.setupRangeItem("test-range-1", "Port::TESTPORT-1", "EVC::TEST-4::2", "EVC::TEST-4", "5");
+ dataSetup.setupRangeItem("test-range-1", "Port::TESTPORT-1", "EVC::TEST-4::3", "EVC::TEST-4", "6");
+
+ dataSetup.setupRangeItem("test-range-1", "Port::TESTPORT-2", "EVC::TEST-1::1", "EVC::TEST-1", "1");
+
+ dataSetup.setupRangeItem("test-range-1", "Port::TESTPORT-2", "EVC::TEST-3::1", "EVC::TEST-3", "3");
+ dataSetup.setupRangeItem("test-range-1", "Port::TESTPORT-2", "EVC::TEST-3::2", "EVC::TEST-3", "4");
+
+ dataSetup.setupRangeItem("test-range-1", "Port::TESTPORT-2", "EVC::TEST-5::1", "EVC::TEST-5", "5");
+
+ dataSetup.setupRangeItem("test-range-1", "Port::TESTPORT-2", "EVC::TEST-6::1", "EVC::TEST-6", "6-20");
+
+ dataSetup.setupLimitItem("test-limit-1", "Port::TESTPORT-1", "EVC::TEST-1::1", "EVC::TEST-1", 100);
+
+ dataSetup.setupLimitItem("test-limit-1", "Port::TESTPORT-1", "EVC::TEST-2::1", "EVC::TEST-2", 200);
+ dataSetup.setupLimitItem("test-limit-1", "Port::TESTPORT-1", "EVC::TEST-2::2", "EVC::TEST-2", 200);
+
+ dataSetup.setupLimitItem("test-limit-1", "Port::TESTPORT-1", "EVC::TEST-3::1", "EVC::TEST-3", 300);
+ dataSetup.setupLimitItem("test-limit-1", "Port::TESTPORT-1", "EVC::TEST-3::2", "EVC::TEST-3", 400);
+
+ dataSetup.setupLimitItem("test-limit-1", "Port::TESTPORT-1", "EVC::TEST-4::1", "EVC::TEST-4", 500);
+ dataSetup.setupLimitItem("test-limit-1", "Port::TESTPORT-1", "EVC::TEST-4::2", "EVC::TEST-4", 500);
+ dataSetup.setupLimitItem("test-limit-1", "Port::TESTPORT-1", "EVC::TEST-4::3", "EVC::TEST-4", 600);
+
+ dataSetup.setupLimitItem("test-limit-1", "Port::TESTPORT-2", "EVC::TEST-1::1", "EVC::TEST-1", 100);
+
+ dataSetup.setupLimitItem("test-limit-1", "Port::TESTPORT-2", "EVC::TEST-3::1", "EVC::TEST-3", 300);
+ dataSetup.setupLimitItem("test-limit-1", "Port::TESTPORT-2", "EVC::TEST-3::2", "EVC::TEST-3", 400);
+
+ dataSetup.setupLimitItem("test-limit-1", "Port::TESTPORT-2", "EVC::TEST-5::1", "EVC::TEST-5", 500);
+
+ dataSetup.setupLimitItem("test-limit-1", "Port::TESTPORT-2", "EVC::TEST-6::1", "EVC::TEST-6", 1000);
+ }
+
+ @Test
+ public void test001() throws Exception {
+
+ String t = "001";
+ log.info("============== release node " + t + " ================================");
+ log.info("=== Test release - with resource set");
+
+ setupResourceData();
+
+ Assert.assertTrue(dataSetup.checkRangeItem("test-range-1", "Port::TESTPORT-1", "EVC::TEST-4::1", "5"));
+ Assert.assertTrue(dataSetup.checkRangeItem("test-range-1", "Port::TESTPORT-1", "EVC::TEST-4::2", "5"));
+ Assert.assertTrue(dataSetup.checkRangeItem("test-range-1", "Port::TESTPORT-1", "EVC::TEST-4::3", "6"));
+
+ Assert.assertTrue(dataSetup.checkLimitItem("test-limit-1", "Port::TESTPORT-1", "EVC::TEST-4::1", 500));
+ Assert.assertTrue(dataSetup.checkLimitItem("test-limit-1", "Port::TESTPORT-1", "EVC::TEST-4::2", 500));
+ Assert.assertTrue(dataSetup.checkLimitItem("test-limit-1", "Port::TESTPORT-1", "EVC::TEST-4::3", 600));
+
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute("ra-input.resource-entity-type", "EVC");
+ ctx.setAttribute("ra-input.resource-entity-id", "TEST-4");
+ ctx.setAttribute("ra-input.resource-entity-version", "2");
+
+ QueryStatus st = resourceAllocator.release("NETWORK-CAPACITY", null, ctx);
+
+ Assert.assertTrue(st == QueryStatus.SUCCESS);
+
+ Assert.assertTrue(dataSetup.checkRangeItem("test-range-1", "Port::TESTPORT-1", "EVC::TEST-4::1", "5"));
+ Assert.assertFalse(dataSetup.checkRangeItem("test-range-1", "Port::TESTPORT-1", "EVC::TEST-4::2", "5"));
+ Assert.assertTrue(dataSetup.checkRangeItem("test-range-1", "Port::TESTPORT-1", "EVC::TEST-4::3", "6"));
+
+ Assert.assertTrue(dataSetup.checkLimitItem("test-limit-1", "Port::TESTPORT-1", "EVC::TEST-4::1", 500));
+ Assert.assertFalse(dataSetup.checkLimitItem("test-limit-1", "Port::TESTPORT-1", "EVC::TEST-4::2", 500));
+ Assert.assertTrue(dataSetup.checkLimitItem("test-limit-1", "Port::TESTPORT-1", "EVC::TEST-4::3", 600));
+ }
+
+ @Test
+ public void test002() throws Exception {
+
+ String t = "002";
+ log.info("============== query node " + t + " ================================");
+ log.info("=== Test release - with resource union");
+
+ setupResourceData();
+
+ Assert.assertTrue(dataSetup.checkRangeItem("test-range-1", "Port::TESTPORT-1", "EVC::TEST-4::1", "5"));
+ Assert.assertTrue(dataSetup.checkRangeItem("test-range-1", "Port::TESTPORT-1", "EVC::TEST-4::2", "5"));
+ Assert.assertTrue(dataSetup.checkRangeItem("test-range-1", "Port::TESTPORT-1", "EVC::TEST-4::3", "6"));
+
+ Assert.assertTrue(dataSetup.checkLimitItem("test-limit-1", "Port::TESTPORT-1", "EVC::TEST-4::1", 500));
+ Assert.assertTrue(dataSetup.checkLimitItem("test-limit-1", "Port::TESTPORT-1", "EVC::TEST-4::2", 500));
+ Assert.assertTrue(dataSetup.checkLimitItem("test-limit-1", "Port::TESTPORT-1", "EVC::TEST-4::3", 600));
+
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute("ra-input.resource-entity-type", "EVC");
+ ctx.setAttribute("ra-input.resource-entity-id", "TEST-4");
+
+ QueryStatus st = resourceAllocator.release("NETWORK-CAPACITY", null, ctx);
+
+ Assert.assertTrue(st == QueryStatus.SUCCESS);
+
+ Assert.assertFalse(dataSetup.checkRangeItem("test-range-1", "Port::TESTPORT-1", "EVC::TEST-4::1", "5"));
+ Assert.assertFalse(dataSetup.checkRangeItem("test-range-1", "Port::TESTPORT-1", "EVC::TEST-4::2", "5"));
+ Assert.assertFalse(dataSetup.checkRangeItem("test-range-1", "Port::TESTPORT-1", "EVC::TEST-4::3", "6"));
+
+ Assert.assertFalse(dataSetup.checkLimitItem("test-limit-1", "Port::TESTPORT-1", "EVC::TEST-4::1", 500));
+ Assert.assertFalse(dataSetup.checkLimitItem("test-limit-1", "Port::TESTPORT-1", "EVC::TEST-4::2", 500));
+ Assert.assertFalse(dataSetup.checkLimitItem("test-limit-1", "Port::TESTPORT-1", "EVC::TEST-4::3", 600));
+ }
+
+ @Test
+ public void test003() throws Exception {
+
+ String t = "003";
+ log.info("============== release node " + t + " ================================");
+ log.info("=== Test release - with resource set on 2 ports");
+
+ setupResourceData();
+
+ Assert.assertTrue(dataSetup.checkRangeItem("test-range-1", "Port::TESTPORT-1", "EVC::TEST-3::1", "3"));
+ Assert.assertTrue(dataSetup.checkRangeItem("test-range-1", "Port::TESTPORT-1", "EVC::TEST-3::2", "4"));
+ Assert.assertTrue(dataSetup.checkRangeItem("test-range-1", "Port::TESTPORT-2", "EVC::TEST-3::1", "3"));
+ Assert.assertTrue(dataSetup.checkRangeItem("test-range-1", "Port::TESTPORT-2", "EVC::TEST-3::2", "4"));
+
+ Assert.assertTrue(dataSetup.checkLimitItem("test-limit-1", "Port::TESTPORT-1", "EVC::TEST-3::1", 300));
+ Assert.assertTrue(dataSetup.checkLimitItem("test-limit-1", "Port::TESTPORT-1", "EVC::TEST-3::2", 400));
+ Assert.assertTrue(dataSetup.checkLimitItem("test-limit-1", "Port::TESTPORT-2", "EVC::TEST-3::1", 300));
+ Assert.assertTrue(dataSetup.checkLimitItem("test-limit-1", "Port::TESTPORT-2", "EVC::TEST-3::2", 400));
+
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute("ra-input.resource-entity-type", "EVC");
+ ctx.setAttribute("ra-input.resource-entity-id", "TEST-3");
+ ctx.setAttribute("ra-input.resource-entity-version", "1");
+
+ QueryStatus st = resourceAllocator.release("NETWORK-CAPACITY", null, ctx);
+
+ Assert.assertTrue(st == QueryStatus.SUCCESS);
+
+ Assert.assertFalse(dataSetup.checkRangeItem("test-range-1", "Port::TESTPORT-1", "EVC::TEST-3::1", "3"));
+ Assert.assertTrue(dataSetup.checkRangeItem("test-range-1", "Port::TESTPORT-1", "EVC::TEST-3::2", "4"));
+ Assert.assertFalse(dataSetup.checkRangeItem("test-range-1", "Port::TESTPORT-2", "EVC::TEST-3::1", "3"));
+ Assert.assertTrue(dataSetup.checkRangeItem("test-range-1", "Port::TESTPORT-2", "EVC::TEST-3::2", "4"));
+
+ Assert.assertFalse(dataSetup.checkLimitItem("test-limit-1", "Port::TESTPORT-1", "EVC::TEST-3::1", 300));
+ Assert.assertTrue(dataSetup.checkLimitItem("test-limit-1", "Port::TESTPORT-1", "EVC::TEST-3::2", 400));
+ Assert.assertFalse(dataSetup.checkLimitItem("test-limit-1", "Port::TESTPORT-2", "EVC::TEST-3::1", 300));
+ Assert.assertTrue(dataSetup.checkLimitItem("test-limit-1", "Port::TESTPORT-2", "EVC::TEST-3::2", 400));
+ }
+
+ @Test
+ public void test004() throws Exception {
+
+ String t = "004";
+ log.info("============== release node " + t + " ================================");
+ log.info("=== Test release - with resource union on 2 ports");
+
+ setupResourceData();
+
+ Assert.assertTrue(dataSetup.checkRangeItem("test-range-1", "Port::TESTPORT-1", "EVC::TEST-3::1", "3"));
+ Assert.assertTrue(dataSetup.checkRangeItem("test-range-1", "Port::TESTPORT-1", "EVC::TEST-3::2", "4"));
+ Assert.assertTrue(dataSetup.checkRangeItem("test-range-1", "Port::TESTPORT-2", "EVC::TEST-3::1", "3"));
+ Assert.assertTrue(dataSetup.checkRangeItem("test-range-1", "Port::TESTPORT-2", "EVC::TEST-3::2", "4"));
+
+ Assert.assertTrue(dataSetup.checkLimitItem("test-limit-1", "Port::TESTPORT-1", "EVC::TEST-3::1", 300));
+ Assert.assertTrue(dataSetup.checkLimitItem("test-limit-1", "Port::TESTPORT-1", "EVC::TEST-3::2", 400));
+ Assert.assertTrue(dataSetup.checkLimitItem("test-limit-1", "Port::TESTPORT-2", "EVC::TEST-3::1", 300));
+ Assert.assertTrue(dataSetup.checkLimitItem("test-limit-1", "Port::TESTPORT-2", "EVC::TEST-3::2", 400));
+
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute("ra-input.resource-entity-type", "EVC");
+ ctx.setAttribute("ra-input.resource-entity-id", "TEST-3");
+
+ QueryStatus st = resourceAllocator.release("NETWORK-CAPACITY", null, ctx);
+
+ Assert.assertTrue(st == QueryStatus.SUCCESS);
+
+ Assert.assertFalse(dataSetup.checkRangeItem("test-range-1", "Port::TESTPORT-1", "EVC::TEST-3::1", "3"));
+ Assert.assertFalse(dataSetup.checkRangeItem("test-range-1", "Port::TESTPORT-1", "EVC::TEST-3::2", "4"));
+ Assert.assertFalse(dataSetup.checkRangeItem("test-range-1", "Port::TESTPORT-2", "EVC::TEST-3::1", "3"));
+ Assert.assertFalse(dataSetup.checkRangeItem("test-range-1", "Port::TESTPORT-2", "EVC::TEST-3::2", "4"));
+
+ Assert.assertFalse(dataSetup.checkLimitItem("test-limit-1", "Port::TESTPORT-1", "EVC::TEST-3::1", 300));
+ Assert.assertFalse(dataSetup.checkLimitItem("test-limit-1", "Port::TESTPORT-1", "EVC::TEST-3::2", 400));
+ Assert.assertFalse(dataSetup.checkLimitItem("test-limit-1", "Port::TESTPORT-2", "EVC::TEST-3::1", 300));
+ Assert.assertFalse(dataSetup.checkLimitItem("test-limit-1", "Port::TESTPORT-2", "EVC::TEST-3::2", 400));
+ }
+
+ @Test
+ public void test005() throws Exception {
+
+ String t = "005";
+ log.info("============== release node " + t + " ================================");
+ log.info("=== Test release - with resource set and asset");
+
+ setupResourceData();
+
+ Assert.assertTrue(dataSetup.checkRangeItem("test-range-1", "Port::TESTPORT-1", "EVC::TEST-3::1", "3"));
+ Assert.assertTrue(dataSetup.checkRangeItem("test-range-1", "Port::TESTPORT-1", "EVC::TEST-3::2", "4"));
+ Assert.assertTrue(dataSetup.checkRangeItem("test-range-1", "Port::TESTPORT-2", "EVC::TEST-3::1", "3"));
+ Assert.assertTrue(dataSetup.checkRangeItem("test-range-1", "Port::TESTPORT-2", "EVC::TEST-3::2", "4"));
+
+ Assert.assertTrue(dataSetup.checkLimitItem("test-limit-1", "Port::TESTPORT-1", "EVC::TEST-3::1", 300));
+ Assert.assertTrue(dataSetup.checkLimitItem("test-limit-1", "Port::TESTPORT-1", "EVC::TEST-3::2", 400));
+ Assert.assertTrue(dataSetup.checkLimitItem("test-limit-1", "Port::TESTPORT-2", "EVC::TEST-3::1", 300));
+ Assert.assertTrue(dataSetup.checkLimitItem("test-limit-1", "Port::TESTPORT-2", "EVC::TEST-3::2", 400));
+
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute("ra-input.resource-entity-type", "EVC");
+ ctx.setAttribute("ra-input.resource-entity-id", "TEST-3");
+ ctx.setAttribute("ra-input.resource-entity-version", "1");
+
+ ctx.setAttribute("ra-input.resource-target-type", "Port");
+ ctx.setAttribute("ra-input.resource-target-id", "TESTPORT-1");
+
+ QueryStatus st = resourceAllocator.release("NETWORK-CAPACITY", null, ctx);
+
+ Assert.assertTrue(st == QueryStatus.SUCCESS);
+
+ Assert.assertFalse(dataSetup.checkRangeItem("test-range-1", "Port::TESTPORT-1", "EVC::TEST-3::1", "3"));
+ Assert.assertTrue(dataSetup.checkRangeItem("test-range-1", "Port::TESTPORT-1", "EVC::TEST-3::2", "4"));
+ Assert.assertTrue(dataSetup.checkRangeItem("test-range-1", "Port::TESTPORT-2", "EVC::TEST-3::1", "3"));
+ Assert.assertTrue(dataSetup.checkRangeItem("test-range-1", "Port::TESTPORT-2", "EVC::TEST-3::2", "4"));
+
+ Assert.assertFalse(dataSetup.checkLimitItem("test-limit-1", "Port::TESTPORT-1", "EVC::TEST-3::1", 300));
+ Assert.assertTrue(dataSetup.checkLimitItem("test-limit-1", "Port::TESTPORT-1", "EVC::TEST-3::2", 400));
+ Assert.assertTrue(dataSetup.checkLimitItem("test-limit-1", "Port::TESTPORT-2", "EVC::TEST-3::1", 300));
+ Assert.assertTrue(dataSetup.checkLimitItem("test-limit-1", "Port::TESTPORT-2", "EVC::TEST-3::2", 400));
+ }
+
+ @Test
+ public void test006() throws Exception {
+
+ String t = "006";
+ log.info("============== release node " + t + " ================================");
+ log.info("=== Test release - with resource union on 2 ports");
+
+ setupResourceData();
+
+ Assert.assertTrue(dataSetup.checkRangeItem("test-range-1", "Port::TESTPORT-1", "EVC::TEST-3::1", "3"));
+ Assert.assertTrue(dataSetup.checkRangeItem("test-range-1", "Port::TESTPORT-1", "EVC::TEST-3::2", "4"));
+ Assert.assertTrue(dataSetup.checkRangeItem("test-range-1", "Port::TESTPORT-2", "EVC::TEST-3::1", "3"));
+ Assert.assertTrue(dataSetup.checkRangeItem("test-range-1", "Port::TESTPORT-2", "EVC::TEST-3::2", "4"));
+
+ Assert.assertTrue(dataSetup.checkLimitItem("test-limit-1", "Port::TESTPORT-1", "EVC::TEST-3::1", 300));
+ Assert.assertTrue(dataSetup.checkLimitItem("test-limit-1", "Port::TESTPORT-1", "EVC::TEST-3::2", 400));
+ Assert.assertTrue(dataSetup.checkLimitItem("test-limit-1", "Port::TESTPORT-2", "EVC::TEST-3::1", 300));
+ Assert.assertTrue(dataSetup.checkLimitItem("test-limit-1", "Port::TESTPORT-2", "EVC::TEST-3::2", 400));
+
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute("ra-input.resource-entity-type", "EVC");
+ ctx.setAttribute("ra-input.resource-entity-id", "TEST-3");
+
+ ctx.setAttribute("ra-input.resource-target-type", "Port");
+ ctx.setAttribute("ra-input.resource-target-id", "TESTPORT-1");
+
+ QueryStatus st = resourceAllocator.release("NETWORK-CAPACITY", null, ctx);
+
+ Assert.assertTrue(st == QueryStatus.SUCCESS);
+
+ Assert.assertFalse(dataSetup.checkRangeItem("test-range-1", "Port::TESTPORT-1", "EVC::TEST-3::1", "3"));
+ Assert.assertFalse(dataSetup.checkRangeItem("test-range-1", "Port::TESTPORT-1", "EVC::TEST-3::2", "4"));
+ Assert.assertTrue(dataSetup.checkRangeItem("test-range-1", "Port::TESTPORT-2", "EVC::TEST-3::1", "3"));
+ Assert.assertTrue(dataSetup.checkRangeItem("test-range-1", "Port::TESTPORT-2", "EVC::TEST-3::2", "4"));
+
+ Assert.assertFalse(dataSetup.checkLimitItem("test-limit-1", "Port::TESTPORT-1", "EVC::TEST-3::1", 300));
+ Assert.assertFalse(dataSetup.checkLimitItem("test-limit-1", "Port::TESTPORT-1", "EVC::TEST-3::2", 400));
+ Assert.assertTrue(dataSetup.checkLimitItem("test-limit-1", "Port::TESTPORT-2", "EVC::TEST-3::1", 300));
+ Assert.assertTrue(dataSetup.checkLimitItem("test-limit-1", "Port::TESTPORT-2", "EVC::TEST-3::2", 400));
+ }
+
+ @Test
+ public void test007() throws Exception {
+
+ String t = "007";
+ log.info("============== release node " + t + " ================================");
+ log.info("=== Test release - partial release of range");
+
+ setupResourceData();
+
+ Assert.assertTrue(dataSetup.checkRangeItem("test-range-1", "Port::TESTPORT-2", "EVC::TEST-6::1", "6-20"));
+
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute("ra-input.resource-entity-type", "EVC");
+ ctx.setAttribute("ra-input.resource-entity-id", "TEST-6");
+ ctx.setAttribute("ra-input.resource-entity-version", "1");
+
+ ctx.setAttribute("ra-input.resource-target-type", "Port");
+ ctx.setAttribute("ra-input.resource-target-id", "TESTPORT-2");
+
+ ctx.setAttribute("ra-input.resource-name", "test-range-1");
+ ctx.setAttribute("ra-input.range-release-numbers", "7,9,15-17");
+
+ QueryStatus st = resourceAllocator.release("NETWORK-CAPACITY", null, ctx);
+
+ Assert.assertTrue(st == QueryStatus.SUCCESS);
+
+ Assert.assertTrue(dataSetup.checkRangeItem("test-range-1", "Port::TESTPORT-2", "EVC::TEST-6::1", "6,8,10-14,18-20"));
+ }
+
+ @Test
+ public void test008() throws Exception {
+
+ String t = "008";
+ log.info("============== release node " + t + " ================================");
+ log.info("=== Test release - partial release of range, but release all numbers");
+
+ setupResourceData();
+
+ Assert.assertTrue(dataSetup.checkRangeItem("test-range-1", "Port::TESTPORT-2", "EVC::TEST-6::1", "6-20"));
+
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute("ra-input.resource-entity-type", "EVC");
+ ctx.setAttribute("ra-input.resource-entity-id", "TEST-6");
+ ctx.setAttribute("ra-input.resource-entity-version", "1");
+
+ ctx.setAttribute("ra-input.resource-target-type", "Port");
+ ctx.setAttribute("ra-input.resource-target-id", "TESTPORT-2");
+
+ ctx.setAttribute("ra-input.resource-name", "test-range-1");
+ ctx.setAttribute("ra-input.range-release-numbers", "6-25");
+
+ QueryStatus st = resourceAllocator.release("NETWORK-CAPACITY", null, ctx);
+
+ Assert.assertTrue(st == QueryStatus.SUCCESS);
+
+ Assert.assertTrue(dataSetup.checkItemNotThere("test-range-1", "Port::TESTPORT-2", "EVC::TEST-6::1"));
+ }
+
+ @Test
+ public void test009() throws Exception {
+
+ String t = "009";
+ log.info("============== release node " + t + " ================================");
+ log.info("=== Test release - partial release of limit");
+
+ setupResourceData();
+
+ Assert.assertTrue(dataSetup.checkLimitItem("test-limit-1", "Port::TESTPORT-2", "EVC::TEST-6::1", 1000));
+
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute("ra-input.resource-entity-type", "EVC");
+ ctx.setAttribute("ra-input.resource-entity-id", "TEST-6");
+ ctx.setAttribute("ra-input.resource-entity-version", "1");
+
+ ctx.setAttribute("ra-input.resource-target-type", "Port");
+ ctx.setAttribute("ra-input.resource-target-id", "TESTPORT-2");
+
+ ctx.setAttribute("ra-input.resource-name", "test-limit-1");
+ ctx.setAttribute("ra-input.limit-release-amount", "200");
+
+ QueryStatus st = resourceAllocator.release("NETWORK-CAPACITY", null, ctx);
+
+ Assert.assertTrue(st == QueryStatus.SUCCESS);
+
+ Assert.assertTrue(dataSetup.checkLimitItem("test-limit-1", "Port::TESTPORT-2", "EVC::TEST-6::1", 800));
+ }
+
+ @Test
+ public void test010() throws Exception {
+
+ String t = "010";
+ log.info("============== release node " + t + " ================================");
+ log.info("=== Test release - partial release of limit, but release big number");
+
+ setupResourceData();
+
+ Assert.assertTrue(dataSetup.checkLimitItem("test-limit-1", "Port::TESTPORT-2", "EVC::TEST-6::1", 1000));
+
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute("ra-input.resource-entity-type", "EVC");
+ ctx.setAttribute("ra-input.resource-entity-id", "TEST-6");
+ ctx.setAttribute("ra-input.resource-entity-version", "1");
+
+ ctx.setAttribute("ra-input.resource-target-type", "Port");
+ ctx.setAttribute("ra-input.resource-target-id", "TESTPORT-2");
+
+ ctx.setAttribute("ra-input.resource-name", "test-limit-1");
+ ctx.setAttribute("ra-input.limit-release-amount", "2000");
+
+ QueryStatus st = resourceAllocator.release("NETWORK-CAPACITY", null, ctx);
+
+ Assert.assertTrue(st == QueryStatus.SUCCESS);
+
+ Assert.assertTrue(dataSetup.checkItemNotThere("test-limit-1", "Port::TESTPORT-2", "EVC::TEST-6::1"));
+ }
+}
diff --git a/adaptors/resource-assignment/provider/src/test/java/jtest/org/onap/ccsdk/sli/adaptors/ra/TestReserve.java b/adaptors/resource-assignment/provider/src/test/java/jtest/org/onap/ccsdk/sli/adaptors/ra/TestReserve.java
new file mode 100644
index 000000000..dbf0c4aac
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/test/java/jtest/org/onap/ccsdk/sli/adaptors/ra/TestReserve.java
@@ -0,0 +1,964 @@
+package jtest.org.onap.ccsdk.sli.adaptors.ra;
+
+import static org.junit.Assert.assertNotNull;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.junit.Assert;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.MethodSorters;
+import org.onap.ccsdk.sli.adaptors.ra.ResourceAllocator;
+import org.onap.ccsdk.sli.adaptors.ra.comp.ResourceEntity;
+import org.onap.ccsdk.sli.adaptors.ra.comp.ResourceRequest;
+import org.onap.ccsdk.sli.adaptors.ra.comp.ResourceResponse;
+import org.onap.ccsdk.sli.adaptors.ra.comp.ResourceTarget;
+import org.onap.ccsdk.sli.adaptors.rm.data.AllocationStatus;
+import org.onap.ccsdk.sli.adaptors.rm.data.Range;
+import org.onap.ccsdk.sli.adaptors.rm.data.ResourceType;
+import org.onap.ccsdk.sli.adaptors.util.str.StrUtil;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicResource.QueryStatus;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import jtest.util.org.onap.ccsdk.sli.adaptors.ra.TestTable;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(locations = { "classpath:test-context.xml" })
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestReserve {
+
+ private static final Logger log = LoggerFactory.getLogger(TestReserve.class);
+
+ private JdbcTemplate jdbcTemplate;
+
+ private static final String[] RESOURCE_COLUMNS = { "asset_id", "resource_name", "resource_type", "lt_used" };
+
+ private static final String[] ALLOCATION_ITEM_COLUMNS = { "resource_id", "application_id", "resource_set_id",
+ "resource_union_id", "resource_share_group_list", "lt_used", "allocation_time" };
+
+ @Autowired
+ public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
+ this.jdbcTemplate = jdbcTemplate;
+ }
+
+ @Autowired(required = true)
+ private ResourceAllocator resourceAllocator;
+
+ /*
+ * @Autowired(required = true) private ResourceAllocatorApi
+ * resourceAllocatorApi;
+ */
+
+ @Autowired(required = true)
+ private DataSetup dataSetup;
+
+ @Test
+ public void test001() throws Exception {
+ String t = "001";
+ log.info("============== reserve " + t + " ================================");
+ log.info("=== Test successful response - new start - all resources available");
+
+ // String service1 = "reserve" + t + "/service1";
+
+ dataSetup.cleanup();
+
+ TestTable resource = new TestTable(jdbcTemplate, "RESOURCE", "resource_id", RESOURCE_COLUMNS);
+ TestTable allocationItem = new TestTable(jdbcTemplate, "ALLOCATION_ITEM", "allocation_item_id",
+ ALLOCATION_ITEM_COLUMNS);
+
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute("ra-input.service-model", "ADIG");
+ ctx.setAttribute("ra-input.check-only", "false");
+ ctx.setAttribute("ra-input.reservation-entity-type", "SI");
+ ctx.setAttribute("ra-input.reservation-entity-id", "ICOREPVCID-123456");
+ ctx.setAttribute("ra-input.reservation-entity-data.service-speed", "100");
+ ctx.setAttribute("ra-input.reservation-entity-data.service-speed-unit", "Mbps");
+
+ ctx.setAttribute("ra-input.reservation-target-data.vnf-type", "VPE");
+ ctx.setAttribute("ra-input.reservation-target-data.vpe-name", "mdt300vpe54");
+ ctx.setAttribute("ra-input.reservation-target-id", "mdt300vpe54");
+ ctx.setAttribute("ra-input.reservation-target-type", "VNF");
+
+ ctx.setAttribute("ra-input.reservation-target-data.max-vpe-bandwidth-mbps", "5000");
+
+ QueryStatus st = resourceAllocator.reserve("NetworkCapacity", null, null, null, ctx);
+
+ Assert.assertTrue(st == QueryStatus.SUCCESS);
+
+ resource.print();
+ allocationItem.print();
+
+ ctx.setAttribute("ra-input.service-model", "ADIG");
+ ctx.setAttribute("ra-input.check-only", "false");
+ ctx.setAttribute("ra-input.reservation-entity-type", "SI");
+ ctx.setAttribute("ra-input.reservation-entity-id", "ICOREPVCID-123456");
+ ctx.setAttribute("ra-input.reservation-entity-data.service-speed", "100");
+ ctx.setAttribute("ra-input.reservation-entity-data.service-speed-unit", "Mbps");
+
+ ctx.setAttribute("ra-input.reservation-target-data.service-speed", "100");
+ ctx.setAttribute("ra-input.reservation-target-data.service-speed-unit", "Mbps");
+ ctx.setAttribute("ra-input.reservation-target-id", "ICORESITEID-123456");
+ ctx.setAttribute("ra-input.reservation-target-type", "Port");
+
+ st = resourceAllocator.reserve("NetworkCapacity", null, null, null, ctx);
+
+ Assert.assertTrue(st == QueryStatus.SUCCESS);
+
+ ctx.setAttribute("ra-input.service-model", "ADIG");
+ ctx.setAttribute("ra-input.check-only", "false");
+ ctx.setAttribute("ra-input.reservation-entity-type", "SI");
+ ctx.setAttribute("ra-input.reservation-entity-id", "ICOREPVCID-123456");
+ ctx.setAttribute("ra-input.reservation-entity-data.service-speed", "100");
+ ctx.setAttribute("ra-input.reservation-entity-data.service-speed-unit", "Mbps");
+
+ ctx.setAttribute("ra-input.reservation-target-data.vnf-type", "VPE");
+ ctx.setAttribute("ra-input.reservation-target-data.vpe-name", "mdt300vpe54");
+ ctx.setAttribute("ra-input.reservation-target-id", "mdt300vpe54");
+ ctx.setAttribute("ra-input.reservation-target-type", "AffinityLink");
+
+ st = resourceAllocator.reserve("NetworkCapacity", null, null, null, ctx);
+
+ Assert.assertTrue(st == QueryStatus.SUCCESS);
+
+ resource.print();
+ allocationItem.print();
+
+ /* Query Using ReservationEntityId using ServiceLogicContext */
+ ctx = new SvcLogicContext();
+ ctx.setAttribute("ra-input.service-model", "ADIG");
+ ctx.setAttribute("ra-input.reservation-entity-id", "ICOREPVCID-123456");
+ ctx.setAttribute("ra-input.reservation-entity-type", "SI");
+
+ st = resourceAllocator.query("NetworkCapacity", false, null, null, null, null, ctx);
+ Assert.assertTrue(st == QueryStatus.SUCCESS);
+
+ /* Query Using ReservationTargetId using ServiceLogicContext */
+ ctx = new SvcLogicContext();
+ ctx.setAttribute("ra-input.service-model", "ADIG");
+ ctx.setAttribute("ra-input.reservation-target-id", "ICORESITEID-123456");
+ ctx.setAttribute("ra-input.reservation-target-type", "Port");
+ ctx.setAttribute("ra-input.resource-name", "Bandwidth");
+
+ st = resourceAllocator.query("NetworkCapacity", false, null, null, null, null, ctx);
+ Assert.assertTrue(st == QueryStatus.SUCCESS);
+
+ log.info("======================== Query Using ResourceEntity==============================");
+ /* Query Using ResourceEntity bean */
+ ResourceEntity sd = new ResourceEntity();
+ sd.resourceEntityId = "ICOREPVCID-123456";
+ sd.resourceEntityType = "SI";
+
+ ResourceRequest rr = new ResourceRequest();
+ rr.serviceModel = "ADIG";
+ rr.resourceName = "cust-vlan-id";
+ rr.requestType = "New";
+ rr.rangeMaxOverride = -1;
+ rr.rangeMinOverride = -1;
+
+ List<ResourceResponse> rsList = new ArrayList<>();
+ resourceAllocator.query(sd, null, null, rsList);
+
+ rsList.forEach(r -> {
+ StrUtil.info(log, r);
+ });
+
+ log.info("======================== release Using ResourceEntity==============================");
+ rsList = new ArrayList<>();
+ AllocationStatus status = resourceAllocator.release(sd);
+ Assert.assertTrue(status == AllocationStatus.Success);
+
+ log.info("======================== Query Using ResourceEntity==============================");
+ rsList = new ArrayList<>();
+ resourceAllocator.query(sd, null, null, rsList);
+
+ rsList.forEach(r -> {
+ StrUtil.info(log, r);
+ });
+
+ }
+
+ @Test
+ public void test002() throws Exception {
+ String t = "002";
+ log.info("============== reserve " + t + " ================================");
+ log.info("=== Test successful response - new start - all resources available");
+
+ Map<String, String> data = new HashMap<>();
+ data.put("service-speed", "100");
+ data.put("service-speed-unit", "Mbps");
+
+ ResourceEntity sd = new ResourceEntity();
+ sd.resourceEntityId = "ICOREPVCID-123456";
+ sd.resourceEntityType = "SI";
+ sd.data = data;
+
+ data = new HashMap<>();
+ data.put("vnf-type", "VPE");
+ data.put("vpe-name", "mdt300vpe54");
+ data.put("max-vpe-bandwidth-mbps", "5000");
+
+ ResourceTarget rt = new ResourceTarget();
+ rt.resourceTargetId = "mdt300vpe54";
+ rt.resourceTargetType = "VNF";
+ rt.data = data;
+
+ ResourceRequest rr = new ResourceRequest();
+ rr.serviceModel = "ADIG";
+ // rr.resourceName = "cust-vlan-id";
+ rr.requestType = "New";
+ rr.rangeMaxOverride = -1;
+ rr.rangeMinOverride = -1;
+ rr.applicationId = "myapp";
+
+ List<ResourceResponse> rsList = new ArrayList<>();
+
+ resourceAllocator.reserve(sd, rt, rr, rsList);
+
+ rsList.forEach(r -> {
+ StrUtil.info(log, r);
+ });
+
+ log.info("======================== Query + t ==============================");
+ rsList = new ArrayList<>();
+ resourceAllocator.query(sd, null, rr, rsList);
+
+ rsList.forEach(r -> {
+ StrUtil.info(log, r);
+ });
+ assertNotNull(rsList);
+
+ }
+
+ @Test
+ public void test003() throws Exception {
+ String t = "003";
+ log.info("============== reserve " + t + " ================================");
+ log.info("=== Test successful response - new start - all resources available");
+
+ ResourceEntity sd = new ResourceEntity();
+ sd.resourceEntityId = "gblond2003me6";
+ sd.resourceEntityType = "VNF";
+
+ ResourceTarget rt = new ResourceTarget();
+ rt.resourceTargetId = "MDTWNJ21A5";
+ rt.resourceTargetType = "Site";
+
+ ResourceRequest rr = new ResourceRequest();
+ rr.serviceModel = "MY-SERV-MODEL";
+ rr.resourceName = "VPE-Cust";
+ // rr.requestType = "New";
+ // rr.rangeMaxOverride = 5;
+ // rr.rangeMinOverride = 5;
+
+ List<ResourceResponse> rsList = new ArrayList<>();
+ resourceAllocator.reserve(sd, rt, rr, rsList);
+
+ rsList.forEach(r -> {
+ StrUtil.info(log, r);
+ });
+
+ log.info("======================== Query + t ==============================");
+ rsList = new ArrayList<>();
+ resourceAllocator.query(sd, null, rr, rsList);
+
+ rsList.forEach(r -> {
+ StrUtil.info(log, r);
+ });
+ assertNotNull(sd);
+
+ }
+
+ @Test
+ public void test004() throws Exception {
+ String t = "004";
+ log.info("============== reserve " + t + " ================================");
+ log.info("=== Test successful response - new start - all resources available");
+
+ ResourceEntity sd = new ResourceEntity();
+ sd.resourceEntityId = "gblond2003me6";
+ sd.resourceEntityType = "VNF";
+
+ ResourceTarget rt = new ResourceTarget();
+ rt.resourceTargetId = "MDTWNJ21A5";
+ rt.resourceTargetType = "Site";
+
+ List<ResourceRequest> rrs = new ArrayList<>();
+ ResourceRequest rr = new ResourceRequest();
+ rr.serviceModel = "MY-SERV-MODEL";
+ rr.resourceName = "VPE-Cust";
+ rrs.add(rr);
+
+ rr = new ResourceRequest();
+ rr.serviceModel = "MY-SERV-MODEL";
+ rr.resourceName = "VPE-Core1";
+ rrs.add(rr);
+
+ rr = new ResourceRequest();
+ rr.serviceModel = "MY-SERV-MODEL";
+ rr.resourceName = "VPE-Core2";
+ rrs.add(rr);
+
+ List<ResourceResponse> rsList = new ArrayList<>();
+ // resourceAllocator.reserve(sd, rt, rrs, rsList);
+
+ rsList.forEach(r -> {
+ StrUtil.info(log, r);
+ });
+
+ log.info("======================== Query + t ==============================");
+ rsList = new ArrayList<>();
+ resourceAllocator.query(sd, null, rr, rsList);
+
+ rsList.forEach(r -> {
+ StrUtil.info(log, r);
+ });
+ assertNotNull(rr);
+
+ }
+
+ @Test
+ public void test005() throws Exception {
+ String t = "005";
+ log.info("============== reserve " + t + " ================================");
+ log.info("=== Test successful response - new start - all resources available");
+
+ // String service1 = "reserve" + t + "/service1";
+
+ dataSetup.cleanup();
+
+ TestTable resource = new TestTable(jdbcTemplate, "RESOURCE", "resource_id", RESOURCE_COLUMNS);
+ TestTable allocationItem = new TestTable(jdbcTemplate, "ALLOCATION_ITEM", "allocation_item_id",
+ ALLOCATION_ITEM_COLUMNS);
+
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute("ra-input.service-model", "MY-SERV-MODEL-1");
+ ctx.setAttribute("ra-input.check-only", "false");
+ ctx.setAttribute("ra-input.reservation-entity-type", "VPE-Cust");
+ ctx.setAttribute("ra-input.reservation-entity-id", "gblond2003me6");
+
+ ctx.setAttribute("ra-input.reservation-target-id", "MDTWNJ21A5");
+ ctx.setAttribute("ra-input.reservation-target-type", "Site");
+
+ ctx.setAttribute("ra-input.resource-name", "cust-vlan-id");
+
+ QueryStatus st = resourceAllocator.reserve("NetworkCapacity", null, null, null, ctx);
+
+ Assert.assertTrue(st == QueryStatus.SUCCESS);
+
+ resource.print();
+ allocationItem.print();
+
+ ctx = new SvcLogicContext();
+ ctx.setAttribute("ra-input.service-model", "MY-SERV-MODEL-1");
+ ctx.setAttribute("ra-input.check-only", "false");
+ ctx.setAttribute("ra-input.reservation-entity-type", "VPE-Core1");
+ ctx.setAttribute("ra-input.reservation-entity-id", "gblond2003me6");
+
+ ctx.setAttribute("ra-input.reservation-target-id", "MDTWNJ21A5");
+ ctx.setAttribute("ra-input.reservation-target-type", "Site");
+
+ ctx.setAttribute("ra-input.resource-name", "vlan-id-inner");
+
+ st = resourceAllocator.reserve("NetworkCapacity", null, null, null, ctx);
+
+ Assert.assertTrue(st == QueryStatus.SUCCESS);
+
+ resource.print();
+ allocationItem.print();
+
+ ctx = new SvcLogicContext();
+ ctx.setAttribute("ra-input.service-model", "MY-SERV-MODEL-1");
+ ctx.setAttribute("ra-input.check-only", "false");
+ ctx.setAttribute("ra-input.reservation-entity-type", "VPE-Core2");
+ ctx.setAttribute("ra-input.reservation-entity-id", "gblond2003me6");
+
+ ctx.setAttribute("ra-input.reservation-target-id", "MDTWNJ21A5");
+ ctx.setAttribute("ra-input.reservation-target-type", "Site");
+
+ ctx.setAttribute("ra-input.resource-name", "vlan-id-inner");
+ ctx.setAttribute("ra-input.replace", "false");
+
+ st = resourceAllocator.reserve("NetworkCapacity", null, null, null, ctx);
+
+ Assert.assertTrue(st == QueryStatus.SUCCESS);
+
+ resource.print();
+ allocationItem.print();
+
+ /* Query Using ReservationEntityId using ServiceLogicContext */
+ ctx = new SvcLogicContext();
+ ctx.setAttribute("ra-input.service-model", "MY-SERV-MODEL-1");
+ ctx.setAttribute("ra-input.reservation-entity-id", "gblond2003me6");
+ ctx.setAttribute("ra-input.reservation-entity-type", "VPE-Core1");
+
+ st = resourceAllocator.query("NetworkCapacity", false, null, null, null, null, ctx);
+ Assert.assertTrue(st == QueryStatus.SUCCESS);
+
+ /* Query Using ReservationTargetId using ServiceLogicContext */
+ ctx = new SvcLogicContext();
+ ctx.setAttribute("ra-input.service-model", "MY-SERV-MODEL-1");
+ ctx.setAttribute("ra-input.reservation-target-id", "MDTWNJ21A5");
+ ctx.setAttribute("ra-input.reservation-target-type", "Site");
+ ctx.setAttribute("ra-input.resource-name", "vlan-id-inner");
+
+ st = resourceAllocator.query("NetworkCapacity", false, null, null, null, null, ctx);
+ Assert.assertTrue(st == QueryStatus.SUCCESS);
+
+ log.info("======================== Query Using ResourceEntity==============================");
+ /* Query Using ResourceEntity bean */
+ ResourceEntity sd = new ResourceEntity();
+ sd.resourceEntityId = "gblond2003me6";
+ sd.resourceEntityType = "VPE-Core1";
+
+ ResourceRequest rr = new ResourceRequest();
+ rr.serviceModel = "MY-SERV-MODEL-1";
+ rr.resourceName = "vlan-id-inner";
+ rr.requestType = "New";
+ rr.rangeMaxOverride = -1;
+ rr.rangeMinOverride = -1;
+
+ List<ResourceResponse> rsList = new ArrayList<>();
+ resourceAllocator.query(sd, null, null, rsList);
+
+ rsList.forEach(r -> {
+ StrUtil.info(log, r);
+ });
+
+ /*
+ * log.
+ * info("======================== release Using ResourceEntity=============================="
+ * ); rsList = new ArrayList<ResourceResponse>(); AllocationStatus status =
+ * resourceAllocator.release(sd); Assert.assertTrue(status ==
+ * AllocationStatus.Success);
+ *
+ *
+ * log.
+ * info("======================== Query Using ResourceEntity=============================="
+ * ); rsList = new ArrayList<ResourceResponse>(); resourceAllocator.query(sd,
+ * null, null, rsList);
+ *
+ *
+ * rsList.forEach(r -> { StrUtil.info(log, r); });
+ */
+
+ }
+
+ @Test
+ public void test006() throws Exception {
+ String t = "006";
+ log.info("============== reserve " + t + " ================================");
+ log.info("=== Test successful response - new start - all resources available");
+
+ ResourceEntity sd = new ResourceEntity();
+ sd.resourceEntityId = "gblond2003me6";
+ sd.resourceEntityType = "VPE-Cust";
+
+ ResourceTarget rt = new ResourceTarget();
+ rt.resourceTargetId = "MDTWNJ21A5";
+ rt.resourceTargetType = "Site";
+
+ ResourceRequest rr = new ResourceRequest();
+ rr.serviceModel = "MY-SERV-MODEL-1";
+ rr.resourceName = "cust-vlan-id";
+
+ List<ResourceResponse> rsList = new ArrayList<>();
+ resourceAllocator.reserve(sd, rt, rr, rsList);
+
+ rsList.forEach(r -> {
+ StrUtil.info(log, r);
+ });
+
+ log.info("======================== Query + t ==============================");
+ rsList = new ArrayList<>();
+ resourceAllocator.query(sd, null, rr, rsList);
+
+ rsList.forEach(r -> {
+ StrUtil.info(log, r);
+ });
+ assertNotNull(rsList);
+
+ }
+
+ @Test
+ public void test007() throws Exception {
+ String t = "007";
+ log.info("============== reserve " + t + " ================================");
+ log.info("=== Test successful response - new start - all resources available");
+
+ dataSetup.cleanup();
+
+ TestTable resource = new TestTable(jdbcTemplate, "RESOURCE", "resource_id", RESOURCE_COLUMNS);
+ TestTable allocationItem = new TestTable(jdbcTemplate, "ALLOCATION_ITEM", "allocation_item_id",
+ ALLOCATION_ITEM_COLUMNS);
+
+ ResourceEntity sd = new ResourceEntity();
+ sd.resourceEntityId = "gblond2003me6";
+ sd.resourceEntityType = "VPE";
+ sd.resourceEntityVersion = "1";
+
+ ResourceTarget rt = new ResourceTarget();
+ rt.resourceTargetId = "MDTWNJ21A5";
+ rt.resourceTargetType = "Site";
+
+ ResourceRequest rr = new ResourceRequest();
+ rr.serviceModel = "MY-SERV-MODEL";
+ // rr.resourceName = "vlan-id-outer";
+ rr.endPointPosition = "VPE-Cust";
+ rr.rangeMaxOverride = -1;
+ rr.rangeMinOverride = -1;
+ rr.applicationId = "myapp";
+
+ List<ResourceResponse> rsList = new ArrayList<>();
+ resourceAllocator.reserve(sd, rt, rr, rsList);
+
+ // VPE-Core1
+ sd = new ResourceEntity();
+ sd.resourceEntityId = "gblond2003me6";
+ sd.resourceEntityType = "VPE";
+ sd.resourceEntityVersion = "1";
+
+ rt = new ResourceTarget();
+ rt.resourceTargetId = "MDTWNJ21A5";
+ rt.resourceTargetType = "Site";
+
+ rr = new ResourceRequest();
+ rr.serviceModel = "MY-SERV-MODEL";
+ // rr.resourceName = "vlan-id-filter";
+ rr.endPointPosition = "VPE-Core1";
+ rr.rangeMaxOverride = -1;
+ rr.rangeMinOverride = -1;
+ rr.applicationId = "myapp";
+
+ rsList = new ArrayList<>();
+ resourceAllocator.reserve(sd, rt, rr, rsList);
+
+ // VPE-Core2
+ sd = new ResourceEntity();
+ sd.resourceEntityId = "gblond2003me6";
+ sd.resourceEntityType = "VPE";
+ sd.resourceEntityVersion = "1";
+
+ rt = new ResourceTarget();
+ rt.resourceTargetId = "MDTWNJ21A5";
+ rt.resourceTargetType = "Site";
+
+ rr = new ResourceRequest();
+ rr.serviceModel = "MY-SERV-MODEL";
+ // rr.resourceName = "vlan-id-filter";
+ rr.endPointPosition = "VPE-Core2";
+ rr.rangeMaxOverride = -1;
+ rr.rangeMinOverride = -1;
+ rr.applicationId = "myapp";
+
+ rsList = new ArrayList<>();
+ resourceAllocator.reserve(sd, rt, rr, rsList);
+
+ // VPE-Core3
+ sd = new ResourceEntity();
+ sd.resourceEntityId = "gblond2003me6";
+ sd.resourceEntityType = "VPE";
+ sd.resourceEntityVersion = "1";
+
+ rt = new ResourceTarget();
+ rt.resourceTargetId = "MDTWNJ21A5";
+ rt.resourceTargetType = "Site";
+
+ rr = new ResourceRequest();
+ rr.serviceModel = "MY-SERV-MODEL";
+ // rr.resourceName = "vlan-id-filter";
+ rr.endPointPosition = "VPE-Core3";
+ rr.rangeMaxOverride = -1;
+ rr.rangeMinOverride = -1;
+ rr.applicationId = "myapp";
+
+ rsList = new ArrayList<>();
+ resourceAllocator.reserve(sd, rt, rr, rsList);
+
+ rsList.forEach(r -> {
+ StrUtil.info(log, r);
+ });
+
+ resource.print();
+ allocationItem.print();
+
+ log.info("======================== Query + t ==============================");
+ rsList = new ArrayList<>();
+ resourceAllocator.query(sd, null, rr, rsList);
+
+ rsList.forEach(r -> {
+ StrUtil.info(log, r);
+ });
+
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute("ra-input.reservation-entity-id", "gblond2003me6");
+ ctx.setAttribute("ra-input.reservation-entity-type", "VPE");
+
+ QueryStatus st = resourceAllocator.release("NetworkCapacity", "gblond2003me6", ctx);
+ Assert.assertTrue(st == QueryStatus.SUCCESS);
+
+ }
+
+ @Test
+ public void test008() throws Exception {
+ String t = "008";
+ log.info("============== reserve " + t + " ================================");
+ log.info("=== Test range-force-new-numbers = false");
+
+ String entityId = "reserve" + t;
+ String targetId = "port-id-1";
+ String resourceName = "cust-vlan-id";
+
+ String assetId = "VNF::" + targetId;
+ String resourceUnion = "SI::" + entityId;
+ String resourceSet1 = resourceUnion + "::1";
+ String resourceSet2 = resourceUnion + "::2";
+
+ dataSetup.cleanup();
+
+ dataSetup.setupRangeItem(resourceName, assetId, resourceSet1, resourceUnion, "201");
+
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute("ra-input.service-model", "ADIG");
+ ctx.setAttribute("ra-input.check-only", "false");
+
+ ctx.setAttribute("ra-input.resource-name", resourceName);
+ ctx.setAttribute("ra-input.range-force-new-numbers", "false");
+
+ ctx.setAttribute("ra-input.reservation-entity-type", "SI");
+ ctx.setAttribute("ra-input.reservation-entity-id", entityId);
+ ctx.setAttribute("ra-input.reservation-entity-version", "2");
+
+ ctx.setAttribute("ra-input.reservation-target-id", targetId);
+ ctx.setAttribute("ra-input.reservation-target-type", "VNF");
+
+ QueryStatus st = resourceAllocator.reserve("NetworkCapacity", null, null, null, ctx);
+
+ Assert.assertTrue(st == QueryStatus.SUCCESS);
+ Assert.assertTrue(dataSetup.checkRangeItem(resourceName, assetId, resourceSet1, "201"));
+ Assert.assertTrue(dataSetup.checkRangeItem(resourceName, assetId, resourceSet2, "201"));
+
+ Assert.assertEquals(ctx.getAttribute("resource-list_length"), "1");
+ Assert.assertEquals(ctx.getAttribute("resource-list[0].resource-name"), "cust-vlan-id");
+ Assert.assertEquals(ctx.getAttribute("resource-list[0].resource-target-type"), "VNF");
+ Assert.assertEquals(ctx.getAttribute("resource-list[0].resource-target-id"), "port-id-1");
+ Assert.assertEquals(ctx.getAttribute("resource-list[0].status"), "Success");
+ Assert.assertEquals(ctx.getAttribute("resource-list[0].allocated"), "201");
+ Assert.assertEquals(ctx.getAttribute("resource-list[0].used"), "201");
+ Assert.assertEquals(ctx.getAttribute("resource-list[0].range-list_length"), "1");
+ Assert.assertEquals(ctx.getAttribute("resource-list[0].range-list[0].min"), "2");
+ Assert.assertEquals(ctx.getAttribute("resource-list[0].range-list[0].max"), "1000");
+ }
+
+ @Test
+ public void test009() throws Exception {
+ String t = "009";
+ log.info("============== reserve " + t + " ================================");
+ log.info("=== Test range-force-new-numbers = true");
+
+ String entityId = "reserve" + t;
+ String targetId = "port-id-1";
+ String resourceName = "cust-vlan-id";
+
+ String assetId = "VNF::" + targetId;
+ String resourceUnion = "SI::" + entityId;
+ String resourceSet1 = resourceUnion + "::1";
+ String resourceSet2 = resourceUnion + "::2";
+
+ dataSetup.cleanup();
+
+ dataSetup.setupRangeItem(resourceName, assetId, resourceSet1, resourceUnion, "201");
+
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute("ra-input.service-model", "ADIG");
+ ctx.setAttribute("ra-input.check-only", "false");
+
+ ctx.setAttribute("ra-input.resource-name", resourceName);
+ ctx.setAttribute("ra-input.range-force-new-numbers", "true");
+
+ ctx.setAttribute("ra-input.reservation-entity-type", "SI");
+ ctx.setAttribute("ra-input.reservation-entity-id", entityId);
+ ctx.setAttribute("ra-input.reservation-entity-version", "2");
+
+ ctx.setAttribute("ra-input.reservation-target-id", targetId);
+ ctx.setAttribute("ra-input.reservation-target-type", "VNF");
+
+ QueryStatus st = resourceAllocator.reserve("NetworkCapacity", null, null, null, ctx);
+
+ Assert.assertTrue(st == QueryStatus.SUCCESS);
+ Assert.assertTrue(dataSetup.checkRangeItem(resourceName, assetId, resourceSet1, "201"));
+ Assert.assertFalse(dataSetup.checkRangeItem(resourceName, assetId, resourceSet2, "201"));
+ }
+
+ @Test
+ public void test0010_vlantag_with_resourcemodel() throws Exception {
+
+ String t = "0010";
+ log.info("============== reserve " + t + " ================================");
+
+ dataSetup.cleanup();
+
+ TestTable resource = new TestTable(jdbcTemplate, "RESOURCE", "resource_id", RESOURCE_COLUMNS);
+ TestTable allocationItem = new TestTable(jdbcTemplate, "ALLOCATION_ITEM", "allocation_item_id",
+ ALLOCATION_ITEM_COLUMNS);
+
+ ResourceEntity sd = new ResourceEntity();
+ sd.resourceEntityId = "gblond2003me6";
+ sd.resourceEntityType = "VNF";
+ sd.resourceEntityVersion = "1";
+
+ ResourceTarget rt = new ResourceTarget();
+ rt.resourceTargetId = "MDTWNJ21A5";
+ rt.resourceTargetType = "Site";
+
+ ResourceRequest rr = new ResourceRequest();
+ rr.serviceModel = "MY-SERV-MODEL_3456";
+ rr.resourceName = "vlan-id-outer";
+ rr.endPointPosition = "VPE-Core1";
+ rr.rangeMaxOverride = 3901;
+ rr.rangeMinOverride = 3900;
+ rr.resourceType = ResourceType.Range;
+ rr.applicationId = "myapp";
+
+ List<ResourceResponse> rsList = new ArrayList<>();
+ resourceAllocator.reserve(sd, rt, rr, rsList);
+
+ resource.print();
+ allocationItem.print();
+
+ Range range = new Range();
+ range.min = 3900;
+ range.max = 3901;
+
+ sd = new ResourceEntity();
+ sd.resourceEntityId = "gblond2003me6";
+ sd.resourceEntityType = "VNF";
+ sd.resourceEntityVersion = "1";
+
+ rt = new ResourceTarget();
+ rt.resourceTargetId = "MDTWNJ21A5";
+ rt.resourceTargetType = "Site";
+
+ rr = new ResourceRequest();
+ rr.serviceModel = "MY-SERV-MODEL_3456";
+ rr.resourceName = "vlan-id-outer";
+ rr.endPointPosition = "VPE-Core2";
+ rr.rangeMaxOverride = -1;
+ rr.rangeMinOverride = -1;
+ rr.rangeOverrideList = Arrays.asList(range);
+ rr.resourceType = ResourceType.Range;
+ rr.applicationId = "myapp";
+
+ rsList = new ArrayList<>();
+ resourceAllocator.reserve(sd, rt, rr, rsList);
+
+ resource.print();
+ allocationItem.print();
+
+ sd = new ResourceEntity();
+ sd.resourceEntityId = "gblond2003me6";
+ sd.resourceEntityType = "VNF";
+ sd.resourceEntityVersion = "1";
+
+ rt = new ResourceTarget();
+ rt.resourceTargetId = "MDTWNJ21A5";
+ rt.resourceTargetType = "Site";
+
+ Range range1 = new Range();
+ range1.min = 3900;
+ range1.max = 3901;
+
+ Range range2 = new Range();
+ range2.min = 3904;
+ range2.max = 3905;
+
+ rr = new ResourceRequest();
+ rr.serviceModel = "MY-SERV-MODEL_3456";
+ rr.resourceName = "vlan-id-outer";
+ rr.endPointPosition = "VPE-Core3";
+ rr.rangeMaxOverride = -1;
+ rr.rangeMinOverride = -1;
+ rr.rangeOverrideList = new ArrayList<>();
+ rr.rangeOverrideList.add(range1);
+ rr.rangeOverrideList.add(range2);
+ rr.applicationId = "myapp";
+ rr.resourceType = ResourceType.Range;
+
+ rsList = new ArrayList<>();
+ AllocationStatus status = resourceAllocator.reserve(sd, rt, rr, rsList);
+ Assert.assertTrue(status == AllocationStatus.Success);
+
+ resource.print();
+ allocationItem.print();
+
+ sd = new ResourceEntity();
+ sd.resourceEntityId = "gblond2003me6";
+ sd.resourceEntityType = "VNF";
+ sd.resourceEntityVersion = "1";
+
+ rr = new ResourceRequest();
+ rr.endPointPosition = "VPE-Core2";
+ status = resourceAllocator.release(sd, rr);
+ Assert.assertTrue(status == AllocationStatus.Success);
+
+ resource.print();
+ allocationItem.print();
+
+ }
+
+ @Test
+ public void test011() throws Exception {
+ String t = "011";
+ log.info("============== reserve " + t + " ================================");
+ log.info("=== Test range-next-in-sequence = true");
+
+ String entityId = "reserve" + t;
+ String targetId = "port-id-1";
+ String resourceName = "vlan-id-filter";
+
+ String assetId = "Site::" + targetId;
+ String resourceUnion = "SI::" + entityId;
+ String resourceSet = resourceUnion + "::1";
+
+ dataSetup.cleanup();
+ dataSetup.setupRangeItem(resourceName, assetId, resourceSet, resourceUnion, "1002,1004,1006,1008");
+
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute("ra-input.service-model", "MY-SERV-MODEL");
+ ctx.setAttribute("ra-input.endpoint-position", "VPE-Core2");
+ ctx.setAttribute("ra-input.check-only", "false");
+
+ ctx.setAttribute("ra-input.resource-name", resourceName);
+ ctx.setAttribute("ra-input.range-next-in-sequence", "true");
+
+ ctx.setAttribute("ra-input.reservation-entity-type", "SI");
+ ctx.setAttribute("ra-input.reservation-entity-id", entityId + "_test");
+ ctx.setAttribute("ra-input.reservation-entity-version", "1");
+
+ ctx.setAttribute("ra-input.reservation-target-id", targetId);
+ ctx.setAttribute("ra-input.reservation-target-type", "Site");
+
+ QueryStatus st = resourceAllocator.reserve("NetworkCapacity", null, null, null, ctx);
+
+ Assert.assertTrue(st == QueryStatus.SUCCESS);
+ Assert.assertTrue(dataSetup.checkRangeItem(resourceName, assetId, "SI::" + entityId + "_test::VPE-Core2::1", "1009"));
+ }
+
+ @Test
+ public void test012() throws Exception {
+ String t = "012";
+ log.info("============== reserve " + t + " ================================");
+ log.info("=== Test range-next-in-sequence = false");
+
+ String entityId = "reserve" + t;
+ String targetId = "port-id-1";
+ String resourceName = "vlan-id-filter";
+
+ String assetId = "Site::" + targetId;
+ String resourceUnion = "SI::" + entityId;
+ String resourceSet = resourceUnion + "::1";
+
+ dataSetup.cleanup();
+ dataSetup.setupRangeItem(resourceName, assetId, resourceSet, resourceUnion, "1002,1004,1006,1008");
+
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute("ra-input.service-model", "MY-SERV-MODEL");
+ ctx.setAttribute("ra-input.endpoint-position", "VPE-Core2");
+ ctx.setAttribute("ra-input.check-only", "false");
+
+ ctx.setAttribute("ra-input.resource-name", resourceName);
+ ctx.setAttribute("ra-input.range-next-in-sequence", "false");
+
+ ctx.setAttribute("ra-input.reservation-entity-type", "SI");
+ ctx.setAttribute("ra-input.reservation-entity-id", entityId + "_test");
+ ctx.setAttribute("ra-input.reservation-entity-version", "1");
+
+ ctx.setAttribute("ra-input.reservation-target-id", targetId);
+ ctx.setAttribute("ra-input.reservation-target-type", "Site");
+
+ QueryStatus st = resourceAllocator.reserve("NetworkCapacity", null, null, null, ctx);
+
+ Assert.assertTrue(st == QueryStatus.SUCCESS);
+ Assert.assertTrue(dataSetup.checkRangeItem(resourceName, assetId, "SI::" + entityId + "_test::VPE-Core2::1", "1003"));
+ }
+
+ @Test
+ public void test013() throws Exception {
+ String t = "013";
+ log.info("============== reserve " + t + " ================================");
+ log.info("=== Test range-next-in-sequence = true - multiple ranges");
+
+ String entityId = "reserve" + t;
+ String targetId = "port-id-1";
+ String resourceName = "vlan-id-filter";
+
+ String assetId = "Site::" + targetId;
+ String resourceUnion = "SI::" + entityId;
+ String resourceSet = resourceUnion + "::1";
+
+ dataSetup.cleanup();
+ dataSetup.setupRangeItem(resourceName, assetId, resourceSet, resourceUnion, "1002,1004,1006,1008,2205-2221");
+
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute("ra-input.service-model", "MY-SERV-MODEL");
+ ctx.setAttribute("ra-input.endpoint-position", "VPE-Core2");
+ ctx.setAttribute("ra-input.check-only", "false");
+
+ ctx.setAttribute("ra-input.resource-name", resourceName);
+ ctx.setAttribute("ra-input.range-next-in-sequence", "true");
+
+ ctx.setAttribute("ra-input.reservation-entity-type", "SI");
+ ctx.setAttribute("ra-input.reservation-entity-id", entityId + "_test");
+ ctx.setAttribute("ra-input.reservation-entity-version", "1");
+
+ ctx.setAttribute("ra-input.reservation-target-id", targetId);
+ ctx.setAttribute("ra-input.reservation-target-type", "Site");
+
+ QueryStatus st = resourceAllocator.reserve("NetworkCapacity", null, null, null, ctx);
+
+ Assert.assertTrue(st == QueryStatus.SUCCESS);
+ Assert.assertTrue(dataSetup.checkRangeItem(resourceName, assetId, "SI::" + entityId + "_test::VPE-Core2::1", "2222"));
+ }
+
+ @Test
+ public void test014() throws Exception {
+ String t = "014";
+ log.info("============== reserve " + t + " ================================");
+ log.info("=== Test range-next-in-sequence = true - no previously reserved numbers");
+
+ String entityId = "reserve" + t;
+ String targetId = "port-id-1";
+ String resourceName = "vlan-id-filter";
+
+ String assetId = "Site::" + targetId;
+
+ dataSetup.cleanup();
+
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute("ra-input.service-model", "MY-SERV-MODEL");
+ ctx.setAttribute("ra-input.endpoint-position", "VPE-Core2");
+ ctx.setAttribute("ra-input.check-only", "false");
+
+ ctx.setAttribute("ra-input.resource-name", resourceName);
+ ctx.setAttribute("ra-input.range-next-in-sequence", "true");
+
+ ctx.setAttribute("ra-input.reservation-entity-type", "SI");
+ ctx.setAttribute("ra-input.reservation-entity-id", entityId + "_test");
+ ctx.setAttribute("ra-input.reservation-entity-version", "1");
+
+ ctx.setAttribute("ra-input.reservation-target-id", targetId);
+ ctx.setAttribute("ra-input.reservation-target-type", "Site");
+
+ QueryStatus st = resourceAllocator.reserve("NetworkCapacity", null, null, null, ctx);
+
+ Assert.assertTrue(st == QueryStatus.SUCCESS);
+ Assert.assertTrue(dataSetup.checkRangeItem(resourceName, assetId, "SI::" + entityId + "_test::VPE-Core2::1", "1002"));
+ }
+}
diff --git a/adaptors/resource-assignment/provider/src/test/java/jtest/org/onap/ccsdk/sli/adaptors/ra/TestResourceLockNode.java b/adaptors/resource-assignment/provider/src/test/java/jtest/org/onap/ccsdk/sli/adaptors/ra/TestResourceLockNode.java
new file mode 100644
index 000000000..dc0761c20
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/test/java/jtest/org/onap/ccsdk/sli/adaptors/ra/TestResourceLockNode.java
@@ -0,0 +1,39 @@
+package jtest.org.onap.ccsdk.sli.adaptors.ra;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.Assert;
+import org.junit.FixMethodOrder;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.MethodSorters;
+import org.onap.ccsdk.sli.adaptors.ra.ResourceLockNode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(locations = { "classpath:test-context.xml" })
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class TestResourceLockNode {
+
+ @SuppressWarnings("unused")
+ private static final Logger log = LoggerFactory.getLogger(TestResourceLockNode.class);
+
+ @Autowired
+ private ResourceLockNode resourceLockNode;
+
+ @Test
+ public void test1() throws Exception {
+ Map<String, String> paramMap = new HashMap<>();
+ paramMap.put("resource-name", "test-resource-1");
+ paramMap.put("lock-requester", "SDNA");
+
+ resourceLockNode.lockResource(paramMap, null);
+ resourceLockNode.unlockResource(paramMap, null);
+ Assert.assertNotNull(paramMap);
+ }
+}
diff --git a/adaptors/resource-assignment/provider/src/test/java/jtest/org/onap/ccsdk/sli/adaptors/rm/util/LabelUtilTest.java b/adaptors/resource-assignment/provider/src/test/java/jtest/org/onap/ccsdk/sli/adaptors/rm/util/LabelUtilTest.java
new file mode 100644
index 000000000..eb903ecdc
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/test/java/jtest/org/onap/ccsdk/sli/adaptors/rm/util/LabelUtilTest.java
@@ -0,0 +1,45 @@
+package jtest.org.onap.ccsdk.sli.adaptors.rm.util;
+
+import org.junit.Test;
+import org.onap.ccsdk.sli.adaptors.rm.data.AllocationItem;
+import org.onap.ccsdk.sli.adaptors.rm.data.LabelAllocationRequest;
+import org.onap.ccsdk.sli.adaptors.rm.data.LabelResource;
+import org.onap.ccsdk.sli.adaptors.rm.util.LabelUtil;
+
+import java.util.Date;
+
+import static org.junit.Assert.*;
+
+public class LabelUtilTest {
+
+ @Test
+ public void testLabelUtils() {
+ LabelAllocationRequest req = new LabelAllocationRequest();
+ req.check = true;
+ req.allocate = true;
+ req.label = "testLabel";
+ req.resourceUnionId = "123";
+ req.applicationId = "testApp";
+ req.assetId = "asset1";
+ req.resourceName = "resource1";
+ req.resourceSetId = "set1";
+
+
+
+ LabelResource resource = new LabelResource();
+ resource.label = "testLabel";
+
+ LabelUtil.allocateLabel(resource, req);
+ LabelUtil.checkLabel(resource, req);
+ LabelUtil.recalculate(resource);
+
+
+
+
+
+
+
+ }
+
+
+} \ No newline at end of file
diff --git a/adaptors/resource-assignment/provider/src/test/java/jtest/util/org/onap/ccsdk/sli/adaptors/ra/TestDb.java b/adaptors/resource-assignment/provider/src/test/java/jtest/util/org/onap/ccsdk/sli/adaptors/ra/TestDb.java
new file mode 100644
index 000000000..6446240dc
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/test/java/jtest/util/org/onap/ccsdk/sli/adaptors/ra/TestDb.java
@@ -0,0 +1,37 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package jtest.util.org.onap.ccsdk.sli.adaptors.ra;
+
+import org.springframework.jdbc.core.JdbcTemplate;
+
+public class TestDb {
+
+ private JdbcTemplate jdbcTemplate;
+
+ public TestTable table(String tableName, String idName, String... columnList) {
+ return new TestTable(jdbcTemplate, tableName, idName, columnList);
+ }
+
+ public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
+ this.jdbcTemplate = jdbcTemplate;
+ }
+}
diff --git a/adaptors/resource-assignment/provider/src/test/java/jtest/util/org/onap/ccsdk/sli/adaptors/ra/TestTable.java b/adaptors/resource-assignment/provider/src/test/java/jtest/util/org/onap/ccsdk/sli/adaptors/ra/TestTable.java
new file mode 100644
index 000000000..e2541f393
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/test/java/jtest/util/org/onap/ccsdk/sli/adaptors/ra/TestTable.java
@@ -0,0 +1,135 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package jtest.util.org.onap.ccsdk.sli.adaptors.ra;
+
+import java.sql.ResultSetMetaData;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.jdbc.core.JdbcTemplate;
+import org.springframework.jdbc.support.rowset.SqlRowSet;
+
+public class TestTable {
+
+ private String tableName;
+ private String[] columnList;
+ private String idName;
+
+ private String insertSql;
+
+ private JdbcTemplate jdbcTemplate;
+
+ private static final Logger log = LoggerFactory.getLogger(TestTable.class);
+
+ public TestTable(JdbcTemplate jdbcTemplate, String tableName, String idName, String... columnList) {
+ this.jdbcTemplate = jdbcTemplate;
+ this.tableName = tableName;
+ this.idName = idName;
+ this.columnList = columnList;
+ createInsertSql();
+ }
+
+ public TestTable(JdbcTemplate jdbcTemplate, String tableName) {
+ this.jdbcTemplate = jdbcTemplate;
+ this.tableName = tableName;
+ }
+
+ private void createInsertSql() {
+ StringBuilder ss = new StringBuilder();
+ ss.append("INSERT INTO ").append(tableName).append(" (");
+ for (String s : columnList)
+ ss.append(s).append(", ");
+ ss.setLength(ss.length() - 2);
+ ss.append(") VALUES (");
+ for (int i = 0; i < columnList.length; i++)
+ ss.append("?, ");
+ ss.setLength(ss.length() - 2);
+ ss.append(")");
+ insertSql = ss.toString();
+ }
+
+ public void add(Object... values) {
+ jdbcTemplate.update(insertSql, values);
+ }
+
+ public void update(String updateSql, Object... values) {
+ jdbcTemplate.update(updateSql, values);
+ }
+
+ public long getLastId() {
+ return jdbcTemplate.queryForObject("SELECT max(" + idName + ") FROM " + tableName, Long.class);
+ }
+
+ public Long getId(String where) {
+ String selectSql = "SELECT " + idName + " FROM " + tableName + " WHERE " + where;
+ SqlRowSet rs = jdbcTemplate.queryForRowSet(selectSql);
+ if (rs.first())
+ return rs.getLong(idName);
+ return null;
+ }
+
+ public Object getColumn(String columnName, String where) {
+ String selectSql = "SELECT " + columnName + " FROM " + tableName + " WHERE " + where;
+ SqlRowSet rs = jdbcTemplate.queryForRowSet(selectSql);
+ if (rs.first())
+ return rs.getObject(columnName);
+ return null;
+ }
+
+ public boolean exists(String where) {
+ String selectSql = "SELECT * FROM " + tableName + " WHERE " + where;
+ SqlRowSet rs = jdbcTemplate.queryForRowSet(selectSql);
+ return rs.first();
+ }
+
+ public void delete(String where) {
+ jdbcTemplate.update("DELETE FROM " + tableName + " WHERE " + where);
+ }
+
+ public void print() {
+
+ jdbcTemplate.query("SELECT * FROM " + tableName,
+ (rs, rowNum) -> {
+ String row = "Table Data for " + tableName +"\n";
+ String col = "";
+
+ final ResultSetMetaData meta = rs.getMetaData();
+ final int columnCount = meta.getColumnCount();
+
+ do {
+ col = "";
+
+ for (int column = 1; column <= columnCount; ++column) {
+ Object obj = rs.getObject(column);
+ if(!rs.wasNull()) {
+ col = col + obj + ",";
+ }
+ }
+ col = col.trim().length() == 0 ? "" : (col.trim().substring(0, col.trim().length() - 1));
+ row = row + col + "\n";
+ } while (rs.next());
+
+ return row;
+ }).forEach(row -> {
+ log.info(row);
+ });
+ }
+} \ No newline at end of file
diff --git a/adaptors/resource-assignment/provider/src/test/resources/log4j.properties b/adaptors/resource-assignment/provider/src/test/resources/log4j.properties
new file mode 100644
index 000000000..34dcdfb68
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/test/resources/log4j.properties
@@ -0,0 +1,26 @@
+###
+# ============LICENSE_START=======================================================
+# openECOMP : SDN-C
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights
+# reserved.
+# ================================================================================
+# 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.
+# ============LICENSE_END=========================================================
+###
+
+log4j.rootLogger=INFO, A1
+log4j.appender.A1=org.apache.log4j.ConsoleAppender
+log4j.appender.A1.layout=org.apache.log4j.PatternLayout
+log4j.appender.A1.layout.ConversionPattern=%d{ISO8601} %5p %t %X{UUID} %c{3}:%L - %m%n
+log4j.logger.org.hibernate=INFO
diff --git a/adaptors/resource-assignment/provider/src/test/resources/sql/data.sql b/adaptors/resource-assignment/provider/src/test/resources/sql/data.sql
new file mode 100644
index 000000000..236a16d18
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/test/resources/sql/data.sql
@@ -0,0 +1,180 @@
+---
+-- ============LICENSE_START=======================================================
+-- openECOMP : SDN-C
+-- ================================================================================
+-- Copyright (C) 2017 AT&T Intellectual Property. All rights
+-- reserved.
+-- ================================================================================
+-- 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.
+-- ============LICENSE_END=========================================================
+---
+
+INSERT INTO RESOURCE_RULE (
+ resource_name, service_model, end_point_position, service_expression, equipment_level, equipment_expression,
+ allocation_expression, soft_limit_expression, hard_limit_expression)
+VALUES (
+ 'Bandwidth', 'L3SDN', 'IPAG-TOA', 'true', 'Port', 'true',
+ 'service-speed-kbps', '0.5 * max-port-speed', '0.9 * max-port-speed');
+
+INSERT INTO RESOURCE_RULE (
+ resource_name, service_model, end_point_position, service_expression, equipment_level, equipment_expression,
+ allocation_expression, soft_limit_expression, hard_limit_expression)
+VALUES (
+ 'Bandwidth', 'L3SDN', 'VCE-Cust', 'true', 'Server', 'true',
+ 'service-speed-kbps', '0.6 * max-server-speed * number-primary-servers', 'max-server-speed * number-primary-servers');
+
+INSERT INTO RESOURCE_RULE (
+ resource_name, service_model, end_point_position, service_expression, equipment_level,
+ equipment_expression, allocation_expression, soft_limit_expression, hard_limit_expression)
+VALUES (
+ 'Connection', 'L3SDN', 'VCE-Cust', 'true', 'Server',
+ 'true', '1', '40', '40');
+
+INSERT INTO RESOURCE_RULE (
+ resource_name, service_model, end_point_position, service_expression, equipment_level, equipment_expression,
+ allocation_expression, soft_limit_expression, hard_limit_expression)
+VALUES (
+ 'Bandwidth', 'L3SDN', 'VPE-Cust', 'true', 'Port', 'true',
+ 'service-speed-kbps', '0.5 * max-port-speed', '0.9 * max-port-speed');
+
+INSERT INTO RESOURCE_RULE (
+ resource_name, service_model, end_point_position, service_expression,
+ equipment_level, equipment_expression, allocation_expression, soft_limit_expression, hard_limit_expression)
+VALUES (
+ 'Bandwidth', 'L3AVPN-EVC', 'VPE-Cust', 'true', 'Port', 'true', 'service-speed-kbps', '8000000', '8000000');
+
+INSERT INTO RESOURCE_RULE (
+ resource_name, service_model, end_point_position, service_expression,
+ equipment_level, equipment_expression, allocation_expression, soft_limit_expression, hard_limit_expression)
+VALUES (
+ 'Connection', 'L3AVPN-EVC', 'VPE-Cust', 'true', 'Port', 'true', '1', '200', '200');
+
+INSERT INTO RESOURCE_RULE (
+ resource_name, service_model, end_point_position, service_expression,
+ equipment_level, equipment_expression, allocation_expression, soft_limit_expression, hard_limit_expression)
+VALUES (
+ 'Bandwidth', 'L3AVPN-PORT', 'VPE-Cust', 'true', 'Port', 'true', 'service-speed-kbps', '8000000', '8000000');
+
+insert into RESOURCE_THRESHOLD (
+ resource_rule_id, threshold_expression, threshold_message)
+values (
+ (select resource_rule_id from RESOURCE_RULE where resource_name = 'Bandwidth' and equipment_level = 'Server'),
+ '0.5 * max-server-speed * number-primary-servers',
+ 'The provisioned access bandwidth is at or exceeds 50% of the total server capacity.');
+
+insert into RESOURCE_THRESHOLD (
+ resource_rule_id, threshold_expression, threshold_message)
+values (
+ (select resource_rule_id from RESOURCE_RULE where resource_name = 'Bandwidth' and equipment_level = 'Server'),
+ '0.7 * max-server-speed * number-primary-servers',
+ 'The provisioned access bandwidth is at or exceeds 70% of the total server capacity.');
+
+INSERT INTO RANGE_RULE (
+ range_name, service_model, end_point_position, equipment_level, equipment_expression, ranges)
+VALUES (
+ 'subinterface-id', 'L3AVPN-EVC', 'VPE-Cust', 'Port', 'true', '100-3999');
+
+INSERT INTO RANGE_RULE (
+ range_name, service_model, end_point_position, equipment_level, equipment_expression, ranges)
+VALUES (
+ 'vlan-id-inner', 'L3AVPN-EVC', 'VPE-Cust', 'Port', 'true', '2-4091');
+
+INSERT INTO RANGE_RULE (
+ range_name, service_model, end_point_position, equipment_level, equipment_expression, ranges)
+VALUES (
+ 'bundle-id', 'L3AVPN-PORT', 'VPE-Cust', 'Port', 'true', '1-99999');
+
+INSERT INTO MAX_PORT_SPEED (
+ image_file_name, end_point_position, interface_name, max_speed, unit)
+VALUES (
+ 'JUNIPER_VPE_IMAGE_FILENAME', 'VPE-Cust', 'ae0', 5000, 'Mpbs');
+
+INSERT INTO MAX_SERVER_SPEED (server_model, evc_count, max_speed, unit, description)
+VALUES ('ALL', 5, 1600, 'Mbps', 'Max speed, when there are <=5 EVC on server');
+
+INSERT INTO MAX_SERVER_SPEED (server_model, evc_count, max_speed, unit, description)
+VALUES ('ALL', 10, 1400, 'Mbps', 'Max speed, when there are 6 to 10 (including 10) EVC on server');
+
+INSERT INTO MAX_SERVER_SPEED (server_model, evc_count, max_speed, unit, description)
+VALUES ('ALL', 15, 1000, 'Mbps', 'Max speed, when there are 11 to 15 (including 15) EVC on server');
+
+INSERT INTO MAX_SERVER_SPEED (server_model, evc_count, max_speed, unit, description)
+VALUES ('ALL', 20, 700, 'Mbps', 'Max speed, when there are 16 to 20 (including 20) EVC on server');
+
+INSERT INTO MAX_SERVER_SPEED (server_model, evc_count, max_speed, unit, description)
+VALUES ('ALL', 10000, 500, 'Mbps', 'Max speed, when there are 21 or more EVC on server');
+
+INSERT INTO PARAMETERS (name, value, category, memo)
+VALUES ('homing.pserver.sparing.ratio', '1:1', 'homing',
+ 'Ratio of primary to backup servers within any of the AIC sites. Used in RA to calculate the max allowed bw in an AIC site.');
+
+INSERT INTO RESOURCE_RULE (
+ resource_name, service_model, end_point_position, service_expression, equipment_level, equipment_expression,
+ allocation_expression, soft_limit_expression, hard_limit_expression)
+VALUES (
+ 'PortBandwidth', 'ADIG', 'VPE', 'true', 'Port', 'true',
+ 'service-speed-mbps', 'service-speed-mbps', 'service-speed-mbps');
+
+INSERT INTO RESOURCE_RULE (
+ resource_name, service_model, end_point_position, service_expression, equipment_level, equipment_expression,
+ allocation_expression, soft_limit_expression, hard_limit_expression)
+VALUES (
+ 'Bandwidth', 'ADIG', 'VPE', 'true', 'VNF', 'vnf-type = "VPE"',
+ 'service-speed-mbps', '0.5 * max-vpe-bandwidth-mbps', '0.9 * max-vpe-bandwidth-mbps');
+
+
+INSERT INTO RESOURCE_RULE (
+ resource_name, service_model, end_point_position, service_expression, equipment_level, equipment_expression,
+ allocation_expression, soft_limit_expression, hard_limit_expression)
+VALUES (
+ 'Bandwidth', 'ADIG', 'VPE', 'true', 'AffinityLink', 'true',
+ 'service-speed-mbps', '9999999999', '9999999999');
+
+INSERT INTO RESOURCE_RULE (
+ resource_name, service_model, end_point_position, service_expression, equipment_level, equipment_expression,
+ allocation_expression, soft_limit_expression, hard_limit_expression)
+VALUES (
+ 'Connection', 'ADIG', 'VPE', 'true', 'VNF', 'true',
+ '1', '200', '200');
+
+INSERT INTO RANGE_RULE (
+ range_name, service_model, end_point_position, equipment_level, equipment_expression, ranges)
+VALUES (
+ 'cust-vlan-id', 'ADIG', 'VPE', 'VNF', 'true', '2-1000');
+
+INSERT INTO RANGE_RULE (
+ range_name, service_model, end_point_position, equipment_level, equipment_expression, ranges)
+VALUES (
+ 'vlan-id-inner', 'ADIG', 'VPE', 'VNF', 'true', '1002-2000');
+
+
+INSERT INTO RANGE_RULE (
+ range_name, service_model, end_point_position, equipment_level, equipment_expression, ranges)
+VALUES (
+ 'vlan-id-outer', 'MY-SERV-MODEL', 'VPE-Cust', 'Site', 'true', '2-1000');
+
+INSERT INTO RANGE_RULE (
+ range_name, service_model, end_point_position, equipment_level, equipment_expression, ranges)
+VALUES (
+ 'vlan-id-filter', 'MY-SERV-MODEL', 'VPE-Core1', 'Site', 'true', '1002-2000');
+
+INSERT INTO RANGE_RULE (
+ range_name, service_model, end_point_position, equipment_level, equipment_expression, ranges)
+VALUES (
+ 'vlan-id-filter', 'MY-SERV-MODEL', 'VPE-Core2', 'Site', 'true', '1002-2000,2200-4000');
+
+INSERT INTO RANGE_RULE (
+ range_name, service_model, end_point_position, equipment_level, equipment_expression, ranges)
+VALUES (
+ 'vlan-id-filter', 'MY-SERV-MODEL', 'VPE-Core3', 'Site', 'true', '400-600');
+ \ No newline at end of file
diff --git a/adaptors/resource-assignment/provider/src/test/resources/sql/schema.sql b/adaptors/resource-assignment/provider/src/test/resources/sql/schema.sql
new file mode 100644
index 000000000..275337e44
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/test/resources/sql/schema.sql
@@ -0,0 +1,201 @@
+---
+-- ============LICENSE_START=======================================================
+-- openECOMP : SDN-C
+-- ================================================================================
+-- Copyright (C) 2017 AT&T Intellectual Property. All rights
+-- reserved.
+-- ================================================================================
+-- 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.
+-- ============LICENSE_END=========================================================
+---
+
+CREATE TABLE RESOURCE_LOCK (
+ resource_lock_id SERIAL PRIMARY KEY,
+ resource_name VARCHAR(50) NOT NULL UNIQUE,
+ lock_holder VARCHAR(100) NOT NULL,
+ lock_count SMALLINT NOT NULL,
+ lock_time DATETIME NOT NULL,
+ expiration_time DATETIME NOT NULL
+);
+
+CREATE TABLE RESOURCE (
+ resource_id SERIAL PRIMARY KEY,
+ asset_id VARCHAR(50) NOT NULL,
+ resource_name VARCHAR(50) NOT NULL,
+ resource_type VARCHAR(10) NOT NULL,
+ lt_used BIGINT,
+ ll_label VARCHAR(50),
+ ll_reference_count SMALLINT,
+ rr_used VARCHAR(4000)
+);
+
+ALTER TABLE RESOURCE ADD CONSTRAINT c1_resource CHECK (resource_type IN ('Limit', 'Label', 'Range'));
+CREATE UNIQUE INDEX ak1_resource ON RESOURCE (asset_id, resource_name);
+
+CREATE TABLE RESOURCE_LOAD (
+ resource_load_id SERIAL PRIMARY KEY,
+ resource_id BIGINT NOT NULL REFERENCES resource (resource_id),
+ application_id VARCHAR(20) NOT NULL,
+ resource_load_time DATETIME NOT NULL,
+ resource_expiration_time DATETIME
+);
+
+CREATE INDEX i1_resource_load ON RESOURCE_LOAD (resource_id);
+CREATE UNIQUE INDEX ak1_resource_load ON RESOURCE_LOAD (resource_id, application_id);
+
+CREATE TABLE ALLOCATION_ITEM (
+ allocation_item_id SERIAL PRIMARY KEY,
+ resource_id BIGINT NOT NULL REFERENCES resource (resource_id),
+ application_id VARCHAR(50) NOT NULL,
+ resource_set_id VARCHAR(50) NOT NULL,
+ resource_union_id VARCHAR(50) NOT NULL,
+ resource_share_group_list VARCHAR(200),
+ lt_used BIGINT,
+ ll_label VARCHAR(50),
+ rr_used VARCHAR(200),
+ allocation_time DATETIME NOT NULL
+);
+
+CREATE INDEX i1_allocation_item ON allocation_item (resource_id);
+CREATE UNIQUE INDEX ak1_allocation_item ON allocation_item (resource_id, resource_set_id);
+
+CREATE TABLE RESOURCE_RULE (
+ resource_rule_id SERIAL PRIMARY KEY,
+ resource_name VARCHAR(50) NOT NULL,
+ service_model VARCHAR(50) NOT NULL,
+ end_point_position VARCHAR(50) NOT NULL,
+ service_expression VARCHAR(2000) NOT NULL,
+ equipment_level VARCHAR(50) NOT NULL,
+ equipment_expression VARCHAR(2000) NOT NULL,
+ allocation_expression VARCHAR(2000) NOT NULL,
+ soft_limit_expression VARCHAR(2000) NOT NULL,
+ hard_limit_expression VARCHAR(2000) NOT NULL
+);
+
+CREATE TABLE RESOURCE_THRESHOLD (
+ resource_threshold_id bigint(20) unsigned NOT NULL AUTO_INCREMENT,
+ resource_rule_id bigint(20) NOT NULL,
+ threshold_expression varchar(2000) NOT NULL,
+ threshold_message varchar(2000) NOT NULL,
+ PRIMARY KEY (resource_threshold_id)
+);
+
+CREATE TABLE RANGE_RULE (
+ range_rule_id SERIAL PRIMARY KEY,
+ range_name VARCHAR(50) NOT NULL,
+ service_model VARCHAR(50) NOT NULL,
+ end_point_position VARCHAR(50) NOT NULL,
+ equipment_level VARCHAR(50) NOT NULL,
+ equipment_expression VARCHAR(2000) NOT NULL,
+ ranges VARCHAR(100) NOT NULL
+);
+
+CREATE TABLE MAX_PORT_SPEED (
+ max_port_speed_id SERIAL PRIMARY KEY,
+ image_file_name VARCHAR(50) NOT NULL,
+ end_point_position VARCHAR(50) NOT NULL,
+ interface_name VARCHAR(100) NOT NULL,
+ max_speed BIGINT NOT NULL,
+ unit VARCHAR(10) NOT NULL
+);
+
+CREATE TABLE MAX_SERVER_SPEED (
+ max_server_speed_id SERIAL PRIMARY KEY,
+ server_model VARCHAR(50) NOT NULL,
+ evc_count SMALLINT NOT NULL,
+ max_speed BIGINT NOT NULL,
+ unit VARCHAR(10) NOT NULL,
+ description VARCHAR(500)
+);
+
+CREATE TABLE SERVICE_RESOURCE (
+ service_resource_id SERIAL PRIMARY KEY,
+ service_instance_id VARCHAR(80) NOT NULL,
+ service_status VARCHAR(10) NOT NULL,
+ service_change_number SMALLINT NOT NULL,
+ resource_set_id VARCHAR(100) NOT NULL,
+ resource_union_id VARCHAR(100) NOT NULL
+);
+
+ALTER TABLE SERVICE_RESOURCE ADD CONSTRAINT C1_SERVICE_RESOURCE CHECK (service_status IN ('Active', 'Pending'));
+CREATE INDEX i1_service_resource ON SERVICE_RESOURCE (service_instance_id);
+CREATE UNIQUE INDEX ak1_service_resource ON SERVICE_RESOURCE (service_instance_id, service_change_number);
+
+CREATE TABLE VPE_POOL (
+ vpe_name VARCHAR(20) NOT NULL,
+ ipv4_oam_address VARCHAR(20) NOT NULL,
+ loopback0_ipv4_address VARCHAR(20) NOT NULL,
+ provisioning_status VARCHAR(10) NOT NULL,
+ aic_site_id VARCHAR(100) NOT NULL,
+ availability_zone VARCHAR(100) NOT NULL,
+ vlan_id_outer VARCHAR(20) NOT NULL,
+ vendor VARCHAR(20) NOT NULL,
+ physical_intf_name VARCHAR(40) NOT NULL,
+ physical_intf_speed VARCHAR(20) NOT NULL,
+ physical_intf_units VARCHAR(20) NOT NULL,
+ vpe_uuid VARCHAR(80) DEFAULT NULL,
+ vpe_id VARCHAR(80) DEFAULT NULL,
+ image_filename VARCHAR(100) DEFAULT NULL,
+ PRIMARY KEY (aic_site_id, vpe_name, availability_zone)
+);
+
+CREATE TABLE VPLSPE_POOL (
+ vplspe_name varchar(20) NOT NULL,
+ aic_site_id varchar(100) NOT NULL,
+ availability_zone varchar(100) NOT NULL,
+ physical_intf_name varchar(40) NOT NULL,
+ physical_intf_speed varchar(20) NOT NULL,
+ physical_intf_units varchar(20) NOT NULL,
+ loopback0_ipv4_address varchar(20) NOT NULL,
+ vlan_id_outer varchar(20) NOT NULL,
+ vplspe_uuid varchar(80) DEFAULT NULL,
+ image_filename varchar(100) DEFAULT NULL,
+ provisioning_status varchar(10) DEFAULT NULL,
+ vendor varchar(20) DEFAULT NULL,
+ PRIMARY KEY (vplspe_name, aic_site_id, availability_zone, physical_intf_name)
+);
+
+CREATE TABLE VPE_LOCK (
+ vpe_name varchar(20) NOT NULL,
+ vpn_lock varchar(20) NOT NULL,
+ PRIMARY KEY (vpe_name)
+);
+
+CREATE TABLE PARAMETERS (
+ name varchar(100) PRIMARY KEY,
+ value varchar(24) NOT NULL,
+ category varchar(24) NOT NULL,
+ memo varchar(128)
+);
+
+CREATE TABLE PSERVER (
+ hostname varchar(255) NOT NULL,
+ ptnii_equip_name varchar(255),
+ number_of_cpus varchar(255),
+ disk_in_gigabytes varchar(255),
+ ram_in_megabytes varchar(255),
+ equip_type varchar(255),
+ equip_vendor varchar(255),
+ equip_model varchar(255),
+ fqdn varchar(255),
+ pserver_selflink varchar(255),
+ ipv4_oam_address varchar(15),
+ serial_number varchar(255),
+ pserver_id varchar(255),
+ internet_topology varchar(40),
+ aic_site_id varchar(100),
+ in_maint varchar(5),
+ pserver_name2 varchar(255),
+ purpose varchar(255),
+ PRIMARY KEY (hostname)
+);
diff --git a/adaptors/resource-assignment/provider/src/test/resources/test-context.xml b/adaptors/resource-assignment/provider/src/test/resources/test-context.xml
new file mode 100644
index 000000000..ecebec723
--- /dev/null
+++ b/adaptors/resource-assignment/provider/src/test/resources/test-context.xml
@@ -0,0 +1,153 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ============LICENSE_START=======================================================
+ openECOMP : SDN-C
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property. All rights
+ reserved.
+ ================================================================================
+ 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.
+ ============LICENSE_END=========================================================
+ -->
+
+<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:jdbc="http://www.springframework.org/schema/jdbc"
+ xmlns:context="http://www.springframework.org/schema/context"
+ xsi:schemaLocation="http://www.springframework.org/schema/beans
+ http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
+ http://www.springframework.org/schema/jdbc
+ http://www.springframework.org/schema/jdbc/spring-jdbc-3.1.xsd
+ http://www.springframework.org/schema/context
+ http://www.springframework.org/schema/context/spring-context-3.1.xsd
+ ">
+
+ <context:annotation-config />
+
+ <!-- JDBC setup -->
+
+ <bean id="test.dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"
+ lazy-init="false" primary="true">
+ <property name="driverClassName" value="org.h2.Driver" />
+ <property name="url" value="jdbc:h2:mem:test;DB_CLOSE_DELAY=-1;MODE=MySQL" />
+ </bean>
+
+ <jdbc:initialize-database data-source="test.dataSource">
+ <jdbc:script location="sql/schema.sql" />
+ <jdbc:script location="sql/data.sql" />
+ </jdbc:initialize-database>
+
+ <bean id="lock.dataSource" class="org.onap.ccsdk.sli.adaptors.util.db.CachedDataSourceWrap">
+ <property name="dataSource" ref="test.dataSource" />
+ </bean>
+
+ <bean id="rm.jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate" primary="true">
+ <property name="dataSource" ref="test.dataSource" />
+ </bean>
+
+ <bean id="lock.jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
+ <property name="dataSource" ref="lock.dataSource" />
+ </bean>
+
+ <bean id="testDb" class="jtest.util.org.onap.ccsdk.sli.adaptors.ra.TestDb">
+ <property name="jdbcTemplate" ref="rm.jdbcTemplate" />
+ </bean>
+
+ <bean id="dataSetup" class="jtest.org.onap.ccsdk.sli.adaptors.ra.DataSetup">
+ <property name="testDb" ref="testDb" />
+ </bean>
+
+ <!-- Resource Lock Configuration -->
+
+ <bean id="resourceLockDao" class="org.onap.ccsdk.sli.adaptors.lock.dao.ResourceLockDaoImpl">
+ <property name="jdbcTemplate" ref="lock.jdbcTemplate" />
+ </bean>
+
+ <bean id="lockHelper" class="org.onap.ccsdk.sli.adaptors.lock.comp.LockHelperImpl">
+ <property name="resourceLockDao" ref="resourceLockDao" />
+ <property name="retryCount" value="10" />
+ <property name="lockWait" value="5" /> <!-- Seconds -->
+ </bean>
+
+ <!-- RM Configuration -->
+
+ <bean id="resourceJdbcDao" class="org.onap.ccsdk.sli.adaptors.rm.dao.jdbc.ResourceJdbcDaoImpl">
+ <property name="jdbcTemplate" ref="rm.jdbcTemplate" />
+ </bean>
+
+ <bean id="allocationItemJdbcDao" class="org.onap.ccsdk.sli.adaptors.rm.dao.jdbc.AllocationItemJdbcDaoImpl">
+ <property name="jdbcTemplate" ref="rm.jdbcTemplate" />
+ </bean>
+
+ <bean id="resourceLoadJdbcDao" class="org.onap.ccsdk.sli.adaptors.rm.dao.jdbc.ResourceLoadJdbcDaoImpl">
+ <property name="jdbcTemplate" ref="rm.jdbcTemplate" />
+ </bean>
+
+ <bean id="resourceDao" class="org.onap.ccsdk.sli.adaptors.rm.dao.jdbc.ResourceDaoImpl">
+ <property name="resourceJdbcDao" ref="resourceJdbcDao" />
+ <property name="allocationItemJdbcDao" ref="allocationItemJdbcDao" />
+ <property name="resourceLoadJdbcDao" ref="resourceLoadJdbcDao" />
+ </bean>
+
+ <bean id="resourceManager" class="org.onap.ccsdk.sli.adaptors.rm.comp.ResourceManagerImpl">
+ <property name="lockHelper" ref="lockHelper" />
+ <property name="resourceDao" ref="resourceDao" />
+ <property name="lockTimeout" value="600" /> <!-- Seconds -->
+ </bean>
+
+ <!-- Rule DAO Configuration -->
+
+ <bean id="resourceRuleDao" class="org.onap.ccsdk.sli.adaptors.ra.rule.dao.ResourceRuleDaoImpl">
+ <property name="jdbcTemplate" ref="rm.jdbcTemplate" />
+ </bean>
+
+ <bean id="rangeRuleDao" class="org.onap.ccsdk.sli.adaptors.ra.rule.dao.RangeRuleDaoImpl">
+ <property name="jdbcTemplate" ref="rm.jdbcTemplate" />
+ </bean>
+
+ <!-- ResourceAllocator Configuration -->
+
+ <bean id="resourceAllocator" class="org.onap.ccsdk.sli.adaptors.ra.ResourceAllocator">
+ <property name="resourceManager" ref="resourceManager" />
+ <property name="endPointAllocator" ref="endPointAllocator" />
+ <property name="speedUtil" ref="speedUtil" />
+ </bean>
+
+ <bean id="resourceLockNode" class="org.onap.ccsdk.sli.adaptors.ra.ResourceLockNode">
+ <property name="lockHelper" ref="lockHelper" />
+ </bean>
+
+ <bean id="speedUtil" class="org.onap.ccsdk.sli.adaptors.util.speed.SpeedUtil" />
+
+ <!-- EndPointAllocator Configuration -->
+
+ <bean id="endPointAllocator" class="org.onap.ccsdk.sli.adaptors.ra.comp.EndPointAllocatorImpl">
+ <property name="resourceManager" ref="resourceManager" />
+ <property name="allocationRuleMap">
+ <map>
+ <entry key="DEFAULT">
+ <list>
+ <ref bean="dbAllocationRule" />
+ </list>
+ </entry>
+ </map>
+ </property>
+ </bean>
+
+ <!-- Resource Allocation Rule Configuration -->
+
+ <bean id="dbAllocationRule" class="org.onap.ccsdk.sli.adaptors.ra.alloc.DbAllocationRule">
+ <property name="resourceRuleDao" ref="resourceRuleDao" />
+ <property name="rangeRuleDao" ref="rangeRuleDao" />
+ </bean>
+
+</beans>
diff --git a/adaptors/saltstack-adapter/.pydevproject b/adaptors/saltstack-adapter/.pydevproject
new file mode 100644
index 000000000..d001f0aea
--- /dev/null
+++ b/adaptors/saltstack-adapter/.pydevproject
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<?eclipse-pydev version="1.0"?><pydev_project>
+<pydev_property name="org.python.pydev.PYTHON_PROJECT_INTERPRETER">Default</pydev_property>
+<pydev_property name="org.python.pydev.PYTHON_PROJECT_VERSION">python interpreter</pydev_property>
+</pydev_project>
diff --git a/adaptors/saltstack-adapter/README.md b/adaptors/saltstack-adapter/README.md
new file mode 100644
index 000000000..9c00457b3
--- /dev/null
+++ b/adaptors/saltstack-adapter/README.md
@@ -0,0 +1,137 @@
+This source repository contains the code for the CCSDK plugins.
+
+To compile this code:
+
+1. Make sure your local Maven settings file ($HOME/.m2/settings.xml) contains references to the ONAP repositories and OpenDaylight repositories. See example-settings.xml for an example.
+
+2. To compile, run "mvn clean install".
+
+
+***SaltStack Adaptor:*** CCSDK SLI ADAPTORS to support SaltStack server:
+
+***Connection from CCSDK SLI ADAPTOR Adaptor to SaltStack server:***
+
+Create an Adaptor to communicate with the SaltStack server:
+1) SaltStack server doesn’t expose any REST API unlike Chef.
+2) SSH based communication with the SaltStack server, one command at a time (preferred). This will mean that SaltStack server should have it’s SSH enabled.
+3) Create a REST-wrap around SaltStack server like is done for Ansible server.
+
+***SSH based communication:***
+1) Adaptor can execute commands on the Salt Master and bring back the result and put to the context memory for DG based analysis. (https://docs.saltstack.com/en/latest/ref/modules/all/index.html#all-salt-modules).
+2) This can be useful for several reasons, for instance it might be useful to know the interfaces in the minions before executing certain network config based commands. This can simple be done by running, 'salt '*' network.interfaces' on server.
+3) SaltStack Server, Output module support: The json-out outputter can be used to display the return data in JSON format. So the DG can put this onto context memory for execution. https://docs.saltstack.com/en/latest/ref/output/all/index.html#all-salt-output
+4) Since the command execution on server might take time, a thread can be spawn to make a single SSH command execution in a SYNC manner. The thread executes the command and brings back the result and puts to the context memory for DG’s access.
+5) For some specific executions operations like configure and upgrade, each configuration execution on the server will be handled by 2 or more SSH command execution. (1 for sending configuration and another for verifying the result). This will give the DGs and Saltstack adaptor with more control on the SaltStack server.
+
+***SaltState (SLS) file for execution on the SaltStack server:***
+ The desired SLS file can be executed by one of the following three ways:
+1) The SLS file for VNF configuration can be assumed to be already on the server, similar to Ansible. In this case, no addition requirements are necessary. We would already know the name of SLS file to execute so the configuration is performed on the VNF.
+2) SLS file creation using DG: Create a DG to parse the configuration and create an SLS file using adaptors such as FileRecorder. Then this SLS file can be passed to the adaptor, so the adaptor can send the configuration to server. The adaptor can also send a SLS file to the Saltstack server and then run the command to execute it.
+3) Third option is for the configuration SLS file that is to be sent to the VNF after instantiation is attached at the design time. This SLS formula- SaltStack file can be picked up and stored in the DB, as part of UEB listener. This can then be sent to adaptor using DGs.
+
+***Requirements and benefits of the chosen SSH method:***
+1) The SaltStack server should have it’s SSH enabled.
+2) Via ssh user account we should have the access to run saltstack command.
+3) Such execution method will give the DGs and adaptor with more refined control on the SaltStack server.
+==================================================================================================================
+
+
+***Defining Saltstack server properties:*** Can be done with 2 different methods.
+1) Saltstack server details are found in the property file named saltstack-adapter.properties. Param has to be given with following types.
+ "org.onap.appc.adapter.saltstack.clientType"; -> Supported types are (BASIC || SSH_CERT || BOTH).
+ "org.onap.appc.adapter.saltstack.host"; -> Saltstack server's host name IP address.
+ "org.onap.appc.adapter.saltstack.port"; -> Saltstack server's port to make SSH connection to.
+ "org.onap.appc.adapter.saltstack.userName"; -> Saltstack server's SSH UserName.
+ "org.onap.appc.adapter.saltstack.userPasswd"; -> Saltstack server's SSH Password.
+ "org.onap.appc.adapter.saltstack.sshKey"; -> Saltstack server's SSH KEY file location.
+2) All the server related details can also be passed as param to the adaptor from the Directed Graphs. Param has to be given with following types.
+ "HostName"; -> Saltstack server's host name IP address.
+ "Port"; -> Saltstack server's port to make SSH connection to.
+ "Password"; -> Saltstack server's SSH UserName.
+ "User"; -> Saltstack server's SSH Password.
+ "withRetry"; -> Specify 'true' if you wanna connect to server with retry.
+ Note: SSH_CERT based Auth is not supported in this method.
+
+***Using Saltstack Adaptor Commands and params to pass in: reqExecCommand API:***
+
+Method to execute a single command on SaltState server and execute a SLS file located on the server. The command entered should request the output in JSON format, this can be done by appending json-out outputter as specified in https://docs.saltstack.com/en/latest/ref/output/all/salt.output.json_out.html#module-salt.output.json_out and https://docs.saltstack.com/en/2017.7/ref/cli/salt-call.html
+The response from Saltstack comes in json format and it is automatically put to context for DGs access, with a certain request-ID as prefix.
+If Id is not passed as part of input param, then a random Id will be generated and put to properties in "org.onap.appc.adapter.saltstack.Id" field. All the output message from the execution will be appended with reqId.
+1) Execute a single command on SaltState server : Example command will look like:
+1.1) Command to test if all VNFC are running: "salt '*' test.ping --out=json --static"
+1.2) To check Network interfaces on your minions: "salt '*' network.interfaces --out=json --static"
+1.3) Restart Minion service after upgrade process: "salt minion1 service.restart salt-minion --out=json --static"
+Note: If using --out=json, you will probably want --static as well. Without the static option, you will get a separate JSON string per minion which makes JSON output invalid as a whole. This is due to using an iterative outputter. So if you want to feed it to a JSON parser, use --static as well.
+
+This "reqExecCommand" method gives the Operator/Directed Graphs to execute commands in a fine-tuned manner, which also means the operator/DG-creator should know what to expect as output as a result of command execution (for both success/failure case).
+By this way using DGs, the operator can check for success/failure of the executed comment.
+If the output is not in JSON format, then the adaptor still tries to convert it into properties, in addition, params that will hold the command execution result for DG access are (note: this is just to check if the command was executed successfully on the server, this doesn't check the status of the command on saltstack server):
+Result code at: org.onap.appc.adapter.saltstack.result.code (On success: This will be always be 250, means command execution was success but the result of the execution is unknown and is to be checked from ctx using DGs)
+Message at: org.onap.appc.adapter.saltstack.message
+Both user inputted/auto generated req Id at: org.onap.appc.adapter.saltstack.Id
+To check the status of the command configuration on saltstack server: the user should exactly know what to look for in the context
+so the user can identify if the configuration execution on the saltstack server succeded or not.
+here for instance, in 1.1) the user should check if $reqId.<minion-name> is set to true in the context memory using DGs.
+
+2) Execute a SLS file located on the server : Example command will look like:
+Knowing the saltstack server has vim.sls file located at "/srv/salt" directory then user can execute the following commands:
+1.1) Command to run the vim.sls file on saltstack server: Cmd = "salt '*' state.apply vim --out=json --static"
+1.2) Command to run the nettools.sls file on saltstack server: Cmd = "cd /srv/salt/; salt '*' state.apply <sls-file-name> --out=json --static"
+Important thing to note: If the reqExecCommand is used to execute sls file then along with following,
+ "HostName"; -> Saltstack server's host name IP address.
+ "Port"; -> Saltstack server's port to make SSH connection to.
+ "Password"; -> Saltstack server's SSH UserName.
+ "User"; -> Saltstack server's SSH Password.
+the param should contain,
+ "SlsExec"; -> this variable should be set to true.
+ "Timeout"; -> set large timeout if your SLS file will take large time to finish executing (in Seconds).
+
+In this case, params that will hold the command execution result for DG access in Key:
+Result code at: org.onap.appc.adapter.saltstack.result.code (On success: This will be 200, this means the command was executed successfully and also configuration change made using the SLS file was also successful)
+Message at: org.onap.appc.adapter.saltstack.message
+Both user inputted/auto generated req Id at: org.onap.appc.adapter.saltstack.Id
+The result code here will be the execution of configuration SLS file on the server.
+NOTE: It would be better to use reqExecSLS, where you will only have to specify SLS file name on server to execute it.
+
+
+***Using Saltstack Adaptor Commands and params to pass in: reqExecSLS API:***
+
+Method to execute a single sls on SaltState server (Where the SLS file already located on the server). The command entered will only be the SLS file name and the output will be in JSON format automatically.
+The response from Saltstack comes in json format and it is automatically put to context for DGs access, with a certain request-ID as prefix.
+If request Id (Id) is not passed as part of input param, then a random Id will be generated and put to properties in "org.onap.appc.adapter.saltstack.Id" field. All the output message from the execution will be appended with reqId.
+1) Execute a single command on SaltState server : Example command will look like:
+ In the context set the "SlsName" to "test.sls"
+ In the context set the "Timeout"; -> set large timeout if your SLS file will take large time to finish executing (in Seconds).
+ In the context set the "NodeList" to "minion1" //to the minions or VNFCs you want to apply the SLS file to.
+ "NodeList" can be empty or set to "*" is the SLS has to be applied to all the minions or VNFCs.
+ In the context set the "FileParameters: A JSON dictionary where keys are filenames and values are contents of files. The Saltstack Server will utilize this feature to generate files with keys as filenames and values as content. This attribute can be used to generate files that a SSL file may require as part of execution (Optional).
+ In the context set the "EnvParameters: A JSON dictionary which should list key value pairs to be passed to the Salstack command to run SLS. These values would correspond to instance specific parameters that a playbook may need to execute an action.
+
+In this case, params that will hold the command execution result for DG access in Key:
+Result code at: org.onap.appc.adapter.saltstack.result.code (On success: This will be 200, this means the command was executed successfully and also configuration change made using the SLS file was also successful)
+Message at: org.onap.appc.adapter.saltstack.message
+Both user inputted/auto generated req Id at: org.onap.appc.adapter.saltstack.Id
+The result code here will be the execution of configuration SLS file on the server.
+
+***Using Saltstack Adaptor Commands and params to pass in: reqExecSLSFile API:***
+
+Method to execute a single sls on SaltState server (Where the SLS file in the adaptor). The command entered will only be the SLS file location on the APPC/ODL container and the output from server will be in JSON format automatically.
+The response from Saltstack comes in json format and it is automatically put to context for DGs access, with a certain request-ID as prefix.
+If request Id (Id) is not passed as part of input param, then a random Id will be generated and put to properties in "org.onap.appc.adapter.saltstack.Id" field. All the output message from the execution will be appended with reqId.
+1) Execute a single command on SaltState server : Example command will look like:
+ In the context set the "SlsFile" to "/path/to/test.sls" //mention the path of the SLS file in ODL container.
+ In the context set the "Timeout"; -> set large timeout if your SLS file will take large time to finish executing (in Seconds).
+ In the context set the "NodeList" to "minion1" //to the minions or VNFCs you want to apply the SLS file to.
+ "NodeList" can be empty or set to 'minion*' (pattern matching) or set to "*" is the SLS has to be applied to all the minions or VNFCs.
+ In the context set the "FileParameters: A JSON dictionary where keys are filenames and values are contents of files. The Saltstack Server will utilize this feature to generate files with keys as filenames and values as content. This attribute can be used to generate files that a SSL file may require as part of execution (Optional).
+ In the context set the "EnvParameters: A JSON dictionary which should list key value pairs to be passed to the Salstack command to run SLS. These values would correspond to instance specific parameters that a playbook may need to execute an action.
+
+In this case, params that will hold the command execution result for DG access in Key:
+Result code at: org.onap.appc.adapter.saltstack.result.code (On success: This will be 200, this means the command was executed successfully and also configuration change made using the SLS file was also successful)
+Message at: org.onap.appc.adapter.saltstack.message
+Both user inputted/auto generated req Id at: org.onap.appc.adapter.saltstack.Id
+The result code here will be the execution of configuration SLS file on the server.
+
+Control the state system on the minion: by specifying Env Params (pillars) and Files.
+
+https://docs.saltstack.com/en/latest/ref/modules/all/salt.modules.state.html \ No newline at end of file
diff --git a/adaptors/saltstack-adapter/pom.xml b/adaptors/saltstack-adapter/pom.xml
new file mode 100644
index 000000000..de8a87b05
--- /dev/null
+++ b/adaptors/saltstack-adapter/pom.xml
@@ -0,0 +1,199 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ============LICENSE_START=======================================================
+ ONAP : CCSDK
+ ================================================================================
+ Copyright (C) 2018 Samsung Electronics. All rights reserved.
+ ================================================================================
+
+ =============================================================================
+ 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.
+
+
+ ============LICENSE_END=========================================================
+ -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>odlparent-lite</artifactId>
+ <version>2.1.0</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.adaptors</groupId>
+ <artifactId>saltstack-adaptor</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>pom</packaging>
+
+ <name>ccsdk-sli-adaptors :: saltstack-adapter</name>
+ <description>Abstractions to interact with Saltstack server via REST
+ </description>
+
+ <modules>
+ <module>saltstack-adapter-provider</module>
+ <module>saltstack-adapter-installer</module>
+ </modules>
+
+ <dependencyManagement>
+ <dependencies>
+
+ <dependency>
+ <groupId>org.onap.appc</groupId>
+ <artifactId>saltstack-adapter-features</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ </dependency>
+
+ <dependency>
+ <groupId>org.onap.appc</groupId>
+ <artifactId>saltstack-adapter-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.11</version>
+ <scope>test</scope>
+ </dependency>
+
+
+ </dependencies>
+
+
+ </dependencyManagement>
+
+ <pluginRepositories>
+ <!-- Black Duck plugin dependencies -->
+ <pluginRepository>
+ <id>JCenter</id>
+ <name>JCenter Repository</name>
+ <url>http://jcenter.bintray.com</url>
+ </pluginRepository>
+
+ </pluginRepositories>
+
+ <build>
+ <plugins>
+
+ <!-- Black duck plugin Not required for regular builds
+ <plugin> <groupId>com.blackducksoftware.integration</groupId> <artifactId>hub-maven-plugin</artifactId>
+ <version>1.4.0</version> <inherited>false</inherited> <configuration> <hubProjectName>${project.name}</hubProjectName>
+ <outputDirectory>${project.basedir}</outputDirectory> <deployHubBdio>false</deployHubBdio>
+ </configuration> <extensions>true</extensions>
+ <executions>
+ <execution>
+ <id>create-bdio-file</id>
+ <phase>package</phase>
+ <goals>
+ <goal>createHubOutput</goal>
+ </goals>
+ </execution>
+ </executions>
+
+ </plugin>
+ -->
+
+ </plugins>
+ </build>
+
+ <reporting>
+ <plugins>
+ <plugin>
+ <artifactId>maven-javadoc-plugin</artifactId>
+ <configuration>
+ <additionalDependencies>
+ <additionalDependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ <version>${slf4j.version}</version>
+ </additionalDependency>
+ <additionalDependency>
+ <groupId>org.antlr</groupId>
+ <artifactId>antlr4</artifactId>
+ <version>${antlr.version}</version>
+ </additionalDependency>
+ <additionalDependency>
+ <groupId>org.antlr</groupId>
+ <artifactId>antlr4-runtime</artifactId>
+ <version>4.3</version>
+ </additionalDependency>
+ </additionalDependencies>
+ </configuration>
+ <reportSets>
+ <reportSet>
+ <reports>
+ <report>javadoc-no-fork</report>
+ <report>test-javadoc-no-fork</report>
+ </reports>
+ </reportSet>
+ <reportSet>
+ <id>aggregate</id>
+ <reports>
+ <report>aggregate</report>
+ <report>test-aggregate</report>
+ </reports>
+ </reportSet>
+ </reportSets>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jxr-plugin</artifactId>
+ <version>2.3</version>
+ <reportSets>
+ <reportSet>
+ <id>aggregate</id>
+ <reports>
+ <report>aggregate</report>
+ <report>test-aggregate</report>
+ </reports>
+ </reportSet>
+ </reportSets>
+ </plugin>
+
+ <plugin>
+ <artifactId>maven-surefire-plugin</artifactId>
+ </plugin>
+
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-changelog-plugin</artifactId>
+ <version>2.3</version>
+ <reportSets>
+ <reportSet>
+ <id>dual-report</id>
+ <configuration>
+ <type>range</type>
+ <range>30</range>
+ </configuration>
+ <reports>
+ <report>changelog</report>
+ <report>file-activity</report>
+ </reports>
+ </reportSet>
+ </reportSets>
+ </plugin>
+
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>taglist-maven-plugin</artifactId>
+ <version>2.4</version>
+ </plugin>
+ </plugins>
+
+ </reporting>
+</project>
diff --git a/adaptors/saltstack-adapter/saltstack-adapter-installer/pom.xml b/adaptors/saltstack-adapter/saltstack-adapter-installer/pom.xml
new file mode 100644
index 000000000..67e30fa02
--- /dev/null
+++ b/adaptors/saltstack-adapter/saltstack-adapter-installer/pom.xml
@@ -0,0 +1,165 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ============LICENSE_START=======================================================
+ ONAP : CCSDK
+ ================================================================================
+ Copyright (C) 2018 Samsung Electronics. All rights reserved.
+ ================================================================================
+
+ =============================================================================
+ 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.
+
+
+ ============LICENSE_END=========================================================
+ -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>odlparent-lite</artifactId>
+ <version>2.1.0</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.adaptors</groupId>
+ <artifactId>saltstack-adapter-installer</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>pom</packaging>
+
+ <name>ccsdk-sli-adaptors :: saltstack-adapter :: ${project.artifactId}
+ </name>
+
+ <properties>
+ <application.name>ccsdk-saltstack-adapter</application.name>
+ <features.boot>${application.name}</features.boot>
+ <features.repositories>
+ mvn:org.onap.ccsdk.sli.adaptors/${features.boot}/${project.version}/xml/features
+ </features.repositories>
+ <include.transitive.dependencies>false</include.transitive.dependencies>
+ </properties>
+
+ <dependencies>
+
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.adaptors</groupId>
+ <artifactId>saltstack-adapter-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>maven-repo-zip</id>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ <phase>package</phase>
+ <configuration>
+ <appendAssemblyId>true</appendAssemblyId>
+ <attach>true</attach>
+ <finalName>
+ stage/${application.name}-${project.version}
+ </finalName>
+ <descriptors>
+ <descriptor>
+ src/assembly/assemble_mvnrepo_zip.xml
+ </descriptor>
+ </descriptors>
+ <appendAssemblyId>true</appendAssemblyId>
+ </configuration>
+ </execution>
+ <execution>
+ <id>installer-zip</id>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ <phase>package</phase>
+ <configuration>
+ <appendAssemblyId>false</appendAssemblyId>
+ <attach>true</attach>
+ <finalName>${application.name}-${project.version}
+ </finalName>
+ <descriptors>
+ <descriptor>
+ src/assembly/assemble_installer_zip.xml
+ </descriptor>
+ </descriptors>
+ <appendAssemblyId>false</appendAssemblyId>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>copy-dependencies</id>
+ <goals>
+ <goal>copy-dependencies</goal>
+ </goals>
+ <phase>prepare-package</phase>
+ <configuration>
+ <transitive>false</transitive>
+ <outputDirectory>
+ ${project.build.directory}/assembly/system
+ </outputDirectory>
+ <overWriteReleases>false</overWriteReleases>
+ <overWriteSnapshots>true</overWriteSnapshots>
+ <overWriteIfNewer>true</overWriteIfNewer>
+ <useRepositoryLayout>true</useRepositoryLayout>
+ <addParentPoms>false</addParentPoms>
+ <copyPom>false</copyPom>
+ <includeGroupIds>org.onap.ccsdk.sli.adaptors</includeGroupIds>
+ <scope>provided</scope>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <artifactId>maven-resources-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>copy-version</id>
+ <goals>
+ <goal>copy-resources</goal>
+ </goals>
+ <!-- here the phase you need -->
+ <phase>validate</phase>
+ <configuration>
+ <outputDirectory>${basedir}/target/stage
+ </outputDirectory>
+ <resources>
+ <resource>
+ <directory>src/main/resources/scripts
+ </directory>
+ <includes>
+ <include>install-feature.sh</include>
+ </includes>
+ <filtering>true</filtering>
+ </resource>
+ </resources>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/adaptors/saltstack-adapter/saltstack-adapter-installer/src/assembly/assemble_installer_zip.xml b/adaptors/saltstack-adapter/saltstack-adapter-installer/src/assembly/assemble_installer_zip.xml
new file mode 100644
index 000000000..d307e4f30
--- /dev/null
+++ b/adaptors/saltstack-adapter/saltstack-adapter-installer/src/assembly/assemble_installer_zip.xml
@@ -0,0 +1,61 @@
+<!--
+ ============LICENSE_START=======================================================
+ ONAP : CCSDK
+ ================================================================================
+ Copyright (C) 2018 Samsung Electronics. All rights reserved.
+ ================================================================================
+
+ =============================================================================
+ 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.
+
+
+ ============LICENSE_END=========================================================
+ -->
+
+<!-- Defines how we build the .zip file which is our distribution. -->
+
+<assembly
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
+ xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
+ <id>adapter</id>
+ <formats>
+ <format>zip</format>
+ </formats>
+
+ <!-- we want "system" and related files right at the root level
+ as this file is suppose to be unzip on top of a karaf
+ distro. -->
+ <includeBaseDirectory>false</includeBaseDirectory>
+
+ <fileSets>
+ <fileSet>
+ <directory>target/stage/</directory>
+ <outputDirectory>${application.name}</outputDirectory>
+ <fileMode>755</fileMode>
+ <includes>
+ <include>*.sh</include>
+ </includes>
+ </fileSet>
+ <fileSet>
+ <directory>target/stage/</directory>
+ <outputDirectory>${application.name}</outputDirectory>
+ <fileMode>644</fileMode>
+ <excludes>
+ <exclude>*.sh</exclude>
+ </excludes>
+ </fileSet>
+ </fileSets>
+
+
+</assembly>
diff --git a/adaptors/saltstack-adapter/saltstack-adapter-installer/src/assembly/assemble_mvnrepo_zip.xml b/adaptors/saltstack-adapter/saltstack-adapter-installer/src/assembly/assemble_mvnrepo_zip.xml
new file mode 100644
index 000000000..1b1bf0b6b
--- /dev/null
+++ b/adaptors/saltstack-adapter/saltstack-adapter-installer/src/assembly/assemble_mvnrepo_zip.xml
@@ -0,0 +1,50 @@
+<!--
+ ============LICENSE_START=======================================================
+ ONAP : CCSDK
+ ================================================================================
+ Copyright (C) 2018 Samsung Electronics. All rights reserved.
+ ================================================================================
+
+ =============================================================================
+ 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.
+
+
+ ============LICENSE_END=========================================================
+ -->
+
+<!-- Defines how we build the .zip file which is our distribution. -->
+
+<assembly
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
+ xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
+ <id>repo</id>
+ <formats>
+ <format>zip</format>
+ </formats>
+
+ <!-- we want "system" and related files right at the root level
+ as this file is suppose to be unzip on top of a karaf
+ distro. -->
+ <includeBaseDirectory>false</includeBaseDirectory>
+
+ <fileSets>
+ <fileSet>
+ <directory>target/assembly/</directory>
+ <outputDirectory>.</outputDirectory>
+ <excludes>
+ </excludes>
+ </fileSet>
+ </fileSets>
+
+</assembly>
diff --git a/adaptors/saltstack-adapter/saltstack-adapter-installer/src/main/resources/scripts/install-feature.sh b/adaptors/saltstack-adapter/saltstack-adapter-installer/src/main/resources/scripts/install-feature.sh
new file mode 100644
index 000000000..38782cabb
--- /dev/null
+++ b/adaptors/saltstack-adapter/saltstack-adapter-installer/src/main/resources/scripts/install-feature.sh
@@ -0,0 +1,42 @@
+###
+# ============LICENSE_START=======================================================
+# ONAP : APPC
+# ================================================================================
+# Copyright (C) 2018 Samsung Electronics. All rights reserved.
+# ================================================================================
+#
+# =============================================================================
+# 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.
+#
+#
+# ============LICENSE_END=========================================================
+###
+
+#!/bin/bash
+
+ODL_HOME=${ODL_HOME:-/opt/opendaylight/current}
+ODL_KARAF_CLIENT=${ODL_KARAF_CLIENT:-${ODL_HOME}/bin/client}
+INSTALLERDIR=$(dirname $0)
+
+REPOZIP=${INSTALLERDIR}/${features.boot}-${project.version}.zip
+
+if [ -f ${REPOZIP} ]
+then
+ unzip -n -d ${ODL_HOME} ${REPOZIP}
+else
+ echo "ERROR : repo zip ($REPOZIP) not found"
+ exit 1
+fi
+
+${ODL_KARAF_CLIENT} feature:repo-add ${features.repositories}
+${ODL_KARAF_CLIENT} feature:install ${features.boot}
diff --git a/adaptors/saltstack-adapter/saltstack-adapter-provider/.gitignore b/adaptors/saltstack-adapter/saltstack-adapter-provider/.gitignore
new file mode 100644
index 000000000..4e1ad823a
--- /dev/null
+++ b/adaptors/saltstack-adapter/saltstack-adapter-provider/.gitignore
@@ -0,0 +1,25 @@
+# ============LICENSE_START==========================================
+# ONAP : CCSDK
+# ===================================================================
+# Copyright (C) 2017-2018 Samsung Electronics. All rights reserved.
+# ===================================================================
+#
+# Unless otherwise specified, all software contained herein is licensed
+# under the Apache License, Version 2.0 (the License);
+# you may not use this software 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.
+#
+#
+# ============LICENSE_END============================================
+/bin/
+/target/
+/target-ide/
+/.settings/
diff --git a/adaptors/saltstack-adapter/saltstack-adapter-provider/pom.xml b/adaptors/saltstack-adapter/saltstack-adapter-provider/pom.xml
new file mode 100644
index 000000000..4b6868179
--- /dev/null
+++ b/adaptors/saltstack-adapter/saltstack-adapter-provider/pom.xml
@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- ============LICENSE_START=======================================================
+ ONAP : CCSDK ================================================================================
+ Copyright (C) 2017-2018 Samsung Electronics. All rights reserved.
+ ================================================================================
+ =============================================================================
+ 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. ============LICENSE_END========================================================= -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>binding-parent</artifactId>
+ <version>2.1.0</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.adaptors</groupId>
+ <artifactId>saltstack-adapter-provider</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>bundle</packaging>
+
+ <name>ccsdk-sli-adaptors :: saltstack-adapter :: ${project.artifactId}
+ </name>
+
+ <properties>
+ <ccsdk.sli.adaptors.version>${project.version}</ccsdk.sli.adaptors.version>
+ </properties>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sli-core-artifacts</artifactId>
+ <version>${ccsdk.sli.core.version}</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>com.att.eelf</groupId>
+ <artifactId>eelf-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>commons-codec</groupId>
+ <artifactId>commons-codec</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>commons-logging</groupId>
+ <artifactId>commons-logging</artifactId>
+ <version>1.2</version>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.core</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>jcl-over-slf4j</artifactId>
+ </dependency>
+
+ <!-- Needed to run SSH -->
+ <!-- VERSION CONFLICT !!!!! -->
+ <!-- OpenDaylight Fluorine comes with version 1.7.0 installed, which is not compatible -->
+ <!-- Code must be updated to use version 1.7.0 before this can be safely installed -->
+ <dependency>
+ <groupId>org.apache.sshd</groupId>
+ <artifactId>sshd-core</artifactId>
+ <version>1.7.0</version>
+ </dependency>
+
+ <!-- Needed to run test cases -->
+
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-io</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.codehaus.jettison</groupId>
+ <artifactId>jettison</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sli-common</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sli-provider</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.json</groupId>
+ <artifactId>json</artifactId>
+ </dependency>
+
+ </dependencies>
+</project>
diff --git a/adaptors/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/SaltstackAdapter.java b/adaptors/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/SaltstackAdapter.java
new file mode 100644
index 000000000..346910a39
--- /dev/null
+++ b/adaptors/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/SaltstackAdapter.java
@@ -0,0 +1,59 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Samsung Electronics. All rights reserved.
+ * ================================================================================
+ *
+ * =============================================================================
+ * 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.
+ *
+ *
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.saltstack;
+
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.core.sli.SvcLogicJavaPlugin;
+
+import java.util.Map;
+
+/**
+ * This interface defines the operations that the Saltstack adapter exposes.
+ */
+public interface SaltstackAdapter extends SvcLogicJavaPlugin {
+ /**
+ * Returns the symbolic name of the adapter
+ *
+ * @return The adapter name
+ */
+ String getAdapterName();
+
+ /* Method to post a single command request for execution on SaltState server
+ * The response from Saltstack comes in json format and it is automatically put
+ * to context for DGs access, with a certain prefix*/
+ void reqExecCommand(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException;
+
+ /* Method for execution of saltstack SLS command on SaltState server
+ * The response from Saltstack comes in json format and it is automatically put
+ * to context for DGs access, with a certain prefix*/
+ void reqExecSLS(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException;
+
+ /* When SLS file is created/available then this Method can be used to post
+ * the file to saltstack server and execute the SLS file on SaltState server
+ * The response from Saltstack comes in json format and it is automatically put
+ * to context for DGs access, with a certain prefix*/
+ void reqExecSLSFile(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException;
+}
diff --git a/adaptors/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/SaltstackAdapterPropertiesProvider.java b/adaptors/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/SaltstackAdapterPropertiesProvider.java
new file mode 100755
index 000000000..a6b707afc
--- /dev/null
+++ b/adaptors/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/SaltstackAdapterPropertiesProvider.java
@@ -0,0 +1,32 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Samsung Electronics. All rights reserved.
+ * ================================================================================
+ *
+ * =============================================================================
+ * 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.
+ *
+ *
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.saltstack;
+
+import java.util.Properties;
+
+public interface SaltstackAdapterPropertiesProvider {
+
+ public Properties getProperties();
+}
diff --git a/adaptors/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/impl/ConnectionBuilder.java b/adaptors/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/impl/ConnectionBuilder.java
new file mode 100644
index 000000000..48469fdd5
--- /dev/null
+++ b/adaptors/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/impl/ConnectionBuilder.java
@@ -0,0 +1,172 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Samsung Electronics. All rights reserved.
+ * ================================================================================
+ *
+ * =============================================================================
+ * 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.
+ *
+ *
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.saltstack.impl;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import org.onap.ccsdk.sli.adaptors.saltstack.model.SshException;
+import org.onap.ccsdk.sli.adaptors.saltstack.model.SaltstackResult;
+import org.onap.ccsdk.sli.adaptors.saltstack.model.SaltstackResultCodes;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+/**
+ * Returns a custom SSH client
+ * - based on options
+ * - can create one with ssl using an X509 certificate that does NOT have a known CA
+ * - create one which trusts ALL SSL certificates
+ * - return default sshclient (which only trusts known CAs from default cacerts file for process) this is the default
+ * option
+ **/
+public class ConnectionBuilder {
+
+ private static final EELFLogger logger = EELFManager.getInstance().getLogger(ConnectionBuilder.class);
+ SshConnection sshConnection;
+
+ /**
+ * Constructor that initializes an ssh client based on username and password
+ **/
+ public ConnectionBuilder(String host, String port, String userName, String userPasswd) {
+ sshConnection = new SshConnection(host, Integer.parseInt(port), userName, userPasswd);
+ }
+
+ /**
+ * Constructor that initializes an ssh client based on ssh certificate
+ * This is still not supported in 1.3.0 version
+ **/
+ public ConnectionBuilder(String host, String port, String certFile) {
+ sshConnection = new SshConnection(host, Integer.parseInt(port), certFile);
+ }
+
+
+ /**
+ * 1. Connect to SSH server.
+ * 2. Exec remote command over SSH. Return command execution status.
+ * Command output is written to out or err stream.
+ *
+ * @param cmd Commands to execute
+ * @return command execution status
+ */
+ public SaltstackResult connectNExecute(String cmd, long execTimeout) throws IOException {
+ return connectNExecute(cmd, false, execTimeout);
+ }
+
+ /**
+ * 1. Connect to SSH server with retry enabled.
+ * 2. Exec remote command over SSH. Return command execution status.
+ * Command output is written to out or err stream.
+ *
+ * @param cmd Commands to execute
+ * @param withRetry make a SSH connection with default retry.
+ * @return command execution status
+ */
+ public SaltstackResult connectNExecute(String cmd, boolean withRetry, long execTimeout)
+ throws IOException {
+
+ SaltstackResult result = new SaltstackResult();
+ ByteArrayOutputStream out = null;
+ ByteArrayOutputStream errs = null;
+ if (execTimeout >= 0) {
+ sshConnection.setExecTimeout(execTimeout);
+ }
+
+ try {
+ if (withRetry) {
+ sshConnection.connectWithRetry();
+ } else {
+ sshConnection.connect();
+ }
+ out = new ByteArrayOutputStream();
+ errs = new ByteArrayOutputStream();
+ int resultCode = sshConnection.execCommand(cmd, out, errs);
+ sshConnection.disconnect();
+ if (resultCode != 0) {
+ return sortExitStatus(resultCode, errs.toString(), cmd);
+ }
+ result.setStatusCode(SaltstackResultCodes.SUCCESS.getValue());
+ result.setStatusMessage("Success");
+ result.setOutputMessage(out);
+ } catch (SshException io) {
+ if (io.toString().equalsIgnoreCase("Authentication failed")) {
+ logger.error(io.toString());
+ result.setStatusCode(SaltstackResultCodes.USER_UNAUTHORIZED.getValue());
+ result.setStatusMessage(io.toString());
+ return result;
+ }
+ logger.error("Caught Exception", io);
+ result.setStatusCode(SaltstackResultCodes.SSH_EXCEPTION.getValue());
+ result.setStatusMessage(io.getMessage());
+ } catch (Exception io) {
+ logger.error("Caught Exception", io);
+ result.setStatusCode(SaltstackResultCodes.SSH_EXCEPTION.getValue());
+ result.setStatusMessage(io.getMessage());
+ } finally {
+ if (out != null) {
+ out.close();
+ }
+ if (errs != null) {
+ errs.close();
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Print Reasonable error messages based on SSH Exit status code
+ * */
+ public SaltstackResult sortExitStatus(int exitStatus, String errMess, String cmd) {
+ SaltstackResult result = new SaltstackResult();
+ if (exitStatus == 255 || exitStatus == 1) {
+ String errMessage = "Error executing command [" + cmd + "] over SSH [" + sshConnection.toString()
+ + "]. Exit Code " + exitStatus + " and Error message : " +
+ "Malformed configuration. " + errMess;
+ logger.error(errMessage);
+ result.setStatusCode(SaltstackResultCodes.INVALID_COMMAND.getValue());
+ result.setStatusMessage(errMessage);
+ } else if (exitStatus == 5 || exitStatus == 65) {
+ String errMessage = "Error executing command [" + cmd + "] over SSH [" + sshConnection.toString()
+ + "]. Exit Code " + exitStatus + " and Error message : " +
+ "Host not allowed to connect. " + errMess;
+ logger.error(errMessage);
+ result.setStatusCode(SaltstackResultCodes.USER_UNAUTHORIZED.getValue());
+ result.setStatusMessage(errMessage);
+ } else if (exitStatus == 67 || exitStatus == 73) {
+ String errMessage = "Error executing command [" + cmd + "] over SSH [" + sshConnection.toString()
+ + "]. Exit Code " + exitStatus + " and Error message : " +
+ "Key exchange failed. " + errMess;
+ logger.error(errMessage);
+ result.setStatusCode(SaltstackResultCodes.CERTIFICATE_ERROR.getValue());
+ result.setStatusMessage(errMessage);
+ } else {
+ String errMessage = "Error executing command [" + cmd + "] over SSH [" + sshConnection.toString()
+ + "]. Exit Code " + exitStatus + " and Error message : " + errMess;
+ logger.error(errMessage);
+ result.setStatusCode(SaltstackResultCodes.UNKNOWN_EXCEPTION.getValue());
+ result.setStatusMessage(errMessage);
+ }
+ return result;
+ }
+}
diff --git a/adaptors/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/impl/SaltstackAdapterImpl.java b/adaptors/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/impl/SaltstackAdapterImpl.java
new file mode 100644
index 000000000..34321ea59
--- /dev/null
+++ b/adaptors/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/impl/SaltstackAdapterImpl.java
@@ -0,0 +1,446 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Samsung Electronics. All rights reserved.
+ * ================================================================================
+ *
+ * =============================================================================
+ * 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.
+ *
+ *
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.saltstack.impl;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.onap.ccsdk.sli.adaptors.saltstack.SaltstackAdapter;
+import org.onap.ccsdk.sli.adaptors.saltstack.SaltstackAdapterPropertiesProvider;
+import org.onap.ccsdk.sli.adaptors.saltstack.model.SaltstackMessageParser;
+import org.onap.ccsdk.sli.adaptors.saltstack.model.SaltstackResult;
+import org.onap.ccsdk.sli.adaptors.saltstack.model.SaltstackResultCodes;
+import org.onap.ccsdk.sli.adaptors.saltstack.model.SaltstackServerEmulator;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Map;
+import java.util.Properties;
+
+/**
+ * This class implements the {@link SaltstackAdapter} interface. This interface defines the behaviors
+ * that our service provides.
+ */
+public class SaltstackAdapterImpl implements SaltstackAdapter {
+
+ /**
+ * The constant for the status code for a failed outcome
+ */
+ @SuppressWarnings("nls")
+ public static final String OUTCOME_FAILURE = "failure";
+ /**
+ * The constant for the status code for a successful outcome
+ */
+ @SuppressWarnings("nls")
+ public static final String OUTCOME_SUCCESS = "success";
+ public static final String CONNECTION_RETRY = "withRetry";
+ private static final String APPC_EXCEPTION_CAUGHT = "APPCException caught";
+ /**
+ * Adapter Name
+ */
+ private static final String ADAPTER_NAME = "Saltstack Adapter";
+ private static final String RESULT_CODE_ATTRIBUTE_NAME = "org.onap.appc.adapter.saltstack.result.code";
+ private static final String MESSAGE_ATTRIBUTE_NAME = "org.onap.appc.adapter.saltstack.message";
+ private static final String ID_ATTRIBUTE_NAME = "org.onap.appc.adapter.saltstack.Id";
+ private static final String CLIENT_TYPE_PROPERTY_NAME = "org.onap.appc.adapter.saltstack.clientType";
+ private static final String SS_SERVER_HOSTNAME = "org.onap.appc.adapter.saltstack.host";
+ private static final String SS_SERVER_PORT = "org.onap.appc.adapter.saltstack.port";
+ private static final String SS_SERVER_USERNAME = "org.onap.appc.adapter.saltstack.userName";
+ private static final String SS_SERVER_PASSWD = "org.onap.appc.adapter.saltstack.userPasswd";
+ private static final String SS_SERVER_SSH_KEY = "org.onap.appc.adapter.saltstack.sshKey";
+
+ private static final String COMMAND_IN_JSON_OUT = " --out=json --static ";
+ private static final String COMMAND_CHANGE_DEFAULT_DIR = " cd /srv/salt/ ;";
+
+ /**
+ * The logger to be used
+ */
+ private static final EELFLogger logger = EELFManager.getInstance().getLogger(SaltstackAdapterImpl.class);
+ /**
+ * Connection object
+ **/
+ private ConnectionBuilder sshClient;
+
+ /**
+ * Saltstack API Message Handlers
+ **/
+ private SaltstackMessageParser messageProcessor;
+
+ /**
+ * indicator whether in test mode
+ **/
+ private boolean testMode = false;
+
+ /**
+ * server emulator object to be used if in test mode
+ **/
+ private SaltstackServerEmulator testServer;
+
+ /**
+ * This default constructor is used as a work around because the activator wasn't getting called
+ */
+ public SaltstackAdapterImpl() throws SvcLogicException {
+ initialize(new SaltstackAdapterPropertiesProviderImpl());
+ }
+
+ public SaltstackAdapterImpl(SaltstackAdapterPropertiesProvider propProvider) throws SvcLogicException {
+ initialize(propProvider);
+ }
+
+ /**
+ * Used for jUnit test and testing interface
+ */
+ public SaltstackAdapterImpl(boolean mode) {
+ testMode = mode;
+ testServer = new SaltstackServerEmulator();
+ messageProcessor = new SaltstackMessageParser();
+ }
+
+ /**
+ * Returns the symbolic name of the adapter
+ *
+ * @return The adapter name
+ * @see SaltstackAdapter#getAdapterName()
+ */
+ @Override
+ public String getAdapterName() {
+ return ADAPTER_NAME;
+ }
+
+ /**
+ * Method posts info to Context memory in case of an error and throws a
+ * SvcLogicException causing SLI to register this as a failure
+ */
+ @SuppressWarnings("static-method")
+ private void doFailure(SvcLogicContext svcLogic, int code, String message) throws SvcLogicException {
+ logger.error(APPC_EXCEPTION_CAUGHT, message);
+ svcLogic.setStatus(OUTCOME_FAILURE);
+ svcLogic.setAttribute(RESULT_CODE_ATTRIBUTE_NAME, Integer.toString(code));
+ svcLogic.setAttribute(MESSAGE_ATTRIBUTE_NAME, message);
+ throw new SvcLogicException("Saltstack Adapter Error = " + message);
+ }
+
+ /**
+ * initialize the Saltstack adapter based on default and over-ride configuration data
+ */
+ private void initialize(SaltstackAdapterPropertiesProvider propProvider) throws SvcLogicException {
+
+
+ Properties props = propProvider.getProperties();
+
+ // Create the message processor instance
+ messageProcessor = new SaltstackMessageParser();
+
+ // Create the ssh client instance
+ // type of client is extracted from the property file parameter
+ // org.onap.appc.adapter.saltstack.clientType
+ // It can be :
+ // 1. BASIC. SSH Connection using username and password
+ // 2. SSH_CERT (trust only those whose certificates have been stored in the SSH KEY file)
+ // 3. DEFAULT SSH Connection without any authentication
+
+ try {
+ String clientType = props.getProperty(CLIENT_TYPE_PROPERTY_NAME);
+ logger.info("Saltstack ssh client type set to " + clientType);
+
+ if ("BASIC".equalsIgnoreCase(clientType)) {
+ logger.info("Creating ssh client connection");
+ // set path to keystore file
+ String sshHost = props.getProperty(SS_SERVER_HOSTNAME);
+ String sshPort = reqServerPort(props);
+ String sshUserName = props.getProperty(SS_SERVER_USERNAME);
+ String sshPassword = props.getProperty(SS_SERVER_PASSWD);
+ sshClient = new ConnectionBuilder(sshHost, sshPort, sshUserName, sshPassword);
+ } else if ("SSH_CERT".equalsIgnoreCase(clientType)) {
+ // set path to keystore file
+ String sshKey = props.getProperty(SS_SERVER_SSH_KEY);
+ String sshHost = props.getProperty(SS_SERVER_HOSTNAME);
+ String sshPort = reqServerPort(props);
+ logger.info("Creating ssh client with ssh KEY from " + sshKey);
+ sshClient = new ConnectionBuilder(sshHost, sshPort, sshKey);
+ } else {
+ logger.info("No saltstack-adapter.properties defined so reading from DG props");
+ sshClient = null;
+ }
+ } catch (NumberFormatException e) {
+ logger.error("Error Initializing Saltstack Adapter due to Unknown Exception", e);
+ throw new SvcLogicException("Saltstack Adapter Property file parsing Error = port in property file has to be an integer.");
+ } catch (Exception e) {
+ logger.error("Error Initializing Saltstack Adapter due to Exception", e);
+ throw new SvcLogicException("Saltstack Adapter Property file parsing Error = " + e.getMessage());
+ }
+ logger.info("Initialized Saltstack Adapter");
+ }
+
+ private String reqServerPort(Properties props) {
+ // use default port if null
+ if (props.getProperty(SS_SERVER_PORT) == null) {
+ return "22";
+ }
+ return props.getProperty(SS_SERVER_PORT);
+ }
+
+ private void setSSHClient(Map<String, String> params) throws SvcLogicException {
+ if (sshClient == null) {
+ logger.info("saltstack-adapter.properties not defined so reading saltstack host and " +
+ "auth details from DG's parameters");
+ String sshHost = messageProcessor.reqHostNameResult(params);
+ String sshPort = messageProcessor.reqPortResult(params);
+ String sshUserName = messageProcessor.reqUserNameResult(params);
+ String sshPassword = messageProcessor.reqPasswordResult(params);
+ logger.info("Creating ssh client with BASIC Auth");
+ if (!testMode) {
+ sshClient = new ConnectionBuilder(sshHost, sshPort, sshUserName, sshPassword);
+ }
+ }
+ }
+
+ private String parseEnvParam(JSONObject envParams) {
+ StringBuilder envParamBuilder = new StringBuilder();
+ if (envParams != null) {
+ for (Object key : envParams.keySet()) {
+ if (envParamBuilder.length() > 0) {
+ envParamBuilder.append(", ");
+ }
+ envParamBuilder.append(key + "=" + envParams.get((String) key));
+ logger.info("EnvParameters : " + envParamBuilder);
+ }
+ }
+ return envParamBuilder.toString();
+ }
+
+ private String parseFileParam(JSONObject fileParams) {
+ StringBuilder fileParamBuilder = new StringBuilder();
+ if (fileParams != null) {
+ for (Object key : fileParams.keySet()) {
+ fileParamBuilder.append("echo -e \"" + fileParams.get((String) key) + "\" > /srv/salt/" + key).append("; ");
+ logger.info("FileParameters : " + fileParamBuilder);
+ }
+ }
+ return fileParamBuilder.toString();
+ }
+
+ private String putToCommands(SvcLogicContext ctx, String slsFileName,
+ String applyTo, JSONObject envParams, JSONObject fileParams) throws SvcLogicException {
+
+ StringBuilder constructedCommand = new StringBuilder();
+ try {
+ File file = new File(slsFileName);
+ String slsFile = file.getName();
+ if (!slsFile.substring(slsFile.lastIndexOf("."),
+ slsFile.length()).equalsIgnoreCase(".sls")) {
+ doFailure(ctx, SaltstackResultCodes.IO_EXCEPTION.getValue(), "Input file " +
+ "is not of type .sls");
+ }
+ try(InputStream in = new FileInputStream(file)){
+ byte[] data = new byte[(int) file.length()];
+ in.read(data);
+ String str = new String(data, "UTF-8");
+ String slsWithoutExtn = stripExtension(slsFile);
+ constructedCommand.append(parseFileParam(fileParams)).append("echo -e \"").append(str).append("\" > /srv/salt/").
+ append(slsFile).append("; ").append(COMMAND_CHANGE_DEFAULT_DIR).append(" salt '").
+ append(applyTo).append("' state.apply ").append(slsWithoutExtn).append(" ").append(parseEnvParam(envParams)).append(COMMAND_IN_JSON_OUT);
+ }
+ logger.info("Command to be executed on server : " + constructedCommand.toString());
+
+ } catch (FileNotFoundException e) {
+ doFailure(ctx, SaltstackResultCodes.IO_EXCEPTION.getValue(), "Input SLS file " +
+ "not found in path : " + slsFileName + ". " + e.getMessage());
+ } catch (IOException e) {
+ doFailure(ctx, SaltstackResultCodes.IO_EXCEPTION.getValue(), "Input SLS file " +
+ "error in path : " + slsFileName + ". " + e.getMessage());
+ } catch (StringIndexOutOfBoundsException e) {
+ doFailure(ctx, SaltstackResultCodes.IO_EXCEPTION.getValue(), "Input file " +
+ "is not of type .sls");
+ }
+ return constructedCommand.toString();
+ }
+
+ private String stripExtension(String str) {
+ if (str == null) {
+ return null;
+ }
+ int pos = str.lastIndexOf(".");
+ if (pos == -1) {
+ return str;
+ }
+ return str.substring(0, pos);
+ }
+
+ private String putToCommands(String slsName, String applyTo, JSONObject envParams, JSONObject fileParams) {
+
+ StringBuilder constructedCommand = new StringBuilder();
+
+ constructedCommand.append(parseFileParam(fileParams)).append(COMMAND_CHANGE_DEFAULT_DIR).append(" salt '").append(applyTo)
+ .append("' state.apply ").append(slsName).append(" ").append(parseEnvParam(envParams)).append(COMMAND_IN_JSON_OUT);
+
+ logger.info("Command to be executed on server : " + constructedCommand.toString());
+ return constructedCommand.toString();
+ }
+
+ private void checkResponseStatus(SaltstackResult testResult, SvcLogicContext ctx, String reqID, boolean slsExec)
+ throws SvcLogicException {
+
+ // Check status of test request returned by Agent
+ if (testResult.getStatusCode() != SaltstackResultCodes.FINAL_SUCCESS.getValue()) {
+ ctx.setAttribute(ID_ATTRIBUTE_NAME, reqID);
+ doFailure(ctx, testResult.getStatusCode(), "Request for execution of command failed. Reason = " + testResult.getStatusMessage());
+ } else {
+ logger.info(String.format("Execution of request : successful."));
+ ctx.setAttribute(RESULT_CODE_ATTRIBUTE_NAME, Integer.toString(testResult.getStatusCode()));
+ ctx.setAttribute(MESSAGE_ATTRIBUTE_NAME, OUTCOME_SUCCESS);
+ ctx.setAttribute(ID_ATTRIBUTE_NAME, reqID);
+ }
+ }
+
+ // Public Method to post single command request to execute saltState. Posts the following back
+ // to Svc context memory
+ // org.onap.appc.adapter.saltstack.req.code : 100 if successful
+ // org.onap.appc.adapter.saltstack.req.messge : any message
+ // org.onap.appc.adapter.saltstack.req.Id : a unique uuid to reference the request
+ @Override
+ public void reqExecCommand(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException {
+ String reqID;
+ boolean slsExec;
+ SaltstackResult testResult;
+ setSSHClient(params);
+ try {
+ reqID = messageProcessor.reqId(params);
+ String commandToExecute = messageProcessor.reqCmd(params);
+ slsExec = messageProcessor.reqIsSLSExec(params);
+ long execTimeout = messageProcessor.reqExecTimeout(params);
+ testResult = execCommand(ctx, params, commandToExecute, execTimeout);
+ testResult = messageProcessor.parseResponse(ctx, reqID, testResult, slsExec);
+ checkResponseStatus(testResult, ctx, reqID, slsExec);
+ } catch (IOException e) {
+ doFailure(ctx, SaltstackResultCodes.IO_EXCEPTION.getValue(),
+ "IOException in file stream : " + e.getMessage());
+ }
+ }
+
+ /**
+ * Public Method to post SLS command request to execute saltState on server. Posts the following back
+ * to Svc context memory
+ * <p>
+ * org.onap.appc.adapter.saltstack.req.code : 200 if successful
+ * org.onap.appc.adapter.saltstack.req.messge : any message
+ * org.onap.appc.adapter.saltstack.req.Id : a unique uuid to reference the request
+ */
+ @Override
+ public void reqExecSLS(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException {
+ String reqID;
+ SaltstackResult testResult;
+ setSSHClient(params);
+ try {
+ reqID = messageProcessor.reqId(params);
+ String slsName = messageProcessor.reqSlsName(params);
+ String applyTo = messageProcessor.reqApplyToDevices(params);
+ long execTimeout = messageProcessor.reqExecTimeout(params);
+ JSONObject envParams = messageProcessor.reqEnvParameters(params);
+ JSONObject fileParams = messageProcessor.reqFileParameters(params);
+
+ String commandToExecute = putToCommands(slsName, applyTo, envParams, fileParams);
+ testResult = execCommand(ctx, params, commandToExecute, execTimeout);
+ testResult = messageProcessor.parseResponse(ctx, reqID, testResult, true);
+ checkResponseStatus(testResult, ctx, reqID, true);
+ } catch (IOException e) {
+ doFailure(ctx, SaltstackResultCodes.IO_EXCEPTION.getValue(),
+ "IOException in file stream : " + e.getMessage());
+ } catch (JSONException e) {
+ doFailure(ctx, SaltstackResultCodes.INVALID_COMMAND.getValue(), e.getMessage());
+ }
+ }
+
+ /**
+ * Public Method to post SLS file request to execute saltState. Posts the following back
+ * to Svc context memory
+ * <p>
+ * org.onap.appc.adapter.saltstack.req.code : 100 if successful
+ * org.onap.appc.adapter.saltstack.req.messge : any message
+ * org.onap.appc.adapter.saltstack.req.Id : a unique uuid to reference the request
+ */
+ @Override
+ public void reqExecSLSFile(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException {
+ String reqID;
+ SaltstackResult testResult;
+ setSSHClient(params);
+ try {
+ reqID = messageProcessor.reqId(params);
+ String slsFile = messageProcessor.reqSlsFile(params);
+ String applyTo = messageProcessor.reqApplyToDevices(params);
+ long execTimeout = messageProcessor.reqExecTimeout(params);
+ JSONObject envParams = messageProcessor.reqEnvParameters(params);
+ JSONObject fileParams = messageProcessor.reqFileParameters(params);
+
+ String commandToExecute = putToCommands(ctx, slsFile, applyTo, envParams, fileParams);
+ testResult = execCommand(ctx, params, commandToExecute, execTimeout);
+ testResult = messageProcessor.parseResponse(ctx, reqID, testResult, true);
+ checkResponseStatus(testResult, ctx, reqID, true);
+ } catch (IOException e) {
+ doFailure(ctx, SaltstackResultCodes.IO_EXCEPTION.getValue(),
+ "IOException in file stream : " + e.getMessage());
+ }
+ }
+
+ public SaltstackResult execCommand(SvcLogicContext ctx, Map<String, String> params, String commandToExecute,
+ long execTimeout)
+ throws SvcLogicException {
+
+ //convert execTimeout to Milliseconds
+ execTimeout = execTimeout * 1000;
+ SaltstackResult testResult = new SaltstackResult();
+ try {
+ if (params.get(CONNECTION_RETRY) == null) {
+ if (!testMode) {
+ testResult = sshClient.connectNExecute(commandToExecute, execTimeout);
+ } else {
+ testResult = testServer.mockReqExec(params);
+ }
+ } else if (params.get(CONNECTION_RETRY).equalsIgnoreCase("true")) {
+ if (!testMode) {
+ testResult = sshClient.connectNExecute(commandToExecute, true, execTimeout);
+ } else {
+ testResult = testServer.mockReqExec(params);
+ }
+ } else {
+ if (!testMode) {
+ testResult = sshClient.connectNExecute(commandToExecute, execTimeout);
+ } else {
+ testResult = testServer.mockReqExec(params);
+ }
+ }
+ } catch (IOException e) {
+ doFailure(ctx, SaltstackResultCodes.IO_EXCEPTION.getValue(),
+ "IOException in file stream : " + e.getMessage());
+ }
+ return testResult;
+ }
+}
diff --git a/adaptors/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/impl/SaltstackAdapterPropertiesProviderImpl.java b/adaptors/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/impl/SaltstackAdapterPropertiesProviderImpl.java
new file mode 100755
index 000000000..8f0d9857a
--- /dev/null
+++ b/adaptors/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/impl/SaltstackAdapterPropertiesProviderImpl.java
@@ -0,0 +1,192 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Samsung Electronics. All rights reserved.
+ * ================================================================================
+ *
+ * =============================================================================
+ * 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.
+ *
+ *
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.saltstack.impl;
+
+import org.onap.ccsdk.sli.adaptors.saltstack.SaltstackAdapterPropertiesProvider;
+import org.onap.ccsdk.sli.core.sli.ConfigurationException;
+import org.onap.ccsdk.sli.core.utils.JREFileResolver;
+import org.onap.ccsdk.sli.core.utils.KarafRootFileResolver;
+import org.onap.ccsdk.sli.core.utils.PropertiesFileResolver;
+import org.onap.ccsdk.sli.core.utils.common.CoreDefaultFileResolver;
+import org.onap.ccsdk.sli.core.utils.common.SdncConfigEnvVarFileResolver;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Optional;
+import java.util.Properties;
+import java.util.Vector;
+
+/**
+ * Responsible for determining the properties file to use and instantiating the
+ * <code>SqlResource</code> Service. The priority for properties file
+ * resolution is as follows:
+ * <p>
+ * <ol>
+ * <li>A directory identified by the system environment variable
+ * <code>SDNC_CONFIG_DIR</code></li>
+ * <li>The default directory <code>DEFAULT_DBLIB_PROP_DIR</code></li>
+ * <li>A directory identified by the JRE argument
+ * <code>sql-resource.properties</code></li>
+ * <li>A <code>sql-resource.properties</code> file located in the karaf root
+ * directory</li>
+ * </ol>
+ */
+public class SaltstackAdapterPropertiesProviderImpl implements SaltstackAdapterPropertiesProvider {
+
+ private static final Logger LOG = LoggerFactory.getLogger(SaltstackAdapterPropertiesProviderImpl.class);
+
+ /**
+ * The name of the properties file for database configuration
+ */
+ private static final String SALTSTACKADAPTER_PROP_FILE_NAME = "saltstack-adapter.properties";
+
+ /**
+ * A prioritized list of strategies for resolving sql-resource properties files.
+ */
+ private Vector<PropertiesFileResolver> saltstackAdapterPropertiesFileResolvers = new Vector<>();
+
+ /**
+ * The configuration properties for the db connection.
+ */
+ private Properties properties;
+
+ /**
+ * Set up the prioritized list of strategies for resolving dblib properties
+ * files.
+ */
+ public SaltstackAdapterPropertiesProviderImpl() {
+ saltstackAdapterPropertiesFileResolvers
+ .add(new SdncConfigEnvVarFileResolver("Using property file (1) from environment variable"));
+ saltstackAdapterPropertiesFileResolvers.add(new CoreDefaultFileResolver("Using property file (2) from default directory"));
+
+ saltstackAdapterPropertiesFileResolvers.add(
+ new JREFileResolver("Using property file (3) from JRE argument", SaltstackAdapterPropertiesProviderImpl.class));
+ saltstackAdapterPropertiesFileResolvers.add(new KarafRootFileResolver("Using property file (4) from karaf root", this));
+
+ // determines properties file as according to the priority described in the
+ // class header comment
+ final File propertiesFile = determinePropertiesFile(this);
+ if (propertiesFile != null) {
+ try (FileInputStream fileInputStream = new FileInputStream(propertiesFile)) {
+ properties = new Properties();
+ properties.load(fileInputStream);
+ } catch (final IOException e) {
+ LOG.error("Failed to load properties for file: {}", propertiesFile.toString(),
+ new ConfigurationException("Failed to load properties for file: " + propertiesFile.toString(),
+ e));
+ }
+ } else {
+ // Try to read properties as resource
+
+ InputStream propStr = getClass().getResourceAsStream("/" + SALTSTACKADAPTER_PROP_FILE_NAME);
+ if (propStr != null) {
+ properties = new Properties();
+ try {
+ properties.load(propStr);
+ propStr.close();
+ } catch (IOException e) {
+ properties = null;
+ }
+ }
+
+ }
+
+ if (properties == null) {
+ reportFailure("Missing configuration properties resource(3)", new ConfigurationException(
+ "Missing configuration properties resource(3): " + SALTSTACKADAPTER_PROP_FILE_NAME));
+
+ LOG.info("Defaulting org.onap.appc.adapter.saltstack.clientType to NONE");
+
+ properties = new Properties();
+ properties.setProperty("org.onap.appc.adapter.saltstack.clientType", "NONE");
+ }
+ }
+
+ /**
+ * Reports the method chosen for properties resolution to the
+ * <code>Logger</code>.
+ *
+ * @param message Some user friendly message
+ * @param fileOptional The file location of the chosen properties file
+ * @return the file location of the chosen properties file
+ */
+ private static File reportSuccess(final String message, final Optional<File> fileOptional) {
+ if (fileOptional.isPresent()) {
+ final File file = fileOptional.get();
+ LOG.info("{} {}", message, file.getPath());
+ return file;
+ }
+ return null;
+ }
+
+ /**
+ * Reports fatal errors. This is the case in which no properties file could be
+ * found.
+ *
+ * @param message An appropriate fatal error message
+ * @param configurationException An exception describing what went wrong during resolution
+ */
+ private static void reportFailure(final String message, final ConfigurationException configurationException) {
+
+ LOG.error("{}", message, configurationException);
+ }
+
+ /**
+ * Extract svclogic config properties.
+ *
+ * @return the svclogic config properties
+ */
+ public Properties getProperties() {
+ return properties;
+ }
+
+ /**
+ * Determines the sql-resource properties file to use based on the following priority:
+ * <ol>
+ * <li>A directory identified by the system environment variable
+ * <code>SDNC_CONFIG_DIR</code></li>
+ * <li>The default directory <code>DEFAULT_DBLIB_PROP_DIR</code></li>
+ * <li>A directory identified by the JRE argument
+ * <code>sql-resource.properties</code></li>
+ * <li>A <code>sql-resource.properties</code> file located in the karaf root
+ * directory</li>
+ * </ol>
+ */
+ File determinePropertiesFile(final SaltstackAdapterPropertiesProviderImpl resourceProvider) {
+
+ for (final PropertiesFileResolver sliPropertiesFileResolver : saltstackAdapterPropertiesFileResolvers) {
+ final Optional<File> fileOptional = sliPropertiesFileResolver.resolveFile(SALTSTACKADAPTER_PROP_FILE_NAME);
+ if (fileOptional.isPresent()) {
+ return reportSuccess(sliPropertiesFileResolver.getSuccessfulResolutionMessage(), fileOptional);
+ }
+ }
+
+ return null;
+ }
+}
diff --git a/adaptors/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/impl/SshConnection.java b/adaptors/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/impl/SshConnection.java
new file mode 100644
index 000000000..25d2d8402
--- /dev/null
+++ b/adaptors/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/impl/SshConnection.java
@@ -0,0 +1,217 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Samsung Electronics. All rights reserved.
+ * ================================================================================
+ *
+ * =============================================================================
+ * 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.
+ *
+ *
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.saltstack.impl;
+
+import java.io.OutputStream;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.security.KeyPair;
+import org.apache.sshd.client.SshClient;
+import org.apache.sshd.client.channel.ChannelExec;
+import org.apache.sshd.client.future.AuthFuture;
+import org.apache.sshd.client.future.OpenFuture;
+import org.apache.sshd.client.session.ClientSession;
+import org.apache.sshd.common.keyprovider.FileKeyPairProvider;
+import org.apache.sshd.common.keyprovider.KeyPairProvider;
+import org.onap.ccsdk.sli.adaptors.saltstack.model.Constants;
+import org.onap.ccsdk.sli.adaptors.saltstack.model.SshException;
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+
+/**
+ * Implementation of SshConnection interface based on Apache MINA SSHD library.
+ */
+class SshConnection {
+
+ private static final EELFLogger logger = EELFManager.getInstance().getApplicationLogger();
+
+ private static final long AUTH_TIMEOUT = 60000;
+ private static final long EXEC_TIMEOUT = 120000;
+ private String host;
+ private int port;
+ private String username;
+ private String password;
+ private long timeout = EXEC_TIMEOUT;
+ private String keyFile;
+ private SshClient sshClient;
+ private ClientSession clientSession;
+
+ public SshConnection(String host, int port, String username, String password, String keyFile) {
+ this.host = host;
+ this.port = port;
+ this.username = username;
+ this.password = password;
+ this.keyFile = keyFile;
+ }
+
+ public SshConnection(String host, int port, String username, String password) {
+ this(host, port, username, password, null);
+ }
+
+ public SshConnection(String host, int port, String keyFile) {
+ this(host, port, null, null, keyFile);
+ }
+
+ public void connect() {
+ sshClient = SshClient.setUpDefaultClient();
+ sshClient.start();
+ try {
+ clientSession =
+ sshClient.connect(username, host, port).getSession();
+ if (password != null) {
+ clientSession.addPasswordIdentity(password);
+ } else if (keyFile != null) {
+ Path keyFilePath = Paths.get(keyFile);
+ KeyPairProvider keyPairProvider = new FileKeyPairProvider(keyFilePath);
+ KeyPair keyPair = keyPairProvider.loadKeys().iterator().next();
+ clientSession.addPublicKeyIdentity(keyPair);
+ }
+ AuthFuture authFuture = clientSession.auth();
+ authFuture.await(AUTH_TIMEOUT);
+ if (!authFuture.isSuccess()) {
+ throw new SshException("Error establishing ssh connection to [" + username + "@" + host + ":" + port
+ + "]. Authentication failed.");
+ }
+ } catch (RuntimeException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new SshException("Error establishing ssh connection to [" + username + "@" + host + ":" + port + "].",
+ e);
+ }
+ if (logger.isDebugEnabled()) {
+ logger.debug("SSH: connected to [" + toString() + "]");
+ }
+ }
+
+ public void connectWithRetry() {
+ int retryCount;
+ int retryDelay;
+ int retriesLeft;
+ retryCount = Constants.DEFAULT_CONNECTION_RETRY_COUNT;
+ retryDelay = Constants.DEFAULT_CONNECTION_RETRY_DELAY;
+ retriesLeft = retryCount + 1;
+ do {
+ try {
+ this.connect();
+ break;
+ } catch (RuntimeException e) {
+ if (retriesLeft > 1) {
+ logger.debug("SSH Connection failed. Waiting for change in server's state.");
+ waitForConnection(retryDelay);
+ retriesLeft--;
+ logger.debug("Retrying SSH connection. Attempt [" + Integer.toString(retryCount - retriesLeft + 1)
+ + "] out of [" + retryCount + "]");
+ } else {
+ throw e;
+ }
+ }
+ } while (retriesLeft > 0);
+ }
+
+ public void disconnect() {
+ try {
+ if (logger.isDebugEnabled()) {
+ logger.debug("SSH: disconnecting from [" + toString() + "]");
+ }
+ clientSession.close(false);
+ } finally {
+ if (sshClient != null) {
+ sshClient.stop();
+ }
+ }
+ }
+
+ public void setExecTimeout(long timeout) {
+ this.timeout = timeout;
+ }
+
+ public int execCommand(String cmd, OutputStream out, OutputStream err) {
+ return execCommand(cmd, out, err, false);
+ }
+
+ public int execCommandWithPty(String cmd, OutputStream out) {
+ return execCommand(cmd, out, out, true);
+ }
+
+ private int execCommand(String cmd, OutputStream out, OutputStream err, boolean usePty) {
+ try {
+ if (logger.isDebugEnabled()) {
+ logger.debug("SSH: executing command");
+ }
+ ChannelExec client = clientSession.createExecChannel(cmd);
+ client.setUsePty(usePty); // use pseudo-tty?
+ client.setOut(out);
+ client.setErr(err);
+ OpenFuture openFuture = client.open();
+ int exitStatus;
+ try {
+ client.wait(timeout);
+ openFuture.verify();
+ Integer exitStatusI = client.getExitStatus();
+ if (exitStatusI == null) {
+ throw new SshException("Error executing command [" + cmd + "] over SSH [" + username + "@" + host
+ + ":" + port + "]. Operation timed out.");
+ }
+ exitStatus = exitStatusI;
+ } finally {
+ client.close(false);
+ }
+ return exitStatus;
+ } catch (RuntimeException e) {
+ throw e;
+ } catch (Exception e1) {
+ throw new SshException(
+ "Error executing command [" + cmd + "] over SSH [" + username + "@" + host + ":" + port + "]", e1);
+ }
+ }
+
+ private void waitForConnection(int retryDelay) {
+ long time = retryDelay * 1000L;
+ long future = System.currentTimeMillis() + time;
+ if (time != 0) {
+ while (System.currentTimeMillis() < future && time > 0) {
+ try {
+ Thread.sleep(time);
+ } catch (InterruptedException e) {
+ /*
+ * This is rare, but it can happen if another thread interrupts us while we are sleeping. In that
+ * case, the thread is resumed before the delay time has actually expired, so re-calculate the
+ * amount of delay time needed and reenter the sleep until we get to the future time.
+ */
+ time = future - System.currentTimeMillis();
+ }
+ }
+ }
+ }
+
+ @Override
+ public String toString() {
+ String address = host;
+ if (username != null) {
+ address = username + '@' + address + ':' + port;
+ }
+ return address;
+ }
+}
diff --git a/adaptors/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/Constants.java b/adaptors/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/Constants.java
new file mode 100644
index 000000000..a1826c4e1
--- /dev/null
+++ b/adaptors/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/Constants.java
@@ -0,0 +1,93 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : APPC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Copyright (C) 2017 Amdocs
+ * =============================================================================
+ * 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.
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.saltstack.model;
+
+public class Constants {
+ public static final String NETCONF_SCHEMA = "sdnctl";
+ public static final String SDNCTL_SCHEMA = "sdnctl";
+ public static final String DEVICE_AUTHENTICATION_TABLE_NAME = "DEVICE_AUTHENTICATION";
+ public static final String CONFIGFILES_TABLE_NAME = "CONFIGFILES";
+ public static final String DEVICE_INTERFACE_LOG_TABLE_NAME = "DEVICE_INTERFACE_LOG";
+ public static final String FILE_CONTENT_TABLE_FIELD_NAME = "FILE_CONTENT";
+ public static final String FILE_NAME_TABLE_FIELD_NAME = "FILE_NAME";
+ public static final String USER_NAME_TABLE_FIELD_NAME = "USER_NAME";
+ public static final String PASSWORD_TABLE_FIELD_NAME = "PASSWORD";
+ public static final String PORT_NUMBER_TABLE_FIELD_NAME = "PORT_NUMBER";
+ public static final String VNF_TYPE_TABLE_FIELD_NAME = "VNF_TYPE";
+ public static final String SERVICE_INSTANCE_ID_FIELD_NAME = "SERVICE_INSTANCE_ID";
+ public static final String REQUEST_ID_FIELD_NAME = "REQUEST_ID";
+ public static final String CREATION_DATE_FIELD_NAME = "CREATION_DATE";
+ public static final String LOG_FIELD_NAME = "LOG";
+ public static final String SDC_ARTIFACTS_TABLE_NAME = "ASDC_ARTIFACTS";
+ public static final String PAYLOAD = "payload";
+ public static final String CONNECTION_RETRY_DELAY = "org.onap.appc.ssh.connection.retry.delay";
+ public static final String CONNECTION_RETRY_COUNT = "org.onap.appc.ssh.connection.retry.count";
+ public static final int DEFAULT_CONNECTION_RETRY_DELAY = 60;
+ public static final int DEFAULT_CONNECTION_RETRY_COUNT = 5;
+ public static final int DEFAULT_SSH_COMMAND_RETRY_COUNT = 3;
+ public static final int DEFAULT_CHECKACTIVE_RETRY_COUNT = 3;
+ public static final int DEFAULT_CHECKACTIVE_RETRY_DELAY = 30;
+ public static final int DEFAULT_STOP_RETRY_COUNT = 3;
+ public static final int DEFAULT_STOP_RETRY_DELAY = 30;
+ public static final String PARAM_IN_CONNECTION_DETAILS = "connection-details";
+ public static final String PARAM_IN_NODE_NAME = "node-name";
+ public static final String PARAM_IN_NODE_STATUS = "node-status";
+ public static final String PARAM_IN_VM_URL = "vm-url";
+ public static final String SKIP_EXECUTION_INSTALLER_BIN_FILE = "Skip-execution-installer-bin-file";
+ public static final String SKIP_DEPLOY = "Skip-deploy";
+ public static final String UPGRADE_VERSION = "upgrade-version";
+ public static final String STATE_COMMAND = "/opt/jnetx/skyfall-scp/asp-state.sh | grep -o UP | wc -l";
+ public static final String VNFC_STATE_COMMAND = "/opt/jnetx/skyfall-scp/asp-state.sh";
+ public static final String RESTART_NODE_COMMAND = "/opt/jnetx/skyfall-scp/asp-stop.sh --restart -f --nodes";
+ public static final String START_NODE_COMMAND = "/opt/jnetx/skyfall-scp/asp-start.sh -f --nodes";
+ public static final String STOP_NODE_COMMAND = "/opt/jnetx/skyfall-scp/asp-stop.sh -f --nodes";
+ public static final int STATE_COMMAND_RESULT = 18;
+ public static final String FE_STATE_TRUE_TEST_COMMAND = "ssh -t -q fe1 /opt/omni/bin/swmml -e display-platform-status | grep -o TRUE | wc -l";
+ public static final int FE_STATE_TRUE_TEST_RESULT = 22;
+ public static final String FE_STATE_FALSE_TEST_COMMAND = "ssh -t -q fe1 /opt/omni/bin/swmml -e display-platform-status | grep -o FALSE | wc -l";
+ public static final int FE_STATE_FALSE_TEST_RESULT = 2;
+ public static final String FE_OPERATIONAL_TEST_COMMAND = "ssh -t -q fe1 /opt/omni/bin/swmml -e display-platform-status | grep -o 'NOT FULLY OPERATIONAL' | wc -l";
+ public static final int FE_OPERATIONAL_TEST_RESULT = 2;
+ public static final String SMP_CHECK_ACTIVE_STATE_COMMAND = "cat skyfall-scp/runtime/SCP_SMP_*/smp/log/system.log| grep SSS | tail -1";
+ public static final String SMP_STATE_ACTIVE = "SMP is active";
+ public static final String SMP_STATE_INACTIVE = "SMP is not active";
+ public static final String RSYNC_COMMAND = "yes n | /opt/jnetx/skyfall-scp/asp-rsync.sh --check | grep -o 'is active' | wc -l";
+ public static final int RSYNC_COMMAND_RESULT = 9;
+ public static final String PARAM_IN_TIMEOUT = "timeout";
+ public static final String PARAM_IN_FILE_URL = "source-file-url";
+ public static final String DOWNLOAD_COMMAND = "wget -N %s";
+ public static final String[] VM_NAMES = new String[]{"fe1", "fe2", "be1", "be2", "be3", "be4", "be5", "smp1", "smp2"};
+ public static final String DEFAULT_DISK_SPACE = "10240000";
+ public static final String DF_COMMAND_TEMPLATE = "ssh %s df | grep vda1 | grep -v grep | tr -s ' '|cut -d ' ' -f4";
+ public static final String DG_OUTPUT_STATUS_MESSAGE = "output.status.message";
+ public static final String ATTRIBUTE_ERROR_MESSAGE = "error-message";
+ public static final String CONNECTION_DETAILS_FIELD_NAME = "connection-details";
+ public static final String VNF_HOST_IP_ADDRESS_FIELD_NAME = "vnf-host-ip-address";
+ public static final String VNF_HOST_IP2_ADDRESS_FIELD_NAME = "vnf-host-ip2-address";
+ public static final String DG_ERROR_FIELD_NAME = "org.openecom.appc.dg.error";
+
+ private Constants() {
+ }
+}
diff --git a/adaptors/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/JsonParser.java b/adaptors/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/JsonParser.java
new file mode 100644
index 000000000..3eb353a17
--- /dev/null
+++ b/adaptors/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/JsonParser.java
@@ -0,0 +1,89 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Samsung Electronics. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.saltstack.model;
+
+import org.codehaus.jettison.json.JSONArray;
+import org.codehaus.jettison.json.JSONException;
+import org.codehaus.jettison.json.JSONObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+public final class JsonParser {
+
+ private static final Logger log = LoggerFactory.getLogger(JsonParser.class);
+
+ private JsonParser() {
+ // Preventing instantiation of the same.
+ }
+
+ @SuppressWarnings("unchecked")
+ public static Map<String, String> convertToProperties(String s)
+ throws JSONException {
+
+ checkNotNull(s, "Input should not be null.");
+
+ JSONObject json = new JSONObject(s);
+ Map<String, Object> wm = new HashMap<>();
+ Iterator<String> ii = json.keys();
+ while (ii.hasNext()) {
+ String key1 = ii.next();
+ wm.put(key1, json.get(key1));
+ }
+
+ Map<String, String> mm = new HashMap<>();
+
+ while (!wm.isEmpty())
+ for (String key : new ArrayList<>(wm.keySet())) {
+ Object o = wm.get(key);
+ wm.remove(key);
+
+ if (o instanceof Boolean || o instanceof Number || o instanceof String) {
+ mm.put(key, o.toString());
+
+ log.info("Added property: {} : {}", key, o.toString());
+ } else if (o instanceof JSONObject) {
+ JSONObject jo = (JSONObject) o;
+ Iterator<String> i = jo.keys();
+ while (i.hasNext()) {
+ String key1 = i.next();
+ wm.put(key + "." + key1, jo.get(key1));
+ }
+ } else if (o instanceof JSONArray) {
+ JSONArray ja = (JSONArray) o;
+ mm.put(key + "_length", String.valueOf(ja.length()));
+
+ log.info("Added property: {}_length: {}", key, String.valueOf(ja.length()));
+
+ for (int i = 0; i < ja.length(); i++)
+ wm.put(key + '[' + i + ']', ja.get(i));
+ }
+ }
+ return mm;
+ }
+}
diff --git a/adaptors/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/SaltstackMessageParser.java b/adaptors/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/SaltstackMessageParser.java
new file mode 100644
index 000000000..3bb401ad4
--- /dev/null
+++ b/adaptors/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/SaltstackMessageParser.java
@@ -0,0 +1,412 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017-2018 Samsung Electronics. All rights reserved.
+ * ================================================================================
+ *
+ * =============================================================================
+ * 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.
+ *
+ *
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.saltstack.model;
+
+/**
+ * This module implements the APP-C/Saltstack Server interface
+ * based on the REST API specifications
+ */
+
+import com.google.common.base.Strings;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.UUID;
+
+/**
+ * Class that validates and constructs requests sent/received from
+ * Saltstack Server
+ */
+public class SaltstackMessageParser {
+
+ private static final String SS_AGENT_HOSTNAME_KEY = "HostName";
+ private static final String SS_AGENT_PORT_KEY = "Port";
+ private static final String PASS_KEY = "Password";
+ private static final String USER_KEY = "User";
+ private static final String CMD_EXEC = "Cmd"; //cmd
+ private static final String IS_SLS_EXEC = "SlsExec"; //slsExec
+ private static final String SS_REQ_ID = "Id";
+ private static final String SLS_FILE_LOCATION = "SlsFile"; //slsFile
+ private static final String SLS_NAME = "SlsName"; //slsName
+ private static final String MINION_TO_APPLY = "NodeList"; //applyTo
+ private static final String EXEC_TIMEOUT_TO_APPLY = "Timeout"; //execTimeout
+ private static final String FILE_PARAMETERS_OPT_KEY = "FileParameters";
+ private static final String ENV_PARAMETERS_OPT_KEY = "EnvParameters";
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(SaltstackMessageParser.class);
+
+ /**
+ * Method that validates that the Map has enough information
+ * to query Saltstack server for a result. If so, it returns
+ * the appropriate PORT number.
+ */
+ public String reqPortResult(Map<String, String> params) throws SvcLogicException {
+ // use default port if null
+ if (params.get(SS_AGENT_PORT_KEY) == null) {
+ return "22";
+ }
+ return params.get(SS_AGENT_PORT_KEY);
+ }
+
+ /**
+ * Method that validates that the Map has enough information
+ * to query Saltstack server for a result. If so, it returns
+ * the appropriate HOST name.
+ */
+ public String reqHostNameResult(Map<String, String> params) throws SvcLogicException {
+
+ throwIfMissingMandatoryParam(params, SS_AGENT_HOSTNAME_KEY);
+ return params.get(SS_AGENT_HOSTNAME_KEY);
+ }
+
+ /**
+ * Method that validates that the Map has enough information
+ * to query Saltstack server for a result. If so, it returns
+ * the appropriate request ID.
+ */
+ public String reqId(Map<String, String> params) {
+
+ if (params.get(SaltstackMessageParser.SS_REQ_ID) == null) {
+ return UUID.randomUUID().toString();
+ } else if (params.get(SaltstackMessageParser.SS_REQ_ID).equalsIgnoreCase("")) {
+ return UUID.randomUUID().toString();
+ }
+ return params.get(SaltstackMessageParser.SS_REQ_ID);
+ }
+
+ /**
+ * Method that validates that the Map has enough information
+ * to query Saltstack server for a result. If so, it returns
+ * the appropriate command to execute.
+ */
+ public String reqCmd(Map<String, String> params) throws SvcLogicException {
+
+ throwIfMissingMandatoryParam(params, CMD_EXEC);
+ return params.get(SaltstackMessageParser.CMD_EXEC);
+ }
+
+ /**
+ * Method that validates that the Map has enough information
+ * to query Saltstack server for a result. If so, it returns
+ * the appropriate SLS file location to execute.
+ */
+ public String reqSlsFile(Map<String, String> params) throws SvcLogicException {
+
+ throwIfMissingMandatoryParam(params, SLS_FILE_LOCATION);
+ return params.get(SaltstackMessageParser.SLS_FILE_LOCATION);
+ }
+
+ /**
+ * Method that validates that the Map has enough information
+ * to query Saltstack server for a result. If so, it returns
+ * the appropriate SLS file location to execute.
+ */
+ public String reqSlsName(Map<String, String> params) throws SvcLogicException {
+
+ throwIfMissingMandatoryParam(params, SLS_NAME);
+ String slsName = params.get(SaltstackMessageParser.SLS_NAME);
+ try {
+ if (slsName.substring(slsName.lastIndexOf("."), slsName.length()).equalsIgnoreCase(".sls")) {
+ return stripExtension(slsName);
+ }
+ } catch (StringIndexOutOfBoundsException e) {
+ return slsName;
+ }
+ return slsName;
+ }
+
+ private String stripExtension(String str) {
+ if (str == null) {
+ return null;
+ }
+ int pos = str.lastIndexOf(".");
+ if (pos == -1) {
+ return str;
+ }
+ return str.substring(0, pos);
+ }
+
+ /**
+ * Method that validates that the Map has enough information
+ * to query Saltstack server for a result. If so, it returns
+ * the appropriate minions/vnfc to execute the SLS file.
+ */
+ public String reqApplyToDevices(Map<String, String> params) {
+
+ if (params.get(SaltstackMessageParser.MINION_TO_APPLY) == null) {
+ return "*";
+ } else if (params.get(SaltstackMessageParser.MINION_TO_APPLY).equalsIgnoreCase("")) {
+ return "*";
+ }
+ return params.get(SaltstackMessageParser.MINION_TO_APPLY);
+ }
+
+ /**
+ * Method that validates that the Map has enough information
+ * to query Saltstack server for a result. If so, it returns
+ * the appropriate minions/vnfc to execute the SLS file.
+ */
+ public long reqExecTimeout(Map<String, String> params) {
+
+ if (params.get(SaltstackMessageParser.EXEC_TIMEOUT_TO_APPLY) == null) {
+ return -1;
+ } else if (params.get(SaltstackMessageParser.EXEC_TIMEOUT_TO_APPLY).equalsIgnoreCase("")) {
+ return -1;
+ }
+ return Long.parseLong(params.get(SaltstackMessageParser.EXEC_TIMEOUT_TO_APPLY));
+ }
+
+ /**
+ * Method that validates that the Map has enough information
+ * to query Saltstack server for a result. If so, it returns
+ * the appropriate EnvParameters to execute the SLS file.
+ */
+ public JSONObject reqEnvParameters(Map<String, String> params) throws JSONException {
+
+ JSONObject jsonPayload = new JSONObject();
+ final String[] optionalTestParam = {SaltstackMessageParser.ENV_PARAMETERS_OPT_KEY};
+ parseParam(params, optionalTestParam, jsonPayload);
+
+ return (JSONObject) jsonPayload.remove(SaltstackMessageParser.ENV_PARAMETERS_OPT_KEY);
+ }
+
+ /**
+ * Method that validates that the Map has enough information
+ * to query Saltstack server for a result. If so, it returns
+ * the appropriate EnvParameters to execute the SLS file.
+ */
+ public JSONObject reqFileParameters(Map<String, String> params) throws JSONException {
+
+ JSONObject jsonPayload = new JSONObject();
+ final String[] optionalTestParam = {SaltstackMessageParser.FILE_PARAMETERS_OPT_KEY};
+ parseParam(params, optionalTestParam, jsonPayload);
+
+ return (JSONObject) jsonPayload.remove(SaltstackMessageParser.FILE_PARAMETERS_OPT_KEY);
+ }
+
+ private void parseParam(Map<String, String> params, String[] optionalTestParams, JSONObject jsonPayload)
+ throws JSONException {
+
+ Set<String> optionalParamsSet = new HashSet<>();
+ Collections.addAll(optionalParamsSet, optionalTestParams);
+
+ //@formatter:off
+ params.entrySet()
+ .stream()
+ .filter(entry -> optionalParamsSet.contains(entry.getKey()))
+ .filter(entry -> !Strings.isNullOrEmpty(entry.getValue()))
+ .forEach(entry -> parseParam(entry, jsonPayload));
+ //@formatter:on
+ }
+
+ private void parseParam(Map.Entry<String, String> params, JSONObject jsonPayload)
+ throws JSONException {
+ String key = params.getKey();
+ String payload = params.getValue();
+
+ switch (key) {
+ case ENV_PARAMETERS_OPT_KEY:
+ JSONObject paramsJson = new JSONObject(payload);
+ jsonPayload.put(key, paramsJson);
+ break;
+
+ case FILE_PARAMETERS_OPT_KEY:
+ jsonPayload.put(key, getFilePayload(payload));
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ /**
+ * Return payload with escaped newlines
+ */
+ private JSONObject getFilePayload(String payload) {
+ String formattedPayload = payload.replace("\n", "\\n").replace("\r", "\\r");
+ return new JSONObject(formattedPayload);
+ }
+
+ /**
+ * Method that validates that the Map has enough information
+ * to query Saltstack server for a result. If so, it returns
+ * the appropriate IsSLSExec true or false.
+ */
+ public boolean reqIsSLSExec(Map<String, String> params) throws SvcLogicException {
+
+ final String[] mandatoryTestParams = {CMD_EXEC, IS_SLS_EXEC};
+
+ for (String key : mandatoryTestParams) {
+ throwIfMissingMandatoryParam(params, key);
+ }
+
+ return params.get(SaltstackMessageParser.IS_SLS_EXEC).equalsIgnoreCase("true");
+ }
+
+ /**
+ * Method that validates that the Map has enough information
+ * to query Saltstack server for a result. If so, it returns
+ * the appropriate Saltstack server login user name.
+ */
+ public String reqUserNameResult(Map<String, String> params) throws SvcLogicException {
+
+ throwIfMissingMandatoryParam(params, USER_KEY);
+ return params.get(USER_KEY);
+ }
+
+ /**
+ * Method that validates that the Map has enough information
+ * to query Saltstack server for a result. If so, it returns
+ * the appropriate Saltstack server login password.
+ */
+ public String reqPasswordResult(Map<String, String> params) throws SvcLogicException {
+
+ throwIfMissingMandatoryParam(params, PASS_KEY);
+ return params.get(PASS_KEY);
+ }
+
+ /**
+ * This method parses response from the Saltstack Server when we do a post
+ * and returns an SaltstackResult object.
+ */
+ public SaltstackResult parseResponse(SvcLogicContext ctx, String pfx,
+ SaltstackResult saltstackResult, boolean slsExec) throws IOException {
+ int code = saltstackResult.getStatusCode();
+ boolean executionStatus = true;
+ boolean retCodeFound = false;
+ if (code != SaltstackResultCodes.SUCCESS.getValue()) {
+ return saltstackResult;
+ }
+ ByteArrayOutputStream outStream = saltstackResult.getOutputMessage();
+ String outMessage = outStream.toString();
+ try {
+ Map<String, String> mm = JsonParser.convertToProperties(outMessage);
+ if (mm != null) {
+ for (Map.Entry<String, String> entry : mm.entrySet()) {
+ if (entry.getKey().contains("retcode")) {
+ retCodeFound = true;
+ if (!entry.getValue().equalsIgnoreCase("0")) {
+ executionStatus = false;
+ }
+ }
+ ctx.setAttribute(pfx + "." + entry.getKey(), entry.getValue());
+ LOGGER.info("+++ " + pfx + "." + entry.getKey() + ": [" + entry.getValue() + "]");
+ }
+ }
+ } catch (org.codehaus.jettison.json.JSONException e) {
+ if (slsExec) {
+ return new SaltstackResult(SaltstackResultCodes.INVALID_RESPONSE.getValue(), "error parsing response file"
+ + " : Output has to be in JSON format");
+ }
+ LOGGER.info("Output not in JSON format");
+ return putToProperties(ctx, pfx, saltstackResult);
+ } catch (Exception e) {
+ return new SaltstackResult(SaltstackResultCodes.INVALID_RESPONSE_FILE.getValue(), "error parsing response file"
+ + " : " + e.getMessage());
+ } finally {
+ if (outStream != null) {
+ outStream.close();
+ }
+ }
+ if (slsExec) {
+ if (!retCodeFound) {
+ if (outMessage != null && !outMessage.equalsIgnoreCase("")) {
+ return new SaltstackResult(SaltstackResultCodes.COMMAND_EXEC_FAILED_STATUS.getValue(),
+ outMessage);
+ }
+ return new SaltstackResult(SaltstackResultCodes.COMMAND_EXEC_FAILED_STATUS.getValue(),
+ "error in executing configuration at the server, check your command input");
+ }
+ if (!executionStatus) {
+ if (outMessage != null && !outMessage.equalsIgnoreCase("")) {
+ return new SaltstackResult(SaltstackResultCodes.COMMAND_EXEC_FAILED_STATUS.getValue(),
+ outMessage);
+ }
+ return new SaltstackResult(SaltstackResultCodes.COMMAND_EXEC_FAILED_STATUS.getValue(),
+ "error in executing configuration at the server, check your command input");
+ }
+ }
+ saltstackResult.setStatusCode(SaltstackResultCodes.FINAL_SUCCESS.getValue());
+ return saltstackResult;
+ }
+
+ public SaltstackResult putToProperties(SvcLogicContext ctx, String pfx,
+ SaltstackResult saltstackResult) throws IOException {
+
+ ByteArrayOutputStream buffer = saltstackResult.getOutputMessage();
+ InputStream inputStream = null;
+ try {
+ byte[] bytes = buffer.toByteArray();
+ Properties prop = new Properties();
+ inputStream = new ByteArrayInputStream(bytes);
+ prop.load(inputStream);
+ ctx.setAttribute(pfx + "completeResult", prop.toString());
+ for (Object key : prop.keySet()) {
+ String name = (String) key;
+ String value = prop.getProperty(name);
+ if (value != null && value.trim().length() > 0) {
+ ctx.setAttribute(pfx + "." + name, value.trim());
+ LOGGER.info("+++ " + pfx + "." + name + ": [" + value + "]");
+ }
+ }
+ } catch (Exception e) {
+ saltstackResult = new SaltstackResult(SaltstackResultCodes.INVALID_RESPONSE_FILE.getValue(), "Error parsing response file." +
+ " Error = " + e.getMessage());
+ } finally {
+ if (buffer != null && inputStream != null) {
+ buffer.close();
+ inputStream.close();
+ }
+ }
+ saltstackResult.setStatusCode(SaltstackResultCodes.FINAL_SUCCESS.getValue());
+ return saltstackResult;
+ }
+
+ private void throwIfMissingMandatoryParam(Map<String, String> params, String key) throws SvcLogicException {
+ if (!params.containsKey(key)) {
+ throw new SvcLogicException(String.format(
+ "Saltstack: Mandatory SaltstackAdapter key %s not found in parameters provided by calling agent !",
+ key));
+ }
+ if (Strings.isNullOrEmpty(params.get(key))) {
+ throw new SvcLogicException(String.format(
+ "Saltstack: Mandatory SaltstackAdapter key %s not found in parameters provided by calling agent !",
+ key));
+ }
+ }
+}
diff --git a/adaptors/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/SaltstackResult.java b/adaptors/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/SaltstackResult.java
new file mode 100644
index 000000000..727cfe314
--- /dev/null
+++ b/adaptors/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/SaltstackResult.java
@@ -0,0 +1,102 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Samsung Electronics. All rights reserved.
+ * ================================================================================
+ *
+ * =============================================================================
+ * 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.
+ *
+ *
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.saltstack.model;
+
+import java.io.ByteArrayOutputStream;
+
+/**
+ * Simple class to store code and message returned by POST/GET to an Saltstack Server
+ */
+public class SaltstackResult {
+
+ private static final String EMPTY_VALUE = "UNKNOWN";
+
+ private int statusCode;
+ private String statusMessage;
+ private String results;
+ private ByteArrayOutputStream out;
+ private int sshExitStatus;
+
+ public SaltstackResult() {
+ this(-1, EMPTY_VALUE, EMPTY_VALUE, -1);
+ }
+
+ public SaltstackResult(int code, String message) {
+ this(code, message, EMPTY_VALUE, -1);
+ }
+
+ public SaltstackResult(int code, String message, String result, int sshCode) {
+ statusCode = code;
+ statusMessage = message;
+ results = result;
+ sshExitStatus = sshCode;
+ }
+
+ void set(int code, String message, String results) {
+ this.statusCode = code;
+ this.statusMessage = message;
+ this.results = results;
+ }
+
+ public ByteArrayOutputStream getOutputMessage() {
+ return out;
+ }
+
+ public void setOutputMessage(ByteArrayOutputStream out) {
+ this.out = out;
+ }
+
+ public int getStatusCode() {
+ return this.statusCode;
+ }
+
+ public void setStatusCode(int code) {
+ this.statusCode = code;
+ }
+
+ public String getStatusMessage() {
+ return this.statusMessage;
+ }
+
+ public void setStatusMessage(String message) {
+ this.statusMessage = message;
+ }
+
+ public String getResults() {
+ return this.results;
+ }
+
+ public void setResults(String results) {
+ this.results = results;
+ }
+
+ public int getSshExitStatus() {
+ return sshExitStatus;
+ }
+
+ public void setSshExitStatus(int sshExitStatus) {
+ this.sshExitStatus = sshExitStatus;
+ }
+}
diff --git a/adaptors/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/SaltstackResultCodes.java b/adaptors/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/SaltstackResultCodes.java
new file mode 100644
index 000000000..932554983
--- /dev/null
+++ b/adaptors/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/SaltstackResultCodes.java
@@ -0,0 +1,100 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Samsung Electronics. All rights reserved.
+ * ================================================================================
+ *
+ * =============================================================================
+ * 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.
+ *
+ *
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.saltstack.model;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * enum of the various codes that APP-C uses to resolve different
+ * status of response from Saltstack Server
+ **/
+
+public enum SaltstackResultCodes {
+
+ // @formatter:off
+ SUCCESS(400),
+ KEYSTORE_EXCEPTION(622),
+ CERTIFICATE_ERROR(610),
+ IO_EXCEPTION(611),
+ HOST_UNKNOWN(625),
+ USER_UNAUTHORIZED(613),
+ UNKNOWN_EXCEPTION(699),
+ OPERATION_TIMEOUT(659),
+ SSL_EXCEPTION(697),
+ SSH_EXCEPTION(695),
+ INVALID_COMMAND(698),
+ INVALID_RESPONSE(601),
+ INVALID_RESPONSE_FILE(600),
+ PENDING(100),
+ REJECTED(101),
+ FINAL_SUCCESS(200),
+ CHECK_CTX_FOR_CMD_SUCCESS(250),
+ COMMAND_EXEC_FAILED_STATUS(670),
+ REQ_FAILURE(401),
+ MESSAGE(1),
+ CODE(0),
+ INITRESPONSE(0),
+ FINALRESPONSE(1);
+ // @formatter:on
+
+ private final Set<Integer> initCodes = new HashSet<>(Arrays.asList(100, 101));
+ private final Set<Integer> finalCodes = new HashSet<>(Arrays.asList(200, 500));
+ private final ArrayList<Set<Integer>> codeSets = new ArrayList<>(Arrays.asList(initCodes, finalCodes));
+ private final Set<String> messageSet = new HashSet<>(Arrays.asList("PENDING", "FINISHED", "TERMINATED"));
+ private final int value;
+
+ SaltstackResultCodes(int value) {
+ this.value = value;
+ }
+
+ ;
+
+ public int getValue() {
+ return value;
+ }
+
+ public boolean checkValidCode(int type, int code) {
+ return codeSets.get(type).contains(code);
+ }
+
+ public String getValidCodes(int type) {
+ StringBuilder sb = new StringBuilder("[ ");
+ codeSets.get(type).stream().forEach(s -> sb.append(s).append(","));
+ return sb.append("]").toString();
+ }
+
+ public boolean checkValidMessage(String message) {
+ return messageSet.contains(message);
+ }
+
+ public String getValidMessages() {
+ StringBuilder sb = new StringBuilder("[ ");
+ messageSet.stream().forEach(s -> sb.append(s).append(","));
+ return sb.append("]").toString();
+ }
+}
diff --git a/adaptors/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/SaltstackServerEmulator.java b/adaptors/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/SaltstackServerEmulator.java
new file mode 100644
index 000000000..78976562b
--- /dev/null
+++ b/adaptors/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/SaltstackServerEmulator.java
@@ -0,0 +1,93 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Samsung Electronics. All rights reserved.
+ * ================================================================================
+ *
+ * =============================================================================
+ * 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.
+ *
+ *
+ * ============LICENSE_END=========================================================
+ */
+
+
+
+/*
+ * Class to emulate responses from the Saltstack Server that is compliant with the APP-C Saltstack Server
+ * Interface. Used for jUnit tests to verify code is working. In tests it can be used
+ * as a replacement for methods from ConnectionBuilder class
+ */
+
+package org.onap.ccsdk.sli.adaptors.saltstack.model;
+
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+
+import java.io.ByteArrayOutputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Map;
+
+public class SaltstackServerEmulator {
+
+ private static final String SALTSTATE_FILE_NAME = "fileName";
+ private final EELFLogger logger = EELFManager.getInstance().getLogger(SaltstackServerEmulator.class);
+
+ /**
+ * Method that emulates the response from an Saltstack Server
+ * when presented with a request to execute a saltState
+ * Returns an saltstack object result. The response code is always the ssh code 200 (i.e connection successful)
+ * payload is json string as would be sent back by Saltstack Server
+ **/
+ public SaltstackResult mockReqExec(Map<String, String> params) {
+ SaltstackResult result = new SaltstackResult();
+
+ try {
+ if (params.get("Test") == "fail") {
+ result = rejectRequest(result, "Mocked: Fail");
+ } else {
+ String fileName = params.get(SALTSTATE_FILE_NAME);
+ if (fileName == null) {
+ throw new FileNotFoundException("No response file found");
+ }
+ result = acceptRequest(result, fileName);
+ }
+ } catch (Exception e) {
+ logger.error("Exception caught", e);
+ rejectRequest(result, e.getMessage());
+ }
+ return result;
+ }
+
+ private SaltstackResult rejectRequest(SaltstackResult result, String Message) {
+ result.setStatusCode(SaltstackResultCodes.REJECTED.getValue());
+ result.setStatusMessage("Rejected");
+ return result;
+ }
+
+ private SaltstackResult acceptRequest(SaltstackResult result, String fileName) throws IOException {
+ result.setStatusCode(SaltstackResultCodes.SUCCESS.getValue());
+ result.setStatusMessage("Success");
+ Path path = Paths.get(fileName);
+ byte[] data = Files.readAllBytes(path);
+ ByteArrayOutputStream byteOut = new ByteArrayOutputStream(data.length);
+ byteOut.write(data, 0, data.length);
+ result.setOutputMessage(byteOut);
+ return result;
+ }
+} \ No newline at end of file
diff --git a/adaptors/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/SshException.java b/adaptors/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/SshException.java
new file mode 100644
index 000000000..037a1e891
--- /dev/null
+++ b/adaptors/saltstack-adapter/saltstack-adapter-provider/src/main/java/org/onap/ccsdk/sli/adaptors/saltstack/model/SshException.java
@@ -0,0 +1,37 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : APPC
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Copyright (C) 2017 Amdocs
+ * =============================================================================
+ * 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.
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.saltstack.model;
+
+public class SshException extends RuntimeException {
+ private static final long serialVersionUID = 1L;
+
+ public SshException(String message) {
+ super(message);
+ }
+
+ public SshException(String message, Throwable cause) {
+ super(message, cause);
+ }
+} \ No newline at end of file
diff --git a/adaptors/saltstack-adapter/saltstack-adapter-provider/src/main/resources/OSGI-INF/blueprint/saltstack-adapter-blueprint.xml b/adaptors/saltstack-adapter/saltstack-adapter-provider/src/main/resources/OSGI-INF/blueprint/saltstack-adapter-blueprint.xml
new file mode 100755
index 000000000..e360f8184
--- /dev/null
+++ b/adaptors/saltstack-adapter/saltstack-adapter-provider/src/main/resources/OSGI-INF/blueprint/saltstack-adapter-blueprint.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ============LICENSE_START=======================================================
+ ONAP : CCSDK
+ ================================================================================
+ Copyright (C) 2017 - 2018 Samsung Electronics. All rights
+ reserved.
+ ================================================================================
+ 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.
+ ============LICENSE_END=========================================================
+ -->
+
+<blueprint xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0"
+ xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+ odl:use-default-for-reference-types="true">
+
+ <bean id="propProvider"
+ class="org.onap.ccsdk.sli.adaptors.saltstack.impl.SaltstackAdapterPropertiesProviderImpl"/>
+
+ <bean id="saltstackAdapterInstance"
+ class="org.onap.ccsdk.sli.adaptors.saltstack.impl.SaltstackAdapterImpl">
+ <argument ref="propProvider"/>
+ </bean>
+
+ <service ref="saltstackAdapterInstance">
+ <interfaces>
+ <value>org.onap.ccsdk.sli.adaptors.saltstack.SaltstackAdapter
+ </value>
+ </interfaces>
+ </service>
+
+</blueprint>
diff --git a/adaptors/saltstack-adapter/saltstack-adapter-provider/src/main/resources/org/opendaylight/blueprint/saltstack-adapter-blueprint.xml b/adaptors/saltstack-adapter/saltstack-adapter-provider/src/main/resources/org/opendaylight/blueprint/saltstack-adapter-blueprint.xml
new file mode 100755
index 000000000..e360f8184
--- /dev/null
+++ b/adaptors/saltstack-adapter/saltstack-adapter-provider/src/main/resources/org/opendaylight/blueprint/saltstack-adapter-blueprint.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ============LICENSE_START=======================================================
+ ONAP : CCSDK
+ ================================================================================
+ Copyright (C) 2017 - 2018 Samsung Electronics. All rights
+ reserved.
+ ================================================================================
+ 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.
+ ============LICENSE_END=========================================================
+ -->
+
+<blueprint xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0"
+ xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+ odl:use-default-for-reference-types="true">
+
+ <bean id="propProvider"
+ class="org.onap.ccsdk.sli.adaptors.saltstack.impl.SaltstackAdapterPropertiesProviderImpl"/>
+
+ <bean id="saltstackAdapterInstance"
+ class="org.onap.ccsdk.sli.adaptors.saltstack.impl.SaltstackAdapterImpl">
+ <argument ref="propProvider"/>
+ </bean>
+
+ <service ref="saltstackAdapterInstance">
+ <interfaces>
+ <value>org.onap.ccsdk.sli.adaptors.saltstack.SaltstackAdapter
+ </value>
+ </interfaces>
+ </service>
+
+</blueprint>
diff --git a/adaptors/saltstack-adapter/saltstack-adapter-provider/src/main/resources/saltstack-adapter.properties b/adaptors/saltstack-adapter/saltstack-adapter-provider/src/main/resources/saltstack-adapter.properties
new file mode 100644
index 000000000..1755f7adf
--- /dev/null
+++ b/adaptors/saltstack-adapter/saltstack-adapter-provider/src/main/resources/saltstack-adapter.properties
@@ -0,0 +1,43 @@
+###
+# ============LICENSE_START=======================================================
+# ONAP : CCSDK
+# ================================================================================
+# Copyright (C) 2018 Samsung Electronics. All rights reserved.
+# ================================================================================
+#
+# =============================================================================
+# 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.
+#
+#
+# ============LICENSE_END=========================================================
+###
+#
+# Default properties for the APP-C TestService Adapter
+#
+# -------------------------------------------------------------------------------------------------
+#
+# Define the name and path of any user-provided configuration (bootstrap) file that can be loaded
+# to supply configuration options
+org.onap.appc.bootstrap.file=appc.properties
+org.onap.appc.bootstrap.path=${user.home},/opt/opendaylight/current/properties
+appc.application.name=APPC
+#
+# Define the message resource bundle name to be loaded
+org.onap.appc.resources=org.onap/appc/i18n/MessageResources
+#
+# The name of the adapter.
+org.onap.appc.provider.adaptor.name=org.onap.appc.appc_saltstack_adapter
+# Default truststore path and password
+org.onap.appc.adapter.saltstack.trustStore=/opt/opendaylight/tls-client/mykeystore.js
+org.onap.appc.adapter.saltstack.trustStore.trustPasswd=changeit
+org.onap.appc.adapter.saltstack.clientType=TRUST_ALL
diff --git a/adaptors/saltstack-adapter/saltstack-adapter-provider/src/test/java/org/onap/ccsdk/adapter/impl/TestConnectionBuilder.java b/adaptors/saltstack-adapter/saltstack-adapter-provider/src/test/java/org/onap/ccsdk/adapter/impl/TestConnectionBuilder.java
new file mode 100644
index 000000000..71fcf3454
--- /dev/null
+++ b/adaptors/saltstack-adapter/saltstack-adapter-provider/src/test/java/org/onap/ccsdk/adapter/impl/TestConnectionBuilder.java
@@ -0,0 +1,184 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Samsung Electronics. All rights reserved.
+ * ================================================================================
+ *
+ * =============================================================================
+ * 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.
+ *
+ *
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.adapter.impl;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.onap.ccsdk.sli.adaptors.saltstack.impl.ConnectionBuilder;
+import org.onap.ccsdk.sli.adaptors.saltstack.model.SaltstackResult;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.junit.Assert.assertEquals;
+
+
+public class TestConnectionBuilder {
+
+ private ConnectionBuilder connBuilder;
+ private Map<String, String> params;
+
+
+ @Before
+ public void setup() throws IllegalArgumentException {
+ String HostName = "test";
+ String Port = "10";
+ String User = "test";
+ String Password = "test";
+ connBuilder = new ConnectionBuilder(HostName, Port, User, Password);
+
+ params = new HashMap<>();
+ params.put("AgentUrl", "https://192.168.1.1");
+ params.put("User", "test");
+ params.put("Password", "test");
+ }
+
+ @After
+ public void tearDown() {
+ connBuilder = null;
+ params = null;
+ }
+
+ @Test
+ public void reqExecCommand_exitStatus255() {
+
+ int exitStatus = 255;
+ String errFilePath = "src/test/resources/test.json";
+ String command = "test";
+
+ SaltstackResult result = connBuilder.sortExitStatus(exitStatus, errFilePath, command);
+ int status = result.getStatusCode();
+ assertEquals(698, status);
+ }
+
+ @Test
+ public void reqExecCommand_exitStatus1() {
+
+ int exitStatus = 1;
+ String errFilePath = "src/test/resources/test.json";
+ String command = "test";
+
+ SaltstackResult result = connBuilder.sortExitStatus(exitStatus, errFilePath, command);
+ int status = result.getStatusCode();
+ assertEquals(698, status);
+ }
+
+ @Test
+ public void reqExecCommand_exitStatus67() {
+
+ int exitStatus = 67;
+ String errFilePath = "src/test/resources/test.json";
+ String command = "test";
+
+ SaltstackResult result = connBuilder.sortExitStatus(exitStatus, errFilePath, command);
+ int status = result.getStatusCode();
+ assertEquals(610, status);
+ }
+
+ @Test
+ public void reqExecCommand_exitStatus73() {
+
+ int exitStatus = 73;
+ String errFilePath = "src/test/resources/test.json";
+ String command = "test";
+
+ SaltstackResult result = connBuilder.sortExitStatus(exitStatus, errFilePath, command);
+ int status = result.getStatusCode();
+ assertEquals(610, status);
+ }
+
+ @Test
+ public void reqExecCommand_exitStatus5() {
+
+ int exitStatus = 5;
+ String errFilePath = "src/test/resources/test.json";
+ String command = "test";
+
+ SaltstackResult result = connBuilder.sortExitStatus(exitStatus, errFilePath, command);
+ int status = result.getStatusCode();
+ assertEquals(613, status);
+ }
+
+ @Test
+ public void reqExecCommand_exitStatus65() {
+
+ int exitStatus = 65;
+ String errFilePath = "src/test/resources/test.json";
+ String command = "test";
+
+ SaltstackResult result = connBuilder.sortExitStatus(exitStatus, errFilePath, command);
+ int status = result.getStatusCode();
+ assertEquals(613, status);
+ }
+
+ @Test
+ public void reqExecCommand_exitStatus67613() {
+
+ int exitStatus = 5;
+ String errFilePath = "src/test/resources/test.json";
+ String command = "test";
+
+ SaltstackResult result = connBuilder.sortExitStatus(exitStatus, errFilePath, command);
+ int status = result.getStatusCode();
+ assertEquals(613, status);
+ }
+
+ @Test
+ public void reqExecCommand_exitStatus65613() {
+
+ int exitStatus = 65;
+ String errFilePath = "src/test/resources/test.json";
+ String command = "test";
+
+ SaltstackResult result = connBuilder.sortExitStatus(exitStatus, errFilePath, command);
+ int status = result.getStatusCode();
+ assertEquals(613, status);
+ }
+
+ @Test
+ public void reqExecCommand_exitStatusUnknown() {
+
+ int exitStatus = 5121;
+ String errFilePath = "src/test/resources/test.json";
+ String command = "test";
+
+ SaltstackResult result = connBuilder.sortExitStatus(exitStatus, errFilePath, command);
+ int status = result.getStatusCode();
+ assertEquals(699, status);
+ }
+
+ @Test
+ public void reqExecCommand_exitStatusNoFile() {
+
+ int exitStatus = 65;
+ String errFilePath = "src/test/resource/test.json";
+ String command = "test";
+
+ SaltstackResult result = connBuilder.sortExitStatus(exitStatus, errFilePath, command);
+ int status = result.getStatusCode();
+ assertEquals(613, status);
+ }
+}
diff --git a/adaptors/saltstack-adapter/saltstack-adapter-provider/src/test/java/org/onap/ccsdk/adapter/impl/TestSaltstackAdapterImpl.java b/adaptors/saltstack-adapter/saltstack-adapter-provider/src/test/java/org/onap/ccsdk/adapter/impl/TestSaltstackAdapterImpl.java
new file mode 100644
index 000000000..22e8c2082
--- /dev/null
+++ b/adaptors/saltstack-adapter/saltstack-adapter-provider/src/test/java/org/onap/ccsdk/adapter/impl/TestSaltstackAdapterImpl.java
@@ -0,0 +1,1051 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Samsung Electronics. All rights reserved.
+ * ================================================================================
+ *
+ * =============================================================================
+ * 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.
+ *
+ *
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.adapter.impl;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.onap.ccsdk.sli.adaptors.saltstack.impl.SaltstackAdapterImpl;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+
+public class TestSaltstackAdapterImpl {
+
+ private SaltstackAdapterImpl adapter;
+ private String TestId;
+ private boolean testMode = true;
+ private Map<String, String> params;
+ private SvcLogicContext svcContext;
+
+
+ @Before
+ public void setup() throws IllegalArgumentException {
+ testMode = true;
+ svcContext = new SvcLogicContext();
+ adapter = new SaltstackAdapterImpl(testMode);
+
+ params = new HashMap<>();
+ params.put("AgentUrl", "https://192.168.1.1");
+ params.put("User", "test");
+ params.put("Password", "test");
+ }
+
+ @After
+ public void tearDown() {
+ testMode = false;
+ adapter = null;
+ params = null;
+ svcContext = null;
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void reqExecCommand_shouldSetFailed() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("HostName", "test");
+ params.put("Port", "10");
+ params.put("User", "test");
+ params.put("Password", "test");
+ params.put("Test", "fail");
+ adapter.reqExecCommand(params, svcContext);
+ String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code");
+ TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id");
+ assertEquals("101", status);
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void reqExecCommand_shouldSetUserFailed() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("HostName", "test");
+ params.put("Port", "10");
+ params.put("Password", "test");
+ params.put("Test", "fail");
+ adapter.reqExecCommand(params, svcContext);
+ String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code");
+ TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id");
+ assertEquals("101", status);
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void reqExecCommand_shouldSetHostFailed() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("Port", "10");
+ params.put("User", "test");
+ params.put("Password", "test");
+ params.put("Test", "fail");
+ adapter.reqExecCommand(params, svcContext);
+ String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code");
+ TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id");
+ assertEquals("101", status);
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void reqExecCommand_shouldSetPortFailed() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("HostName", "test");
+ params.put("User", "test");
+ params.put("Password", "test");
+ params.put("Test", "fail");
+ adapter.reqExecCommand(params, svcContext);
+ String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code");
+ TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id");
+ assertEquals("101", status);
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void reqExecCommand_shouldSetPasswordFailed() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("HostName", "test");
+ params.put("Port", "10");
+ params.put("User", "test");
+ params.put("Test", "fail");
+ adapter.reqExecCommand(params, svcContext);
+ String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code");
+ TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id");
+ assertEquals("101", status);
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void reqExecCommand_shouldSetMandatoryFailed() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("Test", "fail");
+ adapter.reqExecCommand(params, svcContext);
+ String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code");
+ TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id");
+ assertEquals("101", status);
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void reqExecCommand_NoResponseFile() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("HostName", "test");
+ params.put("Port", "10");
+ params.put("User", "test");
+ params.put("Password", "test");
+ params.put("Test", "success");
+ params.put("Cmd", "test");
+ params.put("SlsExec", "false");
+ try {
+ adapter.reqExecCommand(params, svcContext);
+ String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code");
+ TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id");
+ assertEquals("400", status);
+ } catch (NullPointerException e) {
+ fail(e.getMessage() + " Unknown exception encountered ");
+ }
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void reqExecCommand_NoResponseFileWithRetry() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("HostName", "test");
+ params.put("Port", "10");
+ params.put("User", "test");
+ params.put("Password", "test");
+ params.put("Test", "success");
+ params.put("withRetry", "true");
+ params.put("Cmd", "test");
+ params.put("SlsExec", "false");
+ try {
+ adapter.reqExecCommand(params, svcContext);
+ String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code");
+ TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id");
+ assertEquals("400", status);
+ } catch (NullPointerException e) {
+ fail(e.getMessage() + " Unknown exception encountered ");
+ }
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void reqExecCommand_NoResponseFileWithRetryZero() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("HostName", "test");
+ params.put("Port", "10");
+ params.put("User", "test");
+ params.put("Password", "test");
+ params.put("Test", "success");
+ params.put("withRetry", "0");
+ params.put("Cmd", "test");
+ params.put("SlsExec", "false");
+ try {
+ adapter.reqExecCommand(params, svcContext);
+ String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code");
+ TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id");
+ assertEquals("400", status);
+ } catch (NullPointerException e) {
+ fail(e.getMessage() + " Unknown exception encountered ");
+ }
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void reqExecCommand_NoResponseFileWithNoRetry() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("HostName", "test");
+ params.put("Port", "10");
+ params.put("User", "test");
+ params.put("Password", "test");
+ params.put("Test", "success");
+ params.put("withRetry", "false");
+ params.put("Cmd", "test");
+ params.put("SlsExec", "false");
+
+ try {
+ adapter.reqExecCommand(params, svcContext);
+ String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code");
+ TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id");
+ assertEquals("400", status);
+ } catch (NullPointerException e) {
+ fail(e.getMessage() + " Unknown exception encountered ");
+ }
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void reqExecCommand_shouldSetFailure() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("HostName", "test");
+ params.put("Port", "10");
+ params.put("User", "test");
+ params.put("Password", "test");
+ params.put("Cmd", "test");
+ params.put("SlsExec", "test");
+ params.put("Test", "fail");
+ try {
+ adapter.reqExecCommand(params, svcContext);
+ String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code");
+ TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id");
+ assertEquals("400", status);
+ } catch (NullPointerException e) {
+ fail(e.getMessage() + " Unknown exception encountered ");
+ }
+ }
+
+ @Test
+ public void reqExecCommand_shouldSetSuccessNoSLS() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("HostName", "test");
+ params.put("Port", "10");
+ params.put("User", "test");
+ params.put("Password", "test");
+ params.put("Test", "success");
+ params.put("fileName", "src/test/resources/test.json");
+ params.put("Id", "test1");
+ params.put("Cmd", "test");
+ params.put("SlsExec", "false");
+
+ adapter.reqExecCommand(params, svcContext);
+ String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code");
+ TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id");
+ assertEquals("200", status);
+ assertEquals(TestId, "test1");
+ }
+
+ @Test
+ public void reqExecCommand_shouldSetSuccessExecSLS() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("HostName", "test");
+ params.put("Port", "10");
+ params.put("User", "test");
+ params.put("Password", "test");
+ params.put("Test", "success");
+ params.put("fileName", "src/test/resources/test-sls.json");
+ params.put("Id", "test1");
+ params.put("Cmd", "test");
+ params.put("SlsExec", "true");
+
+ adapter.reqExecCommand(params, svcContext);
+ String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code");
+ TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id");
+ assertEquals("200", status);
+ assertEquals(TestId, "test1");
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void reqExecCommand_shouldSetFailExecSLS() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("HostName", "test");
+ params.put("Port", "10");
+ params.put("User", "test");
+ params.put("Password", "test");
+ params.put("Test", "success");
+ params.put("fileName", "src/test/resources/test.json");
+ params.put("Id", "test1");
+ params.put("Cmd", "test");
+ params.put("SlsExec", "true");
+
+ adapter.reqExecCommand(params, svcContext);
+ TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id");
+ assertEquals(TestId, "test1");
+ }
+
+ @Test
+ public void reqExecCommand_shouldSetSuccessFileTxt() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("HostName", "test");
+ params.put("Port", "10");
+ params.put("User", "test");
+ params.put("Password", "test");
+ params.put("Test", "success");
+ params.put("fileName", "src/test/resources/test.txt");
+ params.put("Id", "txt");
+ params.put("Cmd", "test");
+ params.put("SlsExec", "false");
+
+ adapter.reqExecCommand(params, svcContext);
+ String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code");
+ TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id");
+ assertEquals("200", status);
+ assertEquals(TestId, "txt");
+ }
+
+ @Test
+ public void reqExecCommand_shouldSetSuccessFileNoExtension() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("HostName", "test");
+ params.put("Port", "10");
+ params.put("User", "test");
+ params.put("Password", "test");
+ params.put("Test", "success");
+ params.put("fileName", "src/test/resources/test");
+ params.put("Id", "txt");
+ params.put("Cmd", "test");
+ params.put("SlsExec", "false");
+
+ adapter.reqExecCommand(params, svcContext);
+ String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code");
+ TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id");
+ assertEquals("200", status);
+ assertEquals(TestId, "txt");
+ }
+
+ @Test
+ public void reqExecCommand_shouldSetSuccessFileInvalidJson() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("HostName", "test");
+ params.put("Port", "10");
+ params.put("User", "test");
+ params.put("Password", "test");
+ params.put("Test", "success");
+ params.put("fileName", "src/test/resources/test-invalid.json");
+ params.put("Id", "test1");
+ params.put("Cmd", "test");
+ params.put("SlsExec", "false");
+
+ adapter.reqExecCommand(params, svcContext);
+ String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code");
+ TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id");
+ assertEquals("200", status);
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void reqExecCommand_shouldSetFailFileInvalidFile() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("HostName", "test");
+ params.put("Port", "10");
+ params.put("User", "test");
+ params.put("Password", "test");
+ params.put("Test", "success");
+ params.put("fileName", "src/test/resources/test-none.json");
+ params.put("Id", "test1");
+
+ adapter.reqExecCommand(params, svcContext);
+ }
+
+ @Test
+ public void reqExecCommand_shouldSetSuccessFileJsonNoReqID() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("HostName", "test");
+ params.put("Port", "10");
+ params.put("User", "test");
+ params.put("Password", "test");
+ params.put("Test", "success");
+ params.put("fileName", "src/test/resources/test.json");
+ params.put("Cmd", "test");
+ params.put("SlsExec", "false");
+
+ adapter.reqExecCommand(params, svcContext);
+ String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code");
+ TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id");
+ assertEquals("200", status);
+ }
+
+ @Test
+ public void reqExecSLSFile_shouldSetSuccessJson() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("HostName", "test");
+ params.put("Port", "10");
+ params.put("User", "test");
+ params.put("Password", "test");
+ params.put("Test", "success");
+ params.put("SlsFile", "src/test/resources/test.sls");
+ params.put("fileName", "src/test/resources/test-sls.json");
+ params.put("Id", "test1");
+ params.put("Cmd", "test");
+
+ adapter.reqExecSLSFile(params, svcContext);
+ String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code");
+ TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id");
+ assertEquals("200", status);
+ assertEquals(TestId, "test1");
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void reqExecSLSFile_NoSLSfile() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("HostName", "test");
+ params.put("Port", "10");
+ params.put("User", "test");
+ params.put("Password", "test");
+ params.put("Test", "success");
+ params.put("SlsFile", "src/test/resources/test-none.sls");
+ params.put("fileName", "src/test/resources/test-sls.json");
+ params.put("Id", "test1");
+
+ adapter.reqExecSLSFile(params, svcContext);
+ TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id");
+ assertEquals(TestId, "test1");
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void reqExecSLSFile_NoExtn() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("HostName", "test");
+ params.put("Port", "10");
+ params.put("User", "test");
+ params.put("Password", "test");
+ params.put("Test", "success");
+ params.put("SlsFile", "src/test/resources/test-none");
+ params.put("fileName", "src/test/resources/test-sls.json");
+ params.put("Id", "test1");
+
+ adapter.reqExecSLSFile(params, svcContext);
+ TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id");
+ assertEquals(TestId, "test1");
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void reqExecSLSFile_NoResponsefile() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("HostName", "test");
+ params.put("Port", "10");
+ params.put("User", "test");
+ params.put("Password", "test");
+ params.put("Test", "success");
+ params.put("SlsFile", "src/test/resources/test.json");
+ params.put("fileName", "src/test/resources/test-none.json");
+ params.put("Id", "test1");
+
+ adapter.reqExecSLSFile(params, svcContext);
+ TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id");
+ assertEquals(TestId, "test1");
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void reqExecSLSFile_WithMinionSetNotSLSType() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("HostName", "test");
+ params.put("Port", "10");
+ params.put("User", "test");
+ params.put("Password", "test");
+ params.put("Test", "success");
+ params.put("SlsFile", "src/test/resources/test.json");
+ params.put("fileName", "src/test/resources/test-sls.json");
+ params.put("Id", "test1");
+ params.put("Cmd", "test");
+ params.put("NodeList", "minion1");
+
+ adapter.reqExecSLSFile(params, svcContext);
+ String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code");
+ TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id");
+ assertEquals("200", status);
+ assertEquals(TestId, "test1");
+ }
+
+ @Test
+ public void reqExecSLSFile_WithMinionSetSuccessSls() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("HostName", "test");
+ params.put("Port", "10");
+ params.put("User", "test");
+ params.put("Password", "test");
+ params.put("Test", "success");
+ params.put("SlsFile", "src/test/resources/test.sls");
+ params.put("fileName", "src/test/resources/test-sls.json");
+ params.put("Id", "test1");
+ params.put("Cmd", "test");
+ params.put("NodeList", "minion1");
+
+ adapter.reqExecSLSFile(params, svcContext);
+ String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code");
+ TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id");
+ assertEquals("200", status);
+ assertEquals(TestId, "test1");
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void reqExecSLSFile_WithMinionNoSLSfile() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("HostName", "test");
+ params.put("Port", "10");
+ params.put("User", "test");
+ params.put("Password", "test");
+ params.put("Test", "success");
+ params.put("SlsFile", "src/test/resources/test-none.json");
+ params.put("fileName", "src/test/resources/test-sls.json");
+ params.put("Id", "test1");
+ params.put("NodeList", "minion1");
+
+ adapter.reqExecSLSFile(params, svcContext);
+ TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id");
+ assertEquals(TestId, "test1");
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void reqExecSLSFile_WithMinionNoResponsefile() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("HostName", "test");
+ params.put("Port", "10");
+ params.put("User", "test");
+ params.put("Password", "test");
+ params.put("Test", "success");
+ params.put("SlsFile", "src/test/resources/test.json");
+ params.put("fileName", "src/test/resources/test-none.json");
+ params.put("Id", "test1");
+ params.put("NodeList", "minion1");
+
+ adapter.reqExecSLSFile(params, svcContext);
+ TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id");
+ assertEquals(TestId, "test1");
+ }
+
+ @Test
+ public void reqExecSLSFile_WithAllMinionSetSuccessJson() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("HostName", "test");
+ params.put("Port", "10");
+ params.put("User", "test");
+ params.put("Password", "test");
+ params.put("Test", "success");
+ params.put("SlsFile", "src/test/resources/test.sls");
+ params.put("fileName", "src/test/resources/test-sls.json");
+ params.put("Id", "test1");
+ params.put("Cmd", "test");
+ params.put("NodeList", "*");
+
+ adapter.reqExecSLSFile(params, svcContext);
+ String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code");
+ TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id");
+ assertEquals("200", status);
+ assertEquals(TestId, "test1");
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void reqExecSLSFile_WithAllMinionNoSLSfile() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("HostName", "test");
+ params.put("Port", "10");
+ params.put("User", "test");
+ params.put("Password", "test");
+ params.put("Test", "success");
+ params.put("SlsFile", "src/test/resources/test-none.json");
+ params.put("fileName", "src/test/resources/test-sls.json");
+ params.put("Id", "test1");
+ params.put("NodeList", "*");
+
+ adapter.reqExecSLSFile(params, svcContext);
+ TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id");
+ assertEquals(TestId, "test1");
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void reqExecSLSFile_WithAllMinionNoResponsefile() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("HostName", "test");
+ params.put("Port", "10");
+ params.put("User", "test");
+ params.put("Password", "test");
+ params.put("Test", "success");
+ params.put("SlsFile", "src/test/resources/test.json");
+ params.put("fileName", "src/test/resources/test-none.json");
+ params.put("Id", "test1");
+ params.put("NodeList", "*");
+
+ adapter.reqExecSLSFile(params, svcContext);
+ TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id");
+ assertEquals(TestId, "test1");
+ }
+
+
+ @Test
+ public void reqExecSLS_shouldSetSuccessJson() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("HostName", "test");
+ params.put("Port", "10");
+ params.put("User", "test");
+ params.put("Password", "test");
+ params.put("Test", "success");
+ params.put("SlsName", "src/test.sls");
+ params.put("fileName", "src/test/resources/test-sls.json");
+ params.put("Id", "test1");
+ params.put("Cmd", "test");
+
+ adapter.reqExecSLS(params, svcContext);
+ String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code");
+ TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id");
+ assertEquals("200", status);
+ assertEquals(TestId, "test1");
+ }
+
+ @Test
+ public void reqExecSLS_shouldSetNoExtn() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("HostName", "test");
+ params.put("Port", "10");
+ params.put("User", "test");
+ params.put("Password", "test");
+ params.put("Test", "success");
+ params.put("SlsName", "src/test");
+ params.put("fileName", "src/test/resources/test-sls.json");
+ params.put("Id", "test1");
+ params.put("Cmd", "test");
+
+ adapter.reqExecSLS(params, svcContext);
+ String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code");
+ TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id");
+ assertEquals("200", status);
+ assertEquals(TestId, "test1");
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void reqExecSLS_NoResponsefile() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("HostName", "test");
+ params.put("Port", "10");
+ params.put("User", "test");
+ params.put("Password", "test");
+ params.put("Test", "success");
+ params.put("SlsName", "src/test/resources/test.json");
+ params.put("fileName", "src/test/resources/test-none.json");
+ params.put("Id", "test1");
+
+ adapter.reqExecSLS(params, svcContext);
+ TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id");
+ assertEquals(TestId, "test1");
+ }
+
+
+ @Test
+ public void reqExecSLS_WithMinionSetSuccessSls() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("HostName", "test");
+ params.put("Port", "10");
+ params.put("User", "test");
+ params.put("Password", "test");
+ params.put("Test", "success");
+ params.put("SlsName", "src/test/resources/test.sls");
+ params.put("fileName", "src/test/resources/test-sls.json");
+ params.put("Id", "test1");
+ params.put("Cmd", "test");
+ params.put("NodeList", "minion1");
+
+ adapter.reqExecSLS(params, svcContext);
+ String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code");
+ TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id");
+ assertEquals("200", status);
+ assertEquals(TestId, "test1");
+ }
+
+
+ @Test(expected = SvcLogicException.class)
+ public void reqExecSLS_WithMinionNoResponsefile() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("HostName", "test");
+ params.put("Port", "10");
+ params.put("User", "test");
+ params.put("Password", "test");
+ params.put("Test", "success");
+ params.put("SlsName", "src/test/resources/test.json");
+ params.put("fileName", "src/test/resources/test-none.json");
+ params.put("Id", "test1");
+ params.put("NodeList", "minion1");
+
+ adapter.reqExecSLS(params, svcContext);
+ TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id");
+ assertEquals(TestId, "test1");
+ }
+
+ @Test
+ public void reqExecSLS_WithAllMinionSetSuccessJson() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("HostName", "test");
+ params.put("Port", "10");
+ params.put("User", "test");
+ params.put("Password", "test");
+ params.put("Test", "success");
+ params.put("SlsName", "src/test/resources/test.sls");
+ params.put("fileName", "src/test/resources/test-sls.json");
+ params.put("Id", "test1");
+ params.put("Cmd", "test");
+ params.put("NodeList", "*");
+
+ adapter.reqExecSLS(params, svcContext);
+ String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code");
+ TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id");
+ assertEquals("200", status);
+ assertEquals(TestId, "test1");
+ }
+
+
+ @Test(expected = SvcLogicException.class)
+ public void reqExecSLS_WithAllMinionNoResponsefile() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("HostName", "test");
+ params.put("Port", "10");
+ params.put("User", "test");
+ params.put("Password", "test");
+ params.put("Test", "success");
+ params.put("SlsName", "src/test/resources/test.json");
+ params.put("fileName", "src/test/resources/test-none.json");
+ params.put("Id", "test1");
+ params.put("NodeList", "*");
+
+ adapter.reqExecSLS(params, svcContext);
+ TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id");
+ assertEquals(TestId, "test1");
+ }
+
+
+ @Test
+ public void reqExecCommand_shouldSetSuccessReal() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("HostName", "127.0.0.1");
+ params.put("Port", "22");
+ params.put("User", "sdn");
+ params.put("Password", "foo");
+ params.put("Id", "test1");
+ params.put("Cmd", "ls -l");
+ params.put("SlsExec", "false");
+ params.put("Timeout", "120");
+ adapter = new SaltstackAdapterImpl();
+ try {
+ adapter.reqExecCommand(params, svcContext);
+ String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code");
+ TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id");
+ assertEquals("200", status);
+ assertEquals(TestId, "test1");
+ } catch (Exception e) {
+ //if local ssh is not enabled
+ System.out.print(e.getMessage());
+ }
+ }
+
+ @Test
+ public void reqExecCommand_shouldSetSuccessRealSLSCommand() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("HostName", "<IP>");
+ params.put("Port", "2222");
+ params.put("User", "root");
+ params.put("Password", "vagrant");
+ params.put("Id", "test1");
+ params.put("Cmd", "salt '*' test.ping --out=json --static");
+ params.put("SlsExec", "false");
+ params.put("Timeout", "120");
+
+ adapter = new SaltstackAdapterImpl();
+ try {
+ adapter.reqExecCommand(params, svcContext);
+ String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code");
+ TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id");
+ assertEquals("200", status);
+ assertEquals(TestId, "test1");
+ TestId = svcContext.getAttribute("test1.minion1");
+ assertEquals(TestId, "true");
+ } catch (Exception e) {
+ //if saltstack ssh IP is not enabled
+ System.out.print(e.getMessage());
+ }
+ }
+
+ @Test
+ public void reqExecCommand_shouldSetSuccessRealCommand() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("HostName", "<IP>");
+ params.put("Port", "2222");
+ params.put("User", "root");
+ params.put("Password", "vagrant");
+ params.put("Id", "test1");
+ params.put("Cmd", "cd /srv/salt/; salt '*' state.apply vim --out=json --static");
+ params.put("SlsExec", "true");
+ params.put("Timeout", "120");
+
+ adapter = new SaltstackAdapterImpl();
+ try {
+ adapter.reqExecCommand(params, svcContext);
+ String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code");
+ TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id");
+ assertEquals("200", status);
+ assertEquals(TestId, "test1");
+ } catch (Exception e) {
+ //if saltstack ssh IP is not enabled
+ System.out.print(e.getMessage());
+ }
+ }
+
+ @Test
+ public void reqExecCommand_shouldSetSuccessRealSSL() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("HostName", "<IP>");
+ params.put("Port", "2222");
+ params.put("User", "root");
+ params.put("Password", "vagrant");
+ params.put("Id", "test1");
+ params.put("SlsName", "vim");
+ params.put("Timeout", "120");
+ params.put("NodeList", "minion1");
+
+ adapter = new SaltstackAdapterImpl();
+ try {
+ adapter.reqExecSLS(params, svcContext);
+ String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code");
+ TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id");
+ assertEquals("200", status);
+ assertEquals(TestId, "test1");
+ } catch (Exception e) {
+ //if saltstack ssh IP is not enabled
+ System.out.print(e.getMessage());
+ }
+ }
+
+ @Test
+ public void reqExecCommand_shouldSetSuccessEnvParam() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("HostName", "<IP>");
+ params.put("Port", "2222");
+ params.put("User", "root");
+ params.put("Password", "vagrant");
+ params.put("Id", "test1");
+ params.put("SlsName", "vim");
+ params.put("Timeout", "120");
+ params.put("NodeList", "minion1");
+ params.put("EnvParameters", "{\"exclude\": bar*}");
+
+ adapter = new SaltstackAdapterImpl();
+ try {
+ adapter.reqExecSLS(params, svcContext);
+ String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code");
+ TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id");
+ assertEquals("200", status);
+ assertEquals(TestId, "test1");
+ } catch (Exception e) {
+ //if saltstack ssh IP is not enabled
+ System.out.print(e.getMessage());
+ }
+ }
+
+ @Test
+ public void reqExecCommand_shouldSetSuccessFileParam() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("HostName", "<IP>");
+ params.put("Port", "2222");
+ params.put("User", "root");
+ params.put("Password", "vagrant");
+ params.put("Id", "test1");
+ params.put("SlsName", "vim");
+ params.put("Timeout", "120");
+ params.put("NodeList", "minion1");
+ params.put("EnvParameters", "{\"exclude\": \"bar,baz\"}");
+ params.put("FileParameters", "{\"config.txt\":\"db_ip=10.1.1.1, sip_timer=10000\"}");
+
+ adapter = new SaltstackAdapterImpl();
+ try {
+ adapter.reqExecSLS(params, svcContext);
+ String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code");
+ TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id");
+ assertEquals("200", status);
+ assertEquals(TestId, "test1");
+ } catch (Exception e) {
+ //if saltstack ssh IP is not enabled
+ System.out.print(e.getMessage());
+ }
+ }
+
+ @Test
+ public void reqExecCommand_shouldSetSuccessPillarParam() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("HostName", "<IP>");
+ params.put("Port", "2222");
+ params.put("User", "root");
+ params.put("Password", "vagrant");
+ params.put("Id", "test1");
+ params.put("SlsName", "vim");
+ params.put("Timeout", "120");
+ params.put("NodeList", "minion1");
+ params.put("EnvParameters", "{\"exclude\": \"bar,baz\", \"pillar\":\"'{\\\"foo\\\": \\\"bar\\\"}'\"}");
+ params.put("FileParameters", "{\"config.txt\":\"db_ip=10.1.1.1, sip_timer=10000\"}");
+
+ adapter = new SaltstackAdapterImpl();
+ try {
+ adapter.reqExecSLS(params, svcContext);
+ String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code");
+ TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id");
+ assertEquals("200", status);
+ assertEquals(TestId, "test1");
+ } catch (Exception e) {
+ //if saltstack ssh IP is not enabled
+ System.out.print(e.getMessage());
+ }
+ }
+
+ @Test
+ public void reqExecCommand_shouldSetSuccessMultiFileParam() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("HostName", "<IP>");
+ params.put("Port", "2222");
+ params.put("User", "root");
+ params.put("Password", "vagrant");
+ params.put("Id", "test1");
+ params.put("SlsName", "vim");
+ params.put("Timeout", "120");
+ params.put("NodeList", "minion1");
+ params.put("EnvParameters", "{\"exclude\": bar*}");
+ params.put("FileParameters", "{\"config.txt\":\"db_ip=10.1.1.1, sip_timer=10000\" , \"config-tep.txt\":\"db_ip=10.1.1.1, sip_timer=10000\"}");
+
+ adapter = new SaltstackAdapterImpl();
+ try {
+ adapter.reqExecSLS(params, svcContext);
+ String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code");
+ TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id");
+ assertEquals("200", status);
+ assertEquals(TestId, "test1");
+ } catch (Exception e) {
+ //if saltstack ssh IP is not enabled
+ System.out.print(e.getMessage());
+ }
+ }
+
+ @Test
+ public void reqExecCommand_shouldSetSuccessSSLFile() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("HostName", "<IP>");
+ params.put("Port", "2222");
+ params.put("User", "root");
+ params.put("Password", "vagrant");
+ params.put("Id", "test1");
+ params.put("Timeout", "120");
+ params.put("NodeList", "minion1");
+ params.put("SlsFile", "src/test/resources/config.sls");
+
+ adapter = new SaltstackAdapterImpl();
+ try {
+ adapter.reqExecSLSFile(params, svcContext);
+ String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code");
+ TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id");
+ assertEquals("200", status);
+ assertEquals(TestId, "test1");
+ } catch (Exception e) {
+ //if saltstack ssh IP is not enabled
+ System.out.print(e.getMessage());
+ }
+ }
+
+ @Test
+ public void reqExecCommand_shouldSetSuccessSSLFileMultiFileParam() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("HostName", "<IP>");
+ params.put("Port", "2222");
+ params.put("User", "root");
+ params.put("Password", "vagrant");
+ params.put("Id", "test1");
+ params.put("Timeout", "120");
+ params.put("NodeList", "minion1");
+ params.put("SlsFile", "src/test/resources/config.sls");
+ params.put("EnvParameters", "{\"exclude\": bar, \"pillar\":\"'{\\\"foo\\\": \\\"bar\\\"}'\"}");
+ params.put("FileParameters", "{\"config.txt\":\"db_ip=10.1.1.1, sip_timer=10000\" , \"config-tep.txt\":\"db_ip=10.1.1.1, sip_timer=10000\"}");
+
+ adapter = new SaltstackAdapterImpl();
+ try {
+ adapter.reqExecSLSFile(params, svcContext);
+ String status = svcContext.getAttribute("org.onap.appc.adapter.saltstack.result.code");
+ TestId = svcContext.getAttribute("org.onap.appc.adapter.saltstack.Id");
+ assertEquals("200", status);
+ assertEquals(TestId, "test1");
+ } catch (Exception e) {
+ //if saltstack ssh IP is not enabled
+ System.out.print(e.getMessage());
+ }
+ }
+}
diff --git a/adaptors/saltstack-adapter/saltstack-adapter-provider/src/test/java/org/onap/ccsdk/adapter/impl/TestSaltstackAdapterPropertiesProviderImpl.java b/adaptors/saltstack-adapter/saltstack-adapter-provider/src/test/java/org/onap/ccsdk/adapter/impl/TestSaltstackAdapterPropertiesProviderImpl.java
new file mode 100644
index 000000000..88acc1919
--- /dev/null
+++ b/adaptors/saltstack-adapter/saltstack-adapter-provider/src/test/java/org/onap/ccsdk/adapter/impl/TestSaltstackAdapterPropertiesProviderImpl.java
@@ -0,0 +1,310 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Samsung Electronics. All rights reserved.
+ * ================================================================================
+ *
+ * =============================================================================
+ * 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.
+ *
+ *
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.adapter.impl;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.onap.ccsdk.sli.adaptors.saltstack.SaltstackAdapterPropertiesProvider;
+import org.onap.ccsdk.sli.adaptors.saltstack.impl.SaltstackAdapterImpl;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+
+import java.util.Properties;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+public class TestSaltstackAdapterPropertiesProviderImpl {
+
+ private SaltstackAdapterImpl adapter;
+ private Properties params;
+
+
+ @Before
+ public void setup() throws IllegalArgumentException {
+ params = new Properties();
+ }
+
+ @After
+ public void tearDown() {
+ adapter = null;
+ params = null;
+ }
+
+ @Test
+ public void reqExecCommand_setPropertiesBasicPortNull() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+ params.put("org.onap.appc.adapter.saltstack.clientType", "BASIC");
+ params.put("User", "test");
+ params.put("Password", "test");
+ SaltstackAdapterPropertiesProvider propProvider = new SaltstackAdapterPropertiesProvider() {
+ @Override
+ public Properties getProperties() {
+ return params;
+ }
+ };
+ adapter = new SaltstackAdapterImpl(propProvider);
+ assertNotNull(propProvider);
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void reqExecCommand_setPropertiesBasicPortString() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+ params.put("org.onap.appc.adapter.saltstack.clientType", "BASIC");
+ params.put("org.onap.appc.adapter.saltstack.host", "test");
+ params.put("org.onap.appc.adapter.saltstack.port", "test");
+ params.put("org.onap.appc.adapter.saltstack.userName", "test");
+ params.put("org.onap.appc.adapter.saltstack.userPasswd", "test");
+ params.put("org.onap.appc.adapter.saltstack.sshKey", "test");
+ SaltstackAdapterPropertiesProvider propProvider = new SaltstackAdapterPropertiesProvider() {
+ @Override
+ public Properties getProperties() {
+ return params;
+ }
+ };
+ adapter = new SaltstackAdapterImpl(propProvider);
+ }
+
+ @Test
+ public void reqExecCommand_setPropertiesBasicSuccess() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+ params.put("org.onap.appc.adapter.saltstack.clientType", "BASIC");
+ params.put("org.onap.appc.adapter.saltstack.host", "test");
+ params.put("org.onap.appc.adapter.saltstack.port", "10");
+ params.put("org.onap.appc.adapter.saltstack.userName", "test");
+ params.put("org.onap.appc.adapter.saltstack.userPasswd", "test");
+ params.put("org.onap.appc.adapter.saltstack.sshKey", "test");
+ SaltstackAdapterPropertiesProvider propProvider = new SaltstackAdapterPropertiesProvider() {
+ @Override
+ public Properties getProperties() {
+ return params;
+ }
+ };
+ adapter = new SaltstackAdapterImpl(propProvider);
+ assertNotNull(adapter);
+ }
+
+ @Test
+ public void reqExecCommand_setPropertiesSSH_CERTPortNull() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+ params.put("org.onap.appc.adapter.saltstack.clientType", "SSH_CERT");
+ params.put("User", "test");
+ params.put("Password", "test");
+ SaltstackAdapterPropertiesProvider propProvider = new SaltstackAdapterPropertiesProvider() {
+ @Override
+ public Properties getProperties() {
+ return params;
+ }
+ };
+ adapter = new SaltstackAdapterImpl(propProvider);
+ assertNotNull(propProvider);
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void reqExecCommand_setPropertiesSSH_CERTPortString() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+ params.put("org.onap.appc.adapter.saltstack.clientType", "SSH_CERT");
+ params.put("org.onap.appc.adapter.saltstack.host", "test");
+ params.put("org.onap.appc.adapter.saltstack.port", "test");
+ params.put("org.onap.appc.adapter.saltstack.userName", "test");
+ params.put("org.onap.appc.adapter.saltstack.userPasswd", "test");
+ params.put("org.onap.appc.adapter.saltstack.sshKey", "test");
+ SaltstackAdapterPropertiesProvider propProvider = new SaltstackAdapterPropertiesProvider() {
+ @Override
+ public Properties getProperties() {
+ return params;
+ }
+ };
+ adapter = new SaltstackAdapterImpl(propProvider);
+ }
+
+ @Test
+ public void reqExecCommand_setPropertiesSSH_CERTSuccess() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+ params.put("org.onap.appc.adapter.saltstack.clientType", "SSH_CERT");
+ params.put("org.onap.appc.adapter.saltstack.host", "test");
+ params.put("org.onap.appc.adapter.saltstack.port", "10");
+ params.put("org.onap.appc.adapter.saltstack.userName", "test");
+ params.put("org.onap.appc.adapter.saltstack.userPasswd", "test");
+ params.put("org.onap.appc.adapter.saltstack.sshKey", "test");
+ SaltstackAdapterPropertiesProvider propProvider = new SaltstackAdapterPropertiesProvider() {
+ @Override
+ public Properties getProperties() {
+ return params;
+ }
+ };
+ adapter = new SaltstackAdapterImpl(propProvider);
+ assertNotNull(propProvider);
+ }
+
+ @Test
+ public void reqExecCommand_setPropertiesBOTHPortNull() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+ params.put("org.onap.appc.adapter.saltstack.clientType", "BOTH");
+ params.put("User", "test");
+ params.put("Password", "test");
+ SaltstackAdapterPropertiesProvider propProvider = new SaltstackAdapterPropertiesProvider() {
+ @Override
+ public Properties getProperties() {
+ return params;
+ }
+ };
+ adapter = new SaltstackAdapterImpl(propProvider);
+ assertNotNull(propProvider);
+ }
+
+ @Test
+ public void reqExecCommand_setPropertiesBOTHSuccess() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+ params.put("org.onap.appc.adapter.saltstack.clientType", "BOTH");
+ params.put("org.onap.appc.adapter.saltstack.host", "test");
+ params.put("org.onap.appc.adapter.saltstack.port", "10");
+ params.put("org.onap.appc.adapter.saltstack.userName", "test");
+ params.put("org.onap.appc.adapter.saltstack.userPasswd", "test");
+ params.put("org.onap.appc.adapter.saltstack.sshKey", "test");
+ SaltstackAdapterPropertiesProvider propProvider = new SaltstackAdapterPropertiesProvider() {
+ @Override
+ public Properties getProperties() {
+ return params;
+ }
+ };
+ adapter = new SaltstackAdapterImpl(propProvider);
+ assertNotNull(propProvider);
+ }
+
+ @Test
+ public void reqExecCommand_setPropertiesNonePortNull() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+ params.put("org.onap.appc.adapter.saltstack.clientType", "NONE");
+ params.put("User", "test");
+ params.put("Password", "test");
+ SaltstackAdapterPropertiesProvider propProvider = new SaltstackAdapterPropertiesProvider() {
+ @Override
+ public Properties getProperties() {
+ return params;
+ }
+ };
+ adapter = new SaltstackAdapterImpl(propProvider);
+ assertNotNull(propProvider);
+ }
+
+ @Test
+ public void reqExecCommand_setPropertiesNonePortString() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+ params.put("org.onap.appc.adapter.saltstack.clientType", "NONE");
+ params.put("org.onap.appc.adapter.saltstack.host", "test");
+ params.put("org.onap.appc.adapter.saltstack.port", "test");
+ params.put("org.onap.appc.adapter.saltstack.userName", "test");
+ params.put("org.onap.appc.adapter.saltstack.userPasswd", "test");
+ params.put("org.onap.appc.adapter.saltstack.sshKey", "test");
+ SaltstackAdapterPropertiesProvider propProvider = new SaltstackAdapterPropertiesProvider() {
+ @Override
+ public Properties getProperties() {
+ return params;
+ }
+ };
+ adapter = new SaltstackAdapterImpl(propProvider);
+ assertNotNull(propProvider);
+ }
+
+ @Test
+ public void reqExecCommand_setPropertiesNoneSuccess() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+ params.put("org.onap.appc.adapter.saltstack.clientType", "NONE");
+ params.put("org.onap.appc.adapter.saltstack.host", "test");
+ params.put("org.onap.appc.adapter.saltstack.port", "10");
+ params.put("org.onap.appc.adapter.saltstack.userName", "test");
+ params.put("org.onap.appc.adapter.saltstack.userPasswd", "test");
+ params.put("org.onap.appc.adapter.saltstack.sshKey", "test");
+ SaltstackAdapterPropertiesProvider propProvider = new SaltstackAdapterPropertiesProvider() {
+ @Override
+ public Properties getProperties() {
+ return params;
+ }
+ };
+ adapter = new SaltstackAdapterImpl(propProvider);
+ assertNotNull(propProvider);
+ }
+
+
+ @Test
+ public void reqExecCommand_setPropertiesElsePortNull() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+ params.put("User", "test");
+ params.put("Password", "test");
+ SaltstackAdapterPropertiesProvider propProvider = new SaltstackAdapterPropertiesProvider() {
+ @Override
+ public Properties getProperties() {
+ return params;
+ }
+ };
+ adapter = new SaltstackAdapterImpl(propProvider);
+ assertNotNull(propProvider);
+ }
+
+ @Test
+ public void reqExecCommand_setPropertiesElsePortString() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+ params.put("org.onap.appc.adapter.saltstack.host", "test");
+ params.put("org.onap.appc.adapter.saltstack.port", "test");
+ params.put("org.onap.appc.adapter.saltstack.userName", "test");
+ params.put("org.onap.appc.adapter.saltstack.userPasswd", "test");
+ params.put("org.onap.appc.adapter.saltstack.sshKey", "test");
+ SaltstackAdapterPropertiesProvider propProvider = new SaltstackAdapterPropertiesProvider() {
+ @Override
+ public Properties getProperties() {
+ return params;
+ }
+ };
+ adapter = new SaltstackAdapterImpl(propProvider);
+ assertNotNull(propProvider);
+ }
+
+ @Test
+ public void reqExecCommand_setPropertiesElseSuccess() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+ params.put("org.onap.appc.adapter.saltstack.host", "test");
+ params.put("org.onap.appc.adapter.saltstack.port", "10");
+ params.put("org.onap.appc.adapter.saltstack.userName", "test");
+ params.put("org.onap.appc.adapter.saltstack.userPasswd", "test");
+ params.put("org.onap.appc.adapter.saltstack.sshKey", "test");
+ SaltstackAdapterPropertiesProvider propProvider = new SaltstackAdapterPropertiesProvider() {
+ @Override
+ public Properties getProperties() {
+ return params;
+ }
+ };
+ adapter = new SaltstackAdapterImpl(propProvider);
+ String adaptorName = adapter.getAdapterName();
+ assertEquals("Saltstack Adapter", adaptorName);
+ }
+
+ @Test
+ public void reqExecCommand_setPropertiesDefault() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+ adapter = new SaltstackAdapterImpl();
+ assertNotNull(adapter);
+ }
+}
diff --git a/adaptors/saltstack-adapter/saltstack-adapter-provider/src/test/java/org/onap/ccsdk/adapter/model/TestJsonParser.java b/adaptors/saltstack-adapter/saltstack-adapter-provider/src/test/java/org/onap/ccsdk/adapter/model/TestJsonParser.java
new file mode 100644
index 000000000..d4eafc1a0
--- /dev/null
+++ b/adaptors/saltstack-adapter/saltstack-adapter-provider/src/test/java/org/onap/ccsdk/adapter/model/TestJsonParser.java
@@ -0,0 +1,76 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Samsung Electronics. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.adapter.model;
+
+import org.codehaus.jettison.json.JSONException;
+import org.junit.Test;
+import org.onap.ccsdk.sli.adaptors.saltstack.model.JsonParser;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import static org.junit.Assert.assertNotNull;
+
+public class TestJsonParser {
+
+ private static final Logger log = LoggerFactory.getLogger(TestJsonParser.class);
+
+ @Test
+ public void test() throws SvcLogicException, IOException, JSONException {
+ BufferedReader in = new BufferedReader(
+ new InputStreamReader(ClassLoader.getSystemResourceAsStream("test.json"))
+ );
+ StringBuilder b = new StringBuilder();
+ String line;
+ while ((line = in.readLine()) != null)
+ b.append(line).append('\n');
+
+ Map<String, String> mm = JsonParser.convertToProperties(b.toString());
+
+ logProperties(mm);
+
+ in.close();
+ assertNotNull(mm);
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void testNullString() throws SvcLogicException, JSONException {
+ JsonParser.convertToProperties(null);
+ }
+
+ private void logProperties(Map<String, String> mm) {
+ List<String> ll = new ArrayList<>();
+ for (Object o : mm.keySet())
+ ll.add((String) o);
+ Collections.sort(ll);
+ log.info("Properties:");
+ for (String name : ll)
+ log.info("--- {}: {}", name, mm.get(name));
+ }
+}
diff --git a/adaptors/saltstack-adapter/saltstack-adapter-provider/src/test/resources/config.sls b/adaptors/saltstack-adapter/saltstack-adapter-provider/src/test/resources/config.sls
new file mode 100644
index 000000000..aff05939b
--- /dev/null
+++ b/adaptors/saltstack-adapter/saltstack-adapter-provider/src/test/resources/config.sls
@@ -0,0 +1,2 @@
+vim:
+ pkg.installed
diff --git a/adaptors/saltstack-adapter/saltstack-adapter-provider/src/test/resources/org/onap/ccsdk/default.properties b/adaptors/saltstack-adapter/saltstack-adapter-provider/src/test/resources/org/onap/ccsdk/default.properties
new file mode 100644
index 000000000..e5650e853
--- /dev/null
+++ b/adaptors/saltstack-adapter/saltstack-adapter-provider/src/test/resources/org/onap/ccsdk/default.properties
@@ -0,0 +1,102 @@
+###
+# ============LICENSE_START=======================================================
+# ONAP : CCSDK
+# ================================================================================
+# Copyright (C) 2018 Samsung Electronics. All rights reserved.
+# ================================================================================
+#
+# =============================================================================
+# 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.
+#
+#
+# ============LICENSE_END=========================================================
+###
+#
+# Default properties for the APP-C Provider Adapter
+#
+# -------------------------------------------------------------------------------------------------
+#
+# Define the name and path of any user-provided configuration (bootstrap) file that can be loaded
+# to supply configuration options
+org.onap.appc.bootstrap.file=appc.properties
+org.onap.appc.bootstrap.path=/opt/onap/appc/data/properties,${user.home},.
+appc.application.name=APPC
+#
+# Define the message resource bundle name to be loaded
+org.onap.appc.resources=org/onap/appc/i18n/MessageResources
+#
+# The name of the adapter.
+org.onap.appc.provider.adaptor.name=org.onap.appc.appc_provider_adapter
+#
+# Set up the logging environment
+#
+org.onap.appc.logging.file=org/onap/appc/logback.xml
+org.onap.appc.logging.path=${user.home};etc;../etc
+org.onap.appc.logger=org.onap.appc
+org.onap.appc.security.logger=org.onap.appc.security
+#
+# The minimum and maximum provider/tenant context pool sizes. Min=1 means that as soon
+# as the provider/tenant is referenced a Context is opened and added to the pool. Max=0
+# means that the upper bound on the pool is unbounded.
+org.onap.appc.provider.min.pool=1
+org.onap.appc.provider.max.pool=0
+#
+# The following properties are used to configure the retry logic for connection to the
+# IaaS provider(s). The retry delay property is the amount of time, in seconds, the
+# application waits between retry attempts. The retry limit is the number of retries
+# that are allowed before the request is failed.
+org.onap.appc.provider.retry.delay=30
+org.onap.appc.provider.retry.limit=10
+#
+# The trusted hosts list for SSL access when a certificate is not provided.
+#
+provider.trusted.hosts=*
+#
+# The amount of time, in seconds, to wait for a server state change (start->stop, stop->start, etc).
+# If the server does not change state to a valid state within the alloted time, the operation
+# fails.
+org.onap.appc.server.state.change.timeout=300
+#
+# The amount of time to wait, in seconds, between subsequent polls to the OpenStack provider
+# to refresh the status of a resource we are waiting on.
+#
+org.onap.appc.openstack.poll.interval=20
+#
+# The connection information to connect to the provider we are using. These properties
+# are "structured" properties, in that the name is a compound name, where the nodes
+# of the name can be ordered (1, 2, 3, ...). All of the properties with the same ordinal
+# position are defining the same entity. For example, provider1.type and provider1.name
+# are defining the same provider, whereas provider2.name and provider2.type are defining
+# the values for a different provider. Any number of providers can be defined in this
+# way.
+#
+# Don't change these 2 right now since they are hard coded in the DG
+#provider1.type=appc
+#provider1.name=appc
+#These you can change
+#provider1.identity=appc
+#provider1.tenant1.name=appc
+#provider1.tenant1.userid=appc
+#provider1.tenant1.password=appc
+# After a change to the provider make sure to recheck these values with an api call to provider1.identity/tokens
+test.expected-regions=1
+test.expected-endpoints=1
+#Your OpenStack IP
+#test.ip=192.168.1.2
+# Your OpenStack Platform's Keystone Port (default is 5000)
+#test.port=5000
+#test.tenantid=abcde12345fghijk6789lmnopq123rst
+#test.vmid=abc12345-1234-5678-890a-abcdefg12345
+# Port 8774 below is default port for OpenStack's Nova API Service
+#test.url=http://192.168.1.2:8774/v2/abcde12345fghijk6789lmnopq123rst/servers/abc12345-1234-5678-890a-abcdefg12345
+
diff --git a/adaptors/saltstack-adapter/saltstack-adapter-provider/src/test/resources/test b/adaptors/saltstack-adapter/saltstack-adapter-provider/src/test/resources/test
new file mode 100644
index 000000000..dec578bd9
--- /dev/null
+++ b/adaptors/saltstack-adapter/saltstack-adapter-provider/src/test/resources/test
@@ -0,0 +1,30 @@
+operational-data.avpn-ip-port-information.port-level-cos.queueing.pe-egress-class-queueing-policing-codes.cos2v-queueing-code = P
+operational-data.avpn-ip-port-information.port-level-cos.queueing.pe-egress-class-queueing-policing-codes.cos3-queueing-code = W
+operational-data.avpn-ip-port-information.port-level-cos.queueing.pe-per-class-queueing-behaviors.cos2-queueing = WRED
+operational-data.avpn-ip-port-information.port-level-cos.queueing.pe-per-class-queueing-behaviors.cos2v-queueing = QueueLimit
+operational-data.avpn-ip-port-information.port-level-cos.queueing.pe-per-class-queueing-behaviors.cos3-queueing = WRED
+operational-data.avpn-ip-port-information.port-level-cos.shaping.pe-egress-per-class-shaping-behaviors.cos2-shaping = Disable
+operational-data.avpn-ip-port-information.port-level-cos.shaping.pe-egress-per-class-shaping-behaviors.cos2v-shaping = Enable
+operational-data.avpn-ip-port-information.port-level-cos.shaping.pe-egress-per-class-shaping-behaviors.cos3-shaping = Disable
+operational-data.avpn-ip-port-information.port-level-cos.shaping.pe-egress-per-class-shaping-codes.cos2-shaping-code = W
+operational-data.avpn-ip-port-information.port-level-cos.shaping.pe-egress-per-class-shaping-codes.cos2v-shaping-code = P
+service-configuration-notification-input.ack-final-indicator = Y
+service-configuration-notification-input.response-code = 0
+service-configuration-notification-input.response-message = Plc Activation Failed: Device gblond2005me6 Sync-from Failed. Please check device IP address and NCS setup.
+service-configuration-notification-input.service-information.service-instance-id = TEST7
+service-configuration-notification-input.service-information.service-type = AVPN
+service-configuration-notification-input.svc-request-id = TEST7
+service-data.avpn-ip-port-information.avpn-access-information.access-circuit-id = DHEC.54831.170.ATI
+service-data.avpn-ip-port-information.avpn-access-information.access-interface = _1G
+service-data.avpn-ip-port-information.avpn-access-information.access-speed = 10000
+service-data.avpn-ip-port-information.avpn-access-information.access-speed-units = Kbps
+service-data.avpn-ip-port-information.avpn-access-information.l1-customer-handoff = _1000BASELX
+service-data.avpn-ip-port-information.avpn-access-information.managed-ce = N
+service-data.avpn-ip-port-information.avpn-access-information.vlan-tag-control = _1Q
+service-data.avpn-ip-port-information.clli = LONDENEH
+service-data.avpn-ip-port-information.contracted-port-speed = 10000
+service-data.avpn-ip-port-information.contracted-port-speed-units = Kbps
+service-data.avpn-ip-port-information.endpoint-information.bundle-id = 33
+service-data.avpn-ip-port-information.endpoint-information.interface-string = ae0
+service-data.service-information.service-instance-id = ICORESITE-2751508
+service-data.service-information.service-type = AVPN
diff --git a/adaptors/saltstack-adapter/saltstack-adapter-provider/src/test/resources/test-invalid.json b/adaptors/saltstack-adapter/saltstack-adapter-provider/src/test/resources/test-invalid.json
new file mode 100644
index 000000000..d16bfccdf
--- /dev/null
+++ b/adaptors/saltstack-adapter/saltstack-adapter-provider/src/test/resources/test-invalid.json
@@ -0,0 +1,29 @@
+"equipment-data": [
+{
+"server-count": "4",
+"max-server-speed": "1600000",
+"number-primary-servers": "2",
+"equipment-id": "Server1",
+"server-model": "Unknown",
+"server-id": "Server1",
+"test-node": {
+"test-inner-node": "Test-Value"
+}
+}
+],
+"resource-state": {
+"threshold-value": "1600000",
+"last-added": "1605000",
+"used": "1605000",
+"limit-value": "1920000"
+},
+"resource-rule": {
+"endpoint-position": "VCE-Cust",
+"soft-limit-expression": "0.6 * max-server-speed * number-primary-servers",
+"resource-name": "Bandwidth",
+"service-model": "DUMMY",
+"hard-limit-expression": "max-server-speed * number-primary-servers",
+"equipment-level": "Server"
+},
+"message": "The provisioned access bandwidth is at or exceeds 50% of the total server capacity."
+}
diff --git a/adaptors/saltstack-adapter/saltstack-adapter-provider/src/test/resources/test-sls.json b/adaptors/saltstack-adapter/saltstack-adapter-provider/src/test/resources/test-sls.json
new file mode 100644
index 000000000..bc1c10c8d
--- /dev/null
+++ b/adaptors/saltstack-adapter/saltstack-adapter-provider/src/test/resources/test-sls.json
@@ -0,0 +1,35 @@
+{
+ "minion1": {
+ "retcode": 0,
+ "pkg_|-install_network_packages_|-install_network_packages_|-installed": {
+ "comment": "The following packages were installed/updated: lftp\nThe following packages were already installed: rsync, curl",
+ "name": "install_network_packages",
+ "start_time": "08:47:16.061765",
+ "result": true,
+ "duration": 11086.334,
+ "__run_num__": 0,
+ "__sls__": "nettools",
+ "changes": {
+ "lftp": {
+ "new": "4.6.3a-1build2",
+ "old": ""
+ }
+ },
+ "__id__": "install_network_packages"
+ }
+ },
+ "minion2": {
+ "retcode": 0,
+ "pkg_|-install_network_packages_|-install_network_packages_|-installed": {
+ "comment": "All specified packages are already installed",
+ "name": "curl",
+ "start_time": "08:47:16.152099",
+ "result": true,
+ "duration": 426.493,
+ "__run_num__": 0,
+ "__sls__": "nettools",
+ "changes": {},
+ "__id__": "install_network_packages"
+ }
+ }
+}
diff --git a/adaptors/saltstack-adapter/saltstack-adapter-provider/src/test/resources/test.json b/adaptors/saltstack-adapter/saltstack-adapter-provider/src/test/resources/test.json
new file mode 100644
index 000000000..81131d6f4
--- /dev/null
+++ b/adaptors/saltstack-adapter/saltstack-adapter-provider/src/test/resources/test.json
@@ -0,0 +1,30 @@
+{
+ "equipment-data": [
+ {
+ "server-count": "4",
+ "max-server-speed": "1600000",
+ "number-primary-servers": "2",
+ "equipment-id": "Server1",
+ "server-model": "Unknown",
+ "server-id": "Server1",
+ "test-node": {
+ "test-inner-node": "Test-Value"
+ }
+ }
+ ],
+ "resource-state": {
+ "threshold-value": "1600000",
+ "last-added": "1605000",
+ "used": "1605000",
+ "limit-value": "1920000"
+ },
+ "resource-rule": {
+ "endpoint-position": "VCE-Cust",
+ "soft-limit-expression": "0.6 * max-server-speed * number-primary-servers",
+ "resource-name": "Bandwidth",
+ "service-model": "DUMMY",
+ "hard-limit-expression": "max-server-speed * number-primary-servers",
+ "equipment-level": "Server"
+ },
+ "message": "The provisioned access bandwidth is at or exceeds 50% of the total server capacity."
+}
diff --git a/adaptors/saltstack-adapter/saltstack-adapter-provider/src/test/resources/test.sls b/adaptors/saltstack-adapter/saltstack-adapter-provider/src/test/resources/test.sls
new file mode 100644
index 000000000..cd76486aa
--- /dev/null
+++ b/adaptors/saltstack-adapter/saltstack-adapter-provider/src/test/resources/test.sls
@@ -0,0 +1,30 @@
+{
+ "equipment-data": [
+ {
+ "server-count": "4",
+ "max-server-speed": "1600000",
+ "number-primary-servers": "2",
+ "equipment-id": "Server1",
+ "server-model": "Unknown",
+ "server-id": "Server1",
+ "test-node" : {
+ "test-inner-node" : "Test-Value"
+ }
+ }
+ ],
+ "resource-state": {
+ "threshold-value": "1600000",
+ "last-added": "1605000",
+ "used": "1605000",
+ "limit-value": "1920000"
+ },
+ "resource-rule": {
+ "endpoint-position": "VCE-Cust",
+ "soft-limit-expression": "0.6 * max-server-speed * number-primary-servers",
+ "resource-name": "Bandwidth",
+ "service-model": "DUMMY",
+ "hard-limit-expression": "max-server-speed * number-primary-servers",
+ "equipment-level": "Server"
+ },
+ "message": "The provisioned access bandwidth is at or exceeds 50% of the total server capacity."
+}
diff --git a/adaptors/saltstack-adapter/saltstack-adapter-provider/src/test/resources/test.txt b/adaptors/saltstack-adapter/saltstack-adapter-provider/src/test/resources/test.txt
new file mode 100644
index 000000000..dec578bd9
--- /dev/null
+++ b/adaptors/saltstack-adapter/saltstack-adapter-provider/src/test/resources/test.txt
@@ -0,0 +1,30 @@
+operational-data.avpn-ip-port-information.port-level-cos.queueing.pe-egress-class-queueing-policing-codes.cos2v-queueing-code = P
+operational-data.avpn-ip-port-information.port-level-cos.queueing.pe-egress-class-queueing-policing-codes.cos3-queueing-code = W
+operational-data.avpn-ip-port-information.port-level-cos.queueing.pe-per-class-queueing-behaviors.cos2-queueing = WRED
+operational-data.avpn-ip-port-information.port-level-cos.queueing.pe-per-class-queueing-behaviors.cos2v-queueing = QueueLimit
+operational-data.avpn-ip-port-information.port-level-cos.queueing.pe-per-class-queueing-behaviors.cos3-queueing = WRED
+operational-data.avpn-ip-port-information.port-level-cos.shaping.pe-egress-per-class-shaping-behaviors.cos2-shaping = Disable
+operational-data.avpn-ip-port-information.port-level-cos.shaping.pe-egress-per-class-shaping-behaviors.cos2v-shaping = Enable
+operational-data.avpn-ip-port-information.port-level-cos.shaping.pe-egress-per-class-shaping-behaviors.cos3-shaping = Disable
+operational-data.avpn-ip-port-information.port-level-cos.shaping.pe-egress-per-class-shaping-codes.cos2-shaping-code = W
+operational-data.avpn-ip-port-information.port-level-cos.shaping.pe-egress-per-class-shaping-codes.cos2v-shaping-code = P
+service-configuration-notification-input.ack-final-indicator = Y
+service-configuration-notification-input.response-code = 0
+service-configuration-notification-input.response-message = Plc Activation Failed: Device gblond2005me6 Sync-from Failed. Please check device IP address and NCS setup.
+service-configuration-notification-input.service-information.service-instance-id = TEST7
+service-configuration-notification-input.service-information.service-type = AVPN
+service-configuration-notification-input.svc-request-id = TEST7
+service-data.avpn-ip-port-information.avpn-access-information.access-circuit-id = DHEC.54831.170.ATI
+service-data.avpn-ip-port-information.avpn-access-information.access-interface = _1G
+service-data.avpn-ip-port-information.avpn-access-information.access-speed = 10000
+service-data.avpn-ip-port-information.avpn-access-information.access-speed-units = Kbps
+service-data.avpn-ip-port-information.avpn-access-information.l1-customer-handoff = _1000BASELX
+service-data.avpn-ip-port-information.avpn-access-information.managed-ce = N
+service-data.avpn-ip-port-information.avpn-access-information.vlan-tag-control = _1Q
+service-data.avpn-ip-port-information.clli = LONDENEH
+service-data.avpn-ip-port-information.contracted-port-speed = 10000
+service-data.avpn-ip-port-information.contracted-port-speed-units = Kbps
+service-data.avpn-ip-port-information.endpoint-information.bundle-id = 33
+service-data.avpn-ip-port-information.endpoint-information.interface-string = ae0
+service-data.service-information.service-instance-id = ICORESITE-2751508
+service-data.service-information.service-type = AVPN
diff --git a/adaptors/saltstack-adapter/saltstack-directed-graphs-sample/reqExecCommand/APPC_saltstack-adapter-1.0-exe-nonSLS.json b/adaptors/saltstack-adapter/saltstack-directed-graphs-sample/reqExecCommand/APPC_saltstack-adapter-1.0-exe-nonSLS.json
new file mode 100644
index 000000000..562c24ad3
--- /dev/null
+++ b/adaptors/saltstack-adapter/saltstack-directed-graphs-sample/reqExecCommand/APPC_saltstack-adapter-1.0-exe-nonSLS.json
@@ -0,0 +1,203 @@
+[
+ {
+ "id": "d86e7ee4.ee3f1",
+ "type": "method",
+ "name": "saltstack-adapter-1.0",
+ "xml": "<method rpc='saltstack-adapter-1.0-exe-nonSLS' mode='sync'>\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 492,
+ "y": 216,
+ "z": "5945fc3c.78efc4",
+ "wires": [
+ [
+ "38662e01.1d3c22"
+ ]
+ ]
+ },
+ {
+ "id": "9997883e.ec9028",
+ "type": "service-logic",
+ "name": "APPC 2.0.1",
+ "module": "APPC",
+ "version": "2.0.1",
+ "comments": "",
+ "xml": "<service-logic xmlns='http://www.onap.org/sdnc/svclogic' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xsi:schemaLocation='http://www.onap.org/sdnc/svclogic ./svclogic.xsd' module='APPC' version='2.0.1'>",
+ "outputs": 1,
+ "x": 283,
+ "y": 289,
+ "z": "5945fc3c.78efc4",
+ "wires": [
+ [
+ "d86e7ee4.ee3f1"
+ ]
+ ]
+ },
+ {
+ "id": "d40bf650.8338e8",
+ "type": "returnFailure",
+ "name": "return failure",
+ "xml": "<return status='failure'>\n<parameter name='error-code' value='200' />\n<parameter name='error-message' value='`$org.openecomp.appc.adapter.saltstack.message`' />\n<parameter name='output.status.results' value='`$org.openecomp.appc.adapter.saltstack.results`' />\n",
+ "comments": "",
+ "x": 1007,
+ "y": 373,
+ "z": "5945fc3c.78efc4",
+ "wires": []
+ },
+ {
+ "id": "38662e01.1d3c22",
+ "type": "execute",
+ "name": "execute",
+ "xml": "<execute plugin='org.openecomp.appc.adapter.saltstack.SaltstackAdapter' method='reqExecCommand' >\n <parameter name='HostName' value='`$AgentUrl`'/>\n <parameter name='Port' value='`$Port`'/>\n <parameter name='User' value='`$User`'/>\n <parameter name='Password' value='`$Password`'/>\n <parameter name='Id' value='test1'/>\n <parameter name='Cmd' value='cd /srv/salt; ls -l'/>\n <parameter name='SlsExec' value='false'/>\n <parameter name='Timeout' value='`$Timeout`'/>\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 700,
+ "y": 212,
+ "z": "5945fc3c.78efc4",
+ "wires": [
+ [
+ "7b75e382.6344dc",
+ "6f108926.d7baf8"
+ ]
+ ]
+ },
+ {
+ "id": "24fb9f79.a6c6c",
+ "type": "switchNode",
+ "name": "switch",
+ "xml": "<switch test=\"`$org.onap.appc.adapter.saltstack.result.code`\">\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 486,
+ "y": 372,
+ "z": "5945fc3c.78efc4",
+ "wires": [
+ [
+ "c526c44.c850738",
+ "9c394980.2a56a8"
+ ]
+ ]
+ },
+ {
+ "id": "c526c44.c850738",
+ "type": "other",
+ "name": "outcome",
+ "xml": "<outcome value='Other'>\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 675,
+ "y": 371,
+ "z": "5945fc3c.78efc4",
+ "wires": [
+ [
+ "d40bf650.8338e8"
+ ]
+ ]
+ },
+ {
+ "id": "7b75e382.6344dc",
+ "type": "failure",
+ "name": "failure",
+ "xml": "<outcome value='failure'>\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 951,
+ "y": 210,
+ "z": "5945fc3c.78efc4",
+ "wires": [
+ [
+ "d40bf650.8338e8"
+ ]
+ ]
+ },
+ {
+ "id": "6f108926.d7baf8",
+ "type": "other",
+ "name": "other",
+ "xml": "<outcome value='Other'>\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 298,
+ "y": 378,
+ "z": "5945fc3c.78efc4",
+ "wires": [
+ [
+ "24fb9f79.a6c6c"
+ ]
+ ]
+ },
+ {
+ "id": "9c394980.2a56a8",
+ "type": "success",
+ "name": "success",
+ "xml": "<outcome value='200'>\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 667,
+ "y": 460,
+ "z": "5945fc3c.78efc4",
+ "wires": [
+ [
+ "1f81a3db.54cd1c"
+ ]
+ ]
+ },
+ {
+ "id": "1f81a3db.54cd1c",
+ "type": "returnSuccess",
+ "name": "return success",
+ "xml": "<return status='success'>\n<parameter name='output.status.code' value='`$org.openecomp.appc.adapter.saltstack.result.code`' />\n<parameter name='output.status.message' value='`$org.openecomp.appc.adapter.saltstack.message`'/>\n<parameter name='output.status.results' value = '`$org.openecomp.appc.adapter.saltstack.results`'/>\n",
+ "comments": "",
+ "x": 887,
+ "y": 460,
+ "z": "5945fc3c.78efc4",
+ "wires": []
+ },
+ {
+ "id": "fcad80f8.ba2d9",
+ "type": "dgstart",
+ "name": "DGSTART",
+ "outputs": 1,
+ "x": 261,
+ "y": 189,
+ "z": "5945fc3c.78efc4",
+ "wires": [
+ [
+ "9997883e.ec9028"
+ ]
+ ]
+ },
+ {
+ "id": "b86e624d.49f0f",
+ "type": "comment",
+ "name": "SaltStack Adaptor DG",
+ "info": "",
+ "comments": "",
+ "x": 630,
+ "y": 75,
+ "z": "5945fc3c.78efc4",
+ "wires": []
+ },
+ {
+ "id": "83c0578d.061f98",
+ "type": "comment",
+ "name": "request-method = reqExecCommand, req-action = \"execute a single non SLS command\"",
+ "info": "",
+ "comments": "",
+ "x": 650,
+ "y": 155,
+ "z": "5945fc3c.78efc4",
+ "wires": []
+ },
+ {
+ "id": "f104feb6.558f7",
+ "type": "comment",
+ "name": "Assumptions for this DG",
+ "info": "Here we assume, the saltstack server is the example-vagrant based server. Where, the master saltstact controlls minion1 and minion2. ",
+ "comments": "",
+ "x": 627,
+ "y": 115,
+ "z": "5945fc3c.78efc4",
+ "wires": []
+ }
+] \ No newline at end of file
diff --git a/adaptors/saltstack-adapter/saltstack-directed-graphs-sample/reqExecCommand/APPC_saltstack-adapter-1.0-exe-nonSLS.xml b/adaptors/saltstack-adapter/saltstack-directed-graphs-sample/reqExecCommand/APPC_saltstack-adapter-1.0-exe-nonSLS.xml
new file mode 100644
index 000000000..6fbbe5b1f
--- /dev/null
+++ b/adaptors/saltstack-adapter/saltstack-directed-graphs-sample/reqExecCommand/APPC_saltstack-adapter-1.0-exe-nonSLS.xml
@@ -0,0 +1,50 @@
+<service-logic xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
+ xmlns='http://www.onap.org/sdnc/svclogic'
+ xsi:schemaLocation='http://www.onap.org/sdnc/svclogic ./svclogic.xsd'
+ module='APPC' version='2.0.1'>
+ <method rpc='saltstack-adapter-1.0-exe-nonSLS' mode='sync'>
+ <execute plugin='org.openecomp.appc.adapter.saltstack.SaltstackAdapter'
+ method='reqExecCommand'>
+ <parameter name='HostName' value='`$AgentUrl`'/>
+ <parameter name='Port' value='`$Port`'/>
+ <parameter name='User' value='`$User`'/>
+ <parameter name='Password' value='`$Password`'/>
+ <parameter name='Id' value='test1'/>
+ <parameter name='Cmd' value='cd /srv/salt; ls -l'/>
+ <parameter name='SlsExec' value='false'/>
+ <parameter name='Timeout' value='`$Timeout`'/>
+ <outcome value='failure'>
+ <return status='failure'>
+ <parameter name='error-code' value='200'/>
+ <parameter name='error-message'
+ value='`$org.openecomp.appc.adapter.saltstack.message`'/>
+ <parameter name='output.status.results'
+ value='`$org.openecomp.appc.adapter.saltstack.results`'/>
+ </return>
+ </outcome>
+ <outcome value='Other'>
+ <switch test="`$org.onap.appc.adapter.saltstack.result.code`">
+ <outcome value='Other'>
+ <return status='failure'>
+ <parameter name='error-code' value='200'/>
+ <parameter name='error-message'
+ value='`$org.openecomp.appc.adapter.saltstack.message`'/>
+ <parameter name='output.status.results'
+ value='`$org.openecomp.appc.adapter.saltstack.results`'/>
+ </return>
+ </outcome>
+ <outcome value='200'>
+ <return status='success'>
+ <parameter name='output.status.code'
+ value='`$org.openecomp.appc.adapter.saltstack.result.code`'/>
+ <parameter name='output.status.message'
+ value='`$org.openecomp.appc.adapter.saltstack.message`'/>
+ <parameter name='output.status.results'
+ value='`$org.openecomp.appc.adapter.saltstack.results`'/>
+ </return>
+ </outcome>
+ </switch>
+ </outcome>
+ </execute>
+ </method>
+</service-logic> \ No newline at end of file
diff --git a/adaptors/saltstack-adapter/saltstack-directed-graphs-sample/reqExecCommand/APPC_saltstack-adapter-1.0-exec-SLSFile.json b/adaptors/saltstack-adapter/saltstack-directed-graphs-sample/reqExecCommand/APPC_saltstack-adapter-1.0-exec-SLSFile.json
new file mode 100644
index 000000000..7f427674b
--- /dev/null
+++ b/adaptors/saltstack-adapter/saltstack-directed-graphs-sample/reqExecCommand/APPC_saltstack-adapter-1.0-exec-SLSFile.json
@@ -0,0 +1,350 @@
+[
+ {
+ "id": "d0ad0305.352fc",
+ "type": "method",
+ "name": "saltstack-adapter-1.0",
+ "xml": "<method rpc='saltstack-adapter-1.0-exec-SLSFile' mode='sync'>\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 552,
+ "y": 183,
+ "z": "b84dc629.83cd08",
+ "wires": [
+ [
+ "65cc87e2.a95188"
+ ]
+ ]
+ },
+ {
+ "id": "22aefec.e8c7902",
+ "type": "service-logic",
+ "name": "APPC 2.0.1",
+ "module": "APPC",
+ "version": "2.0.1",
+ "comments": "",
+ "xml": "<service-logic xmlns='http://www.onap.org/sdnc/svclogic' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xsi:schemaLocation='http://www.onap.org/sdnc/svclogic ./svclogic.xsd' module='APPC' version='2.0.1'>",
+ "outputs": 1,
+ "x": 343,
+ "y": 261,
+ "z": "b84dc629.83cd08",
+ "wires": [
+ [
+ "d0ad0305.352fc"
+ ]
+ ]
+ },
+ {
+ "id": "31587001.4259e",
+ "type": "returnFailure",
+ "name": "return failure",
+ "xml": "<return status='failure'>\n<parameter name='error-code' value='200' />\n<parameter name='error-message' value='`$org.openecomp.appc.adapter.saltstack.message`' />\n<parameter name='output.status.results' value='`$org.openecomp.appc.adapter.saltstack.results`' />\n",
+ "comments": "",
+ "x": 1262,
+ "y": 365,
+ "z": "b84dc629.83cd08",
+ "wires": []
+ },
+ {
+ "id": "65cc87e2.a95188",
+ "type": "execute",
+ "name": "execute",
+ "xml": "<execute plugin='org.openecomp.appc.adapter.saltstack.SaltstackAdapter' method='reqExecCommand' >\n <parameter name='HostName' value='`$AgentUrl`'/>\n <parameter name='Port' value='`$Port`'/>\n <parameter name='User' value='`$User`'/>\n <parameter name='Password' value='`$Password`'/>\n <parameter name='Id' value='test1'/>\n <parameter name='Cmd' value='salt &apos;*&apos; test.ping --out=json --static'/>\n <parameter name='SlsExec' value='false'/>\n <parameter name='Timeout' value='`$Timeout`'/>\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 761,
+ "y": 185,
+ "z": "b84dc629.83cd08",
+ "wires": [
+ [
+ "f9bf6ee7.cf954",
+ "7b51c357.a852cc"
+ ]
+ ]
+ },
+ {
+ "id": "42fa1258.aa570c",
+ "type": "switchNode",
+ "name": "switch",
+ "xml": "<switch test=\"`$org.onap.appc.adapter.saltstack.result.code`\">\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 544,
+ "y": 345,
+ "z": "b84dc629.83cd08",
+ "wires": [
+ [
+ "a7cf236a.84c03",
+ "c45d597b.20b4c8"
+ ]
+ ]
+ },
+ {
+ "id": "a7cf236a.84c03",
+ "type": "other",
+ "name": "other",
+ "xml": "<outcome value='Other'>\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 735,
+ "y": 343,
+ "z": "b84dc629.83cd08",
+ "wires": [
+ [
+ "31587001.4259e"
+ ]
+ ]
+ },
+ {
+ "id": "f9bf6ee7.cf954",
+ "type": "failure",
+ "name": "failure",
+ "xml": "<outcome value='failure'>\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 1011,
+ "y": 182,
+ "z": "b84dc629.83cd08",
+ "wires": [
+ [
+ "31587001.4259e"
+ ]
+ ]
+ },
+ {
+ "id": "7b51c357.a852cc",
+ "type": "other",
+ "name": "other",
+ "xml": "<outcome value='Other'>\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 366,
+ "y": 343,
+ "z": "b84dc629.83cd08",
+ "wires": [
+ [
+ "42fa1258.aa570c"
+ ]
+ ]
+ },
+ {
+ "id": "c45d597b.20b4c8",
+ "type": "success",
+ "name": "success",
+ "xml": "<outcome value='200'>\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 351,
+ "y": 459,
+ "z": "b84dc629.83cd08",
+ "wires": [
+ [
+ "30d5f0f7.0e3c8"
+ ]
+ ]
+ },
+ {
+ "id": "2856792.c401a86",
+ "type": "returnSuccess",
+ "name": "return success",
+ "xml": "<return status='success'>\n<parameter name='output.status.code' value='`$org.openecomp.appc.adapter.saltstack.result.code`' />\n<parameter name='output.status.message' value='`$org.openecomp.appc.adapter.saltstack.message`'/>\n<parameter name='output.status.results' value = '`$org.openecomp.appc.adapter.saltstack.results`'/>\n",
+ "comments": "",
+ "x": 1042,
+ "y": 656,
+ "z": "b84dc629.83cd08",
+ "wires": []
+ },
+ {
+ "id": "6c359fdc.3b566",
+ "type": "dgstart",
+ "name": "DGSTART",
+ "outputs": 1,
+ "x": 321,
+ "y": 161,
+ "z": "b84dc629.83cd08",
+ "wires": [
+ [
+ "22aefec.e8c7902"
+ ]
+ ]
+ },
+ {
+ "id": "b5342c59.29f74",
+ "type": "comment",
+ "name": "SaltStack Adaptor DG",
+ "info": "",
+ "comments": "",
+ "x": 693,
+ "y": 44,
+ "z": "b84dc629.83cd08",
+ "wires": []
+ },
+ {
+ "id": "19202194.8ff55e",
+ "type": "comment",
+ "name": "request-method = reqExecCommand, req-action = \"execute multiple SLS commands\"",
+ "info": "Here we basically test if minion1 is active by pinging to it, then install vim package to it. \n",
+ "comments": "",
+ "x": 711,
+ "y": 127,
+ "z": "b84dc629.83cd08",
+ "wires": []
+ },
+ {
+ "id": "a2ebc17e.fa03a",
+ "type": "other",
+ "name": "other",
+ "xml": "<outcome value='Other'>\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 396,
+ "y": 661,
+ "z": "b84dc629.83cd08",
+ "wires": [
+ [
+ "c9345fbb.d6d19"
+ ]
+ ]
+ },
+ {
+ "id": "770411a5.18825",
+ "type": "execute",
+ "name": "execute",
+ "xml": "<execute plugin='org.openecomp.appc.adapter.saltstack.SaltstackAdapter' method='reqExecCommand' >\n <parameter name='HostName' value='`$AgentUrl`'/>\n <parameter name='Port' value='`$Port`'/>\n <parameter name='User' value='`$User`'/>\n <parameter name='Password' value='`$Password`'/>\n <parameter name='Id' value='test2'/>\n <parameter name='Cmd' value='cd /srv/salt/; salt &apos;minion1&apos; state.apply vim --out=json --static'/>\n <parameter name='SlsExec' value='true'/>\n <parameter name='Timeout' value='`$Timeout`'/>\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 773,
+ "y": 548,
+ "z": "b84dc629.83cd08",
+ "wires": [
+ [
+ "e09a3e12.87428",
+ "a2ebc17e.fa03a"
+ ]
+ ]
+ },
+ {
+ "id": "e09a3e12.87428",
+ "type": "failure",
+ "name": "failure",
+ "xml": "<outcome value='failure'>\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 991,
+ "y": 554,
+ "z": "b84dc629.83cd08",
+ "wires": [
+ [
+ "31587001.4259e"
+ ]
+ ]
+ },
+ {
+ "id": "c9345fbb.d6d19",
+ "type": "switchNode",
+ "name": "switch",
+ "xml": "<switch test=\"`$org.onap.appc.adapter.saltstack.result.code`\">\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 578,
+ "y": 658,
+ "z": "b84dc629.83cd08",
+ "wires": [
+ [
+ "485e453d.36c75c",
+ "f1adcf2a.2c456"
+ ]
+ ]
+ },
+ {
+ "id": "485e453d.36c75c",
+ "type": "other",
+ "name": "other",
+ "xml": "<outcome value='Other'>\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 783,
+ "y": 732,
+ "z": "b84dc629.83cd08",
+ "wires": [
+ [
+ "31587001.4259e"
+ ]
+ ]
+ },
+ {
+ "id": "f1adcf2a.2c456",
+ "type": "success",
+ "name": "success",
+ "xml": "<outcome value='200'>\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 776,
+ "y": 658,
+ "z": "b84dc629.83cd08",
+ "wires": [
+ [
+ "2856792.c401a86"
+ ]
+ ]
+ },
+ {
+ "id": "30d5f0f7.0e3c8",
+ "type": "switchNode",
+ "name": "switch",
+ "xml": "<switch test=\"`$test1.minion1`\">\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 523,
+ "y": 459,
+ "z": "b84dc629.83cd08",
+ "wires": [
+ [
+ "15e9ff68.9812a1",
+ "17d9d7e.4d9a928"
+ ]
+ ]
+ },
+ {
+ "id": "17d9d7e.4d9a928",
+ "type": "other",
+ "name": "outcome",
+ "xml": "<outcome value='true'>\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 593,
+ "y": 550,
+ "z": "b84dc629.83cd08",
+ "wires": [
+ [
+ "770411a5.18825"
+ ]
+ ]
+ },
+ {
+ "id": "15e9ff68.9812a1",
+ "type": "other",
+ "name": "other",
+ "xml": "<outcome value='Other'>\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 717,
+ "y": 459,
+ "z": "b84dc629.83cd08",
+ "wires": [
+ [
+ "31587001.4259e"
+ ]
+ ]
+ },
+ {
+ "id": "b764890c.ed0018",
+ "type": "comment",
+ "name": "Assumptions for this DG (example-server)",
+ "info": "1) Here we assume, the saltstack server is the example-vagrant based server. Where, the master saltstact controlls minion1 and minion2. \n2) We assume that sls file called vim.sls is already present in the path /srv/salt on the server.",
+ "comments": "",
+ "x": 693,
+ "y": 86,
+ "z": "b84dc629.83cd08",
+ "wires": []
+ }
+] \ No newline at end of file
diff --git a/adaptors/saltstack-adapter/saltstack-directed-graphs-sample/reqExecCommand/APPC_saltstack-adapter-1.0-exec-SLSFile.xml b/adaptors/saltstack-adapter/saltstack-directed-graphs-sample/reqExecCommand/APPC_saltstack-adapter-1.0-exec-SLSFile.xml
new file mode 100644
index 000000000..fc63bbd7b
--- /dev/null
+++ b/adaptors/saltstack-adapter/saltstack-directed-graphs-sample/reqExecCommand/APPC_saltstack-adapter-1.0-exec-SLSFile.xml
@@ -0,0 +1,112 @@
+<service-logic xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
+ xmlns='http://www.onap.org/sdnc/svclogic'
+ xsi:schemaLocation='http://www.onap.org/sdnc/svclogic ./svclogic.xsd'
+ module='APPC' version='2.0.1'>
+ <method rpc='saltstack-adapter-1.0-exec-SLSFile' mode='sync'>
+ <execute plugin='org.openecomp.appc.adapter.saltstack.SaltstackAdapter'
+ method='reqExecCommand'>
+ <parameter name='HostName' value='`$AgentUrl`'/>
+ <parameter name='Port' value='`$Port`'/>
+ <parameter name='User' value='`$User`'/>
+ <parameter name='Password' value='`$Password`'/>
+ <parameter name='Id' value='test1'/>
+ <parameter name='Cmd'
+ value='salt &apos;*&apos; test.ping --out=json --static'/>
+ <parameter name='SlsExec' value='false'/>
+ <parameter name='Timeout' value='`$Timeout`'/>
+ <outcome value='failure'>
+ <return status='failure'>
+ <parameter name='error-code' value='200'/>
+ <parameter name='error-message'
+ value='`$org.openecomp.appc.adapter.saltstack.message`'/>
+ <parameter name='output.status.results'
+ value='`$org.openecomp.appc.adapter.saltstack.results`'/>
+ </return>
+ </outcome>
+ <outcome value='Other'>
+ <switch test="`$org.onap.appc.adapter.saltstack.result.code`">
+ <outcome value='Other'>
+ <return status='failure'>
+ <parameter name='error-code' value='200'/>
+ <parameter name='error-message'
+ value='`$org.openecomp.appc.adapter.saltstack.message`'/>
+ <parameter name='output.status.results'
+ value='`$org.openecomp.appc.adapter.saltstack.results`'/>
+ </return>
+ </outcome>
+ <outcome value='200'>
+ <switch test="`$test1.minion1`">
+ <outcome value='Other'>
+ <return status='failure'>
+ <parameter name='error-code' value='200'/>
+ <parameter name='error-message'
+ value='`$org.openecomp.appc.adapter.saltstack.message`'/>
+ <parameter name='output.status.results'
+ value='`$org.openecomp.appc.adapter.saltstack.results`'/>
+ </return>
+ </outcome>
+ <outcome value='true'>
+ <execute
+ plugin='org.openecomp.appc.adapter.saltstack.SaltstackAdapter'
+ method='reqExecCommand'>
+ <parameter name='HostName'
+ value='`$AgentUrl`'/>
+ <parameter name='Port' value='`$Port`'/>
+ <parameter name='User' value='`$User`'/>
+ <parameter name='Password'
+ value='`$Password`'/>
+ <parameter name='Id' value='test2'/>
+ <parameter name='Cmd'
+ value='cd /srv/salt/; salt &apos;minion1&apos; state.apply vim --out=json --static'/>
+ <parameter name='SlsExec' value='true'/>
+ <parameter name='Timeout'
+ value='`$Timeout`'/>
+ <outcome value='failure'>
+ <return status='failure'>
+ <parameter name='error-code'
+ value='200'/>
+ <parameter name='error-message'
+ value='`$org.openecomp.appc.adapter.saltstack.message`'/>
+ <parameter
+ name='output.status.results'
+ value='`$org.openecomp.appc.adapter.saltstack.results`'/>
+ </return>
+ </outcome>
+ <outcome value='Other'>
+ <switch test="`$org.onap.appc.adapter.saltstack.result.code`">
+ <outcome value='200'>
+ <return status='success'>
+ <parameter
+ name='output.status.code'
+ value='`$org.openecomp.appc.adapter.saltstack.result.code`'/>
+ <parameter
+ name='output.status.message'
+ value='`$org.openecomp.appc.adapter.saltstack.message`'/>
+ <parameter
+ name='output.status.results'
+ value='`$org.openecomp.appc.adapter.saltstack.results`'/>
+ </return>
+ </outcome>
+ <outcome value='Other'>
+ <return status='failure'>
+ <parameter name='error-code'
+ value='200'/>
+ <parameter
+ name='error-message'
+ value='`$org.openecomp.appc.adapter.saltstack.message`'/>
+ <parameter
+ name='output.status.results'
+ value='`$org.openecomp.appc.adapter.saltstack.results`'/>
+ </return>
+ </outcome>
+ </switch>
+ </outcome>
+ </execute>
+ </outcome>
+ </switch>
+ </outcome>
+ </switch>
+ </outcome>
+ </execute>
+ </method>
+</service-logic> \ No newline at end of file
diff --git a/adaptors/saltstack-adapter/saltstack-directed-graphs-sample/reqExecCommand/APPC_saltstack-adapter-1.0-exec-multi-sls.json b/adaptors/saltstack-adapter/saltstack-directed-graphs-sample/reqExecCommand/APPC_saltstack-adapter-1.0-exec-multi-sls.json
new file mode 100644
index 000000000..d7cfef01e
--- /dev/null
+++ b/adaptors/saltstack-adapter/saltstack-directed-graphs-sample/reqExecCommand/APPC_saltstack-adapter-1.0-exec-multi-sls.json
@@ -0,0 +1,399 @@
+[
+ {
+ "id": "65f5c0d6.9c4ce",
+ "type": "method",
+ "name": "saltstack-adapter-1.0",
+ "xml": "<method rpc='saltstack-adapter-1.0-exec-multi-sls' mode='sync'>\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 615,
+ "y": 273,
+ "z": "6df02477.0463cc",
+ "wires": [
+ [
+ "c332cb01.51a3e8"
+ ]
+ ]
+ },
+ {
+ "id": "bf71bd6e.1be5b",
+ "type": "service-logic",
+ "name": "APPC 2.0.1",
+ "module": "APPC",
+ "version": "2.0.1",
+ "comments": "",
+ "xml": "<service-logic xmlns='http://www.onap.org/sdnc/svclogic' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xsi:schemaLocation='http://www.onap.org/sdnc/svclogic ./svclogic.xsd' module='APPC' version='2.0.1'>",
+ "outputs": 1,
+ "x": 406,
+ "y": 351,
+ "z": "6df02477.0463cc",
+ "wires": [
+ [
+ "65f5c0d6.9c4ce"
+ ]
+ ]
+ },
+ {
+ "id": "40ce8a6.5f7d174",
+ "type": "returnFailure",
+ "name": "return failure",
+ "xml": "<return status='failure'>\n<parameter name='error-code' value='200' />\n<parameter name='error-message' value='`$org.openecomp.appc.adapter.saltstack.message`' />\n<parameter name='output.status.results' value='`$org.openecomp.appc.adapter.saltstack.results`' />\n",
+ "comments": "",
+ "x": 1325,
+ "y": 455,
+ "z": "6df02477.0463cc",
+ "wires": []
+ },
+ {
+ "id": "c332cb01.51a3e8",
+ "type": "execute",
+ "name": "execute",
+ "xml": "<execute plugin='org.openecomp.appc.adapter.saltstack.SaltstackAdapter' method='reqExecCommand' >\n <parameter name='HostName' value='`$AgentUrl`'/>\n <parameter name='Port' value='`$Port`'/>\n <parameter name='User' value='`$User`'/>\n <parameter name='Password' value='`$Password`'/>\n <parameter name='Id' value='test1'/>\n <parameter name='Cmd' value='salt &apos;*&apos; test.ping --out=json --static'/>\n <parameter name='SlsExec' value='false'/>\n <parameter name='Timeout' value='`$Timeout`'/>\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 824,
+ "y": 275,
+ "z": "6df02477.0463cc",
+ "wires": [
+ [
+ "5b387684.e51be8",
+ "4bb6b32e.adfc2c"
+ ]
+ ]
+ },
+ {
+ "id": "16dfbd4f.b6da73",
+ "type": "switchNode",
+ "name": "switch",
+ "xml": "<switch test=\"`$org.onap.appc.adapter.saltstack.result.code`\">\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 607,
+ "y": 435,
+ "z": "6df02477.0463cc",
+ "wires": [
+ [
+ "24d22f52.ef59a",
+ "ac765880.a6c548"
+ ]
+ ]
+ },
+ {
+ "id": "24d22f52.ef59a",
+ "type": "other",
+ "name": "other",
+ "xml": "<outcome value='Other'>\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 798,
+ "y": 433,
+ "z": "6df02477.0463cc",
+ "wires": [
+ [
+ "40ce8a6.5f7d174"
+ ]
+ ]
+ },
+ {
+ "id": "5b387684.e51be8",
+ "type": "failure",
+ "name": "failure",
+ "xml": "<outcome value='failure'>\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 1074,
+ "y": 272,
+ "z": "6df02477.0463cc",
+ "wires": [
+ [
+ "40ce8a6.5f7d174"
+ ]
+ ]
+ },
+ {
+ "id": "4bb6b32e.adfc2c",
+ "type": "other",
+ "name": "other",
+ "xml": "<outcome value='Other'>\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 429,
+ "y": 433,
+ "z": "6df02477.0463cc",
+ "wires": [
+ [
+ "16dfbd4f.b6da73"
+ ]
+ ]
+ },
+ {
+ "id": "ac765880.a6c548",
+ "type": "success",
+ "name": "success",
+ "xml": "<outcome value='200'>\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 414,
+ "y": 549,
+ "z": "6df02477.0463cc",
+ "wires": [
+ [
+ "2dda30fc.8747"
+ ]
+ ]
+ },
+ {
+ "id": "e45accfe.91615",
+ "type": "returnSuccess",
+ "name": "return success",
+ "xml": "<return status='success'>\n<parameter name='output.status.code' value='`$org.openecomp.appc.adapter.saltstack.result.code`' />\n<parameter name='output.status.message' value='`$org.openecomp.appc.adapter.saltstack.message`'/>\n<parameter name='output.status.results' value = '`$org.openecomp.appc.adapter.saltstack.results`'/>\n",
+ "comments": "",
+ "x": 1345,
+ "y": 757,
+ "z": "6df02477.0463cc",
+ "wires": []
+ },
+ {
+ "id": "11a891ad.55bc1e",
+ "type": "dgstart",
+ "name": "DGSTART",
+ "outputs": 1,
+ "x": 384,
+ "y": 251,
+ "z": "6df02477.0463cc",
+ "wires": [
+ [
+ "bf71bd6e.1be5b"
+ ]
+ ]
+ },
+ {
+ "id": "a56383b.496c48",
+ "type": "comment",
+ "name": "SaltStack Adaptor DG",
+ "info": "",
+ "comments": "",
+ "x": 756,
+ "y": 134,
+ "z": "6df02477.0463cc",
+ "wires": []
+ },
+ {
+ "id": "cfda30b5.5e166",
+ "type": "comment",
+ "name": "request-method = reqExecCommand, req-action = \"execute multiple SLS commands\"",
+ "info": "Here we basically test if minion1 is active by pinging to it, then install vim package to it. \n",
+ "comments": "",
+ "x": 773,
+ "y": 217,
+ "z": "6df02477.0463cc",
+ "wires": []
+ },
+ {
+ "id": "a8efb922.f23ce8",
+ "type": "other",
+ "name": "other",
+ "xml": "<outcome value='Other'>\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 459,
+ "y": 751,
+ "z": "6df02477.0463cc",
+ "wires": [
+ [
+ "3ff32215.20cd0e"
+ ]
+ ]
+ },
+ {
+ "id": "df0c0907.d17838",
+ "type": "execute",
+ "name": "execute",
+ "xml": "<execute plugin='org.openecomp.appc.adapter.saltstack.SaltstackAdapter' method='reqExecCommand' >\n <parameter name='HostName' value='`$AgentUrl`'/>\n <parameter name='Port' value='`$Port`'/>\n <parameter name='User' value='`$User`'/>\n <parameter name='Password' value='`$Password`'/>\n <parameter name='Id' value='test2'/>\n <parameter name='Cmd' value='salt &apos;minion1&apos; pkg.install vim --out=json --static'/>\n <parameter name='SlsExec' value='false'/>\n <parameter name='Timeout' value='`$Timeout`'/>\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 836,
+ "y": 638,
+ "z": "6df02477.0463cc",
+ "wires": [
+ [
+ "1e5bbe2e.9cbb82",
+ "a8efb922.f23ce8"
+ ]
+ ]
+ },
+ {
+ "id": "1e5bbe2e.9cbb82",
+ "type": "failure",
+ "name": "failure",
+ "xml": "<outcome value='failure'>\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 1054,
+ "y": 644,
+ "z": "6df02477.0463cc",
+ "wires": [
+ [
+ "40ce8a6.5f7d174"
+ ]
+ ]
+ },
+ {
+ "id": "3ff32215.20cd0e",
+ "type": "switchNode",
+ "name": "switch",
+ "xml": "<switch test=\"`$org.onap.appc.adapter.saltstack.result.code`\">\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 647,
+ "y": 745,
+ "z": "6df02477.0463cc",
+ "wires": [
+ [
+ "8e2c712b.784b4",
+ "3d74cfe5.d41f5"
+ ]
+ ]
+ },
+ {
+ "id": "8e2c712b.784b4",
+ "type": "other",
+ "name": "other",
+ "xml": "<outcome value='Other'>\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 830,
+ "y": 823,
+ "z": "6df02477.0463cc",
+ "wires": [
+ [
+ "40ce8a6.5f7d174"
+ ]
+ ]
+ },
+ {
+ "id": "3d74cfe5.d41f5",
+ "type": "success",
+ "name": "success",
+ "xml": "<outcome value='200'>\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 829,
+ "y": 758,
+ "z": "6df02477.0463cc",
+ "wires": [
+ [
+ "8313564b.004798"
+ ]
+ ]
+ },
+ {
+ "id": "2dda30fc.8747",
+ "type": "switchNode",
+ "name": "switch",
+ "xml": "<switch test=\"`$test1.minion1`\">\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 586,
+ "y": 549,
+ "z": "6df02477.0463cc",
+ "wires": [
+ [
+ "e0133af5.2ca028",
+ "7f28f521.cf47cc"
+ ]
+ ]
+ },
+ {
+ "id": "7f28f521.cf47cc",
+ "type": "other",
+ "name": "outcome",
+ "xml": "<outcome value='true'>\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 656,
+ "y": 640,
+ "z": "6df02477.0463cc",
+ "wires": [
+ [
+ "df0c0907.d17838"
+ ]
+ ]
+ },
+ {
+ "id": "e0133af5.2ca028",
+ "type": "other",
+ "name": "other",
+ "xml": "<outcome value='Other'>\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 780,
+ "y": 549,
+ "z": "6df02477.0463cc",
+ "wires": [
+ [
+ "40ce8a6.5f7d174"
+ ]
+ ]
+ },
+ {
+ "id": "8313564b.004798",
+ "type": "switchNode",
+ "name": "switch",
+ "xml": "<switch test=\"`$test2.minion1.retcode`\">\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 986,
+ "y": 752,
+ "z": "6df02477.0463cc",
+ "wires": [
+ [
+ "13d18d2d.71fbf3",
+ "2e940add.522a36"
+ ]
+ ]
+ },
+ {
+ "id": "13d18d2d.71fbf3",
+ "type": "other",
+ "name": "other",
+ "xml": "<outcome value='Other'>\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 1165,
+ "y": 825,
+ "z": "6df02477.0463cc",
+ "wires": [
+ [
+ "40ce8a6.5f7d174"
+ ]
+ ]
+ },
+ {
+ "id": "2e940add.522a36",
+ "type": "success",
+ "name": "success",
+ "xml": "<outcome value='0'>\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 1156,
+ "y": 754,
+ "z": "6df02477.0463cc",
+ "wires": [
+ [
+ "e45accfe.91615"
+ ]
+ ]
+ },
+ {
+ "id": "6d6678d2.6a9bd8",
+ "type": "comment",
+ "name": "Assumptions for this DG (example-server)",
+ "info": "Here we assume, the saltstack server is the example-vagrant based server. Where, the master saltstact controlls minion1 and minion2. ",
+ "comments": "",
+ "x": 756,
+ "y": 173,
+ "z": "6df02477.0463cc",
+ "wires": []
+ }
+] \ No newline at end of file
diff --git a/adaptors/saltstack-adapter/saltstack-directed-graphs-sample/reqExecCommand/APPC_saltstack-adapter-1.0-exec-multi-sls.xml b/adaptors/saltstack-adapter/saltstack-directed-graphs-sample/reqExecCommand/APPC_saltstack-adapter-1.0-exec-multi-sls.xml
new file mode 100644
index 000000000..cc36b1ca7
--- /dev/null
+++ b/adaptors/saltstack-adapter/saltstack-directed-graphs-sample/reqExecCommand/APPC_saltstack-adapter-1.0-exec-multi-sls.xml
@@ -0,0 +1,129 @@
+<service-logic xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
+ xmlns='http://www.onap.org/sdnc/svclogic'
+ xsi:schemaLocation='http://www.onap.org/sdnc/svclogic ./svclogic.xsd'
+ module='APPC' version='2.0.1'>
+ <method rpc='saltstack-adapter-1.0-exec-multi-sls' mode='sync'>
+ <execute plugin='org.openecomp.appc.adapter.saltstack.SaltstackAdapter'
+ method='reqExecCommand'>
+ <parameter name='HostName' value='`$AgentUrl`'/>
+ <parameter name='Port' value='`$Port`'/>
+ <parameter name='User' value='`$User`'/>
+ <parameter name='Password' value='`$Password`'/>
+ <parameter name='Id' value='test1'/>
+ <parameter name='Cmd'
+ value='salt &apos;*&apos; test.ping --out=json --static'/>
+ <parameter name='SlsExec' value='false'/>
+ <parameter name='Timeout' value='`$Timeout`'/>
+ <outcome value='failure'>
+ <return status='failure'>
+ <parameter name='error-code' value='200'/>
+ <parameter name='error-message'
+ value='`$org.openecomp.appc.adapter.saltstack.message`'/>
+ <parameter name='output.status.results'
+ value='`$org.openecomp.appc.adapter.saltstack.results`'/>
+ </return>
+ </outcome>
+ <outcome value='Other'>
+ <switch test="`$org.onap.appc.adapter.saltstack.result.code`">
+ <outcome value='Other'>
+ <return status='failure'>
+ <parameter name='error-code' value='200'/>
+ <parameter name='error-message'
+ value='`$org.openecomp.appc.adapter.saltstack.message`'/>
+ <parameter name='output.status.results'
+ value='`$org.openecomp.appc.adapter.saltstack.results`'/>
+ </return>
+ </outcome>
+ <outcome value='200'>
+ <switch test="`$test1.minion1`">
+ <outcome value='Other'>
+ <return status='failure'>
+ <parameter name='error-code' value='200'/>
+ <parameter name='error-message'
+ value='`$org.openecomp.appc.adapter.saltstack.message`'/>
+ <parameter name='output.status.results'
+ value='`$org.openecomp.appc.adapter.saltstack.results`'/>
+ </return>
+ </outcome>
+ <outcome value='true'>
+ <execute
+ plugin='org.openecomp.appc.adapter.saltstack.SaltstackAdapter'
+ method='reqExecCommand'>
+ <parameter name='HostName'
+ value='`$AgentUrl`'/>
+ <parameter name='Port' value='`$Port`'/>
+ <parameter name='User' value='`$User`'/>
+ <parameter name='Password'
+ value='`$Password`'/>
+ <parameter name='Id' value='test2'/>
+ <parameter name='Cmd'
+ value='salt &apos;minion1&apos; pkg.install vim --out=json --static'/>
+ <parameter name='SlsExec' value='false'/>
+ <parameter name='Timeout'
+ value='`$Timeout`'/>
+ <outcome value='failure'>
+ <return status='failure'>
+ <parameter name='error-code'
+ value='200'/>
+ <parameter name='error-message'
+ value='`$org.openecomp.appc.adapter.saltstack.message`'/>
+ <parameter
+ name='output.status.results'
+ value='`$org.openecomp.appc.adapter.saltstack.results`'/>
+ </return>
+ </outcome>
+ <outcome value='Other'>
+ <switch test="`$org.onap.appc.adapter.saltstack.result.code`">
+ <outcome value='200'>
+ <switch test="`$test2.minion1.retcode`">
+ <outcome value='0'>
+ <return status='success'>
+ <parameter
+ name='output.status.code'
+ value='`$org.openecomp.appc.adapter.saltstack.result.code`'/>
+ <parameter
+ name='output.status.message'
+ value='`$org.openecomp.appc.adapter.saltstack.message`'/>
+ <parameter
+ name='output.status.results'
+ value='`$org.openecomp.appc.adapter.saltstack.results`'/>
+ </return>
+ </outcome>
+ <outcome value='Other'>
+ <return status='failure'>
+ <parameter
+ name='error-code'
+ value='200'/>
+ <parameter
+ name='error-message'
+ value='`$org.openecomp.appc.adapter.saltstack.message`'/>
+ <parameter
+ name='output.status.results'
+ value='`$org.openecomp.appc.adapter.saltstack.results`'/>
+ </return>
+ </outcome>
+ </switch>
+ </outcome>
+ <outcome value='Other'>
+ <return status='failure'>
+ <parameter name='error-code'
+ value='200'/>
+ <parameter
+ name='error-message'
+ value='`$org.openecomp.appc.adapter.saltstack.message`'/>
+ <parameter
+ name='output.status.results'
+ value='`$org.openecomp.appc.adapter.saltstack.results`'/>
+ </return>
+ </outcome>
+ </switch>
+ </outcome>
+ </execute>
+ </outcome>
+ </switch>
+ </outcome>
+ </switch>
+ </outcome>
+ </execute>
+ </method>
+</service-logic> \ No newline at end of file
diff --git a/adaptors/saltstack-adapter/saltstack-directed-graphs-sample/reqExecCommand/APPC_saltstack-adapter-1.0-exec-single-SLSComm.json b/adaptors/saltstack-adapter/saltstack-directed-graphs-sample/reqExecCommand/APPC_saltstack-adapter-1.0-exec-single-SLSComm.json
new file mode 100644
index 000000000..4be0db3dd
--- /dev/null
+++ b/adaptors/saltstack-adapter/saltstack-directed-graphs-sample/reqExecCommand/APPC_saltstack-adapter-1.0-exec-single-SLSComm.json
@@ -0,0 +1,203 @@
+[
+ {
+ "id": "bd0f1105.ff214",
+ "type": "method",
+ "name": "saltstack-adapter-1.0",
+ "xml": "<method rpc='saltstack-adapter-1.0-exec-single-SLSComm' mode='sync'>\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 526,
+ "y": 238,
+ "z": "c053ae12.4067b",
+ "wires": [
+ [
+ "f4e59dd0.ee45f"
+ ]
+ ]
+ },
+ {
+ "id": "26f2a2b8.90f58e",
+ "type": "service-logic",
+ "name": "APPC 2.0.1",
+ "module": "APPC",
+ "version": "2.0.1",
+ "comments": "",
+ "xml": "<service-logic xmlns='http://www.onap.org/sdnc/svclogic' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xsi:schemaLocation='http://www.onap.org/sdnc/svclogic ./svclogic.xsd' module='APPC' version='2.0.1'>",
+ "outputs": 1,
+ "x": 317,
+ "y": 316,
+ "z": "c053ae12.4067b",
+ "wires": [
+ [
+ "bd0f1105.ff214"
+ ]
+ ]
+ },
+ {
+ "id": "55a7736.2789e8c",
+ "type": "returnFailure",
+ "name": "return failure",
+ "xml": "<return status='failure'>\n<parameter name='error-code' value='200' />\n<parameter name='error-message' value='`$org.openecomp.appc.adapter.saltstack.message`' />\n<parameter name='output.status.results' value='`$org.openecomp.appc.adapter.saltstack.results`' />\n",
+ "comments": "",
+ "x": 1064,
+ "y": 453,
+ "z": "c053ae12.4067b",
+ "wires": []
+ },
+ {
+ "id": "f4e59dd0.ee45f",
+ "type": "execute",
+ "name": "execute",
+ "xml": "<execute plugin='org.openecomp.appc.adapter.saltstack.SaltstackAdapter' method='reqExecCommand' >\n <parameter name='HostName' value='`$AgentUrl`'/>\n <parameter name='Port' value='`$Port`'/>\n <parameter name='User' value='`$User`'/>\n <parameter name='Password' value='`$Password`'/>\n <parameter name='Id' value='test1'/>\n <parameter name='Cmd' value='salt &apos;*&apos; test.ping --out=json --static'/>\n <parameter name='SlsExec' value='false'/>\n <parameter name='Timeout' value='`$Timeout`'/>\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 735,
+ "y": 240,
+ "z": "c053ae12.4067b",
+ "wires": [
+ [
+ "93fca622.05ad58",
+ "7ce4a659.44c828"
+ ]
+ ]
+ },
+ {
+ "id": "2ceb37d9.a8ba18",
+ "type": "switchNode",
+ "name": "switch",
+ "xml": "<switch test=\"`$org.onap.appc.adapter.saltstack.result.code`\">\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 522,
+ "y": 398,
+ "z": "c053ae12.4067b",
+ "wires": [
+ [
+ "cd89356c.279678",
+ "781026e2.01d498"
+ ]
+ ]
+ },
+ {
+ "id": "cd89356c.279678",
+ "type": "other",
+ "name": "other",
+ "xml": "<outcome value='Other'>\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 708,
+ "y": 456,
+ "z": "c053ae12.4067b",
+ "wires": [
+ [
+ "55a7736.2789e8c"
+ ]
+ ]
+ },
+ {
+ "id": "93fca622.05ad58",
+ "type": "failure",
+ "name": "failure",
+ "xml": "<outcome value='failure'>\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 985,
+ "y": 237,
+ "z": "c053ae12.4067b",
+ "wires": [
+ [
+ "55a7736.2789e8c"
+ ]
+ ]
+ },
+ {
+ "id": "7ce4a659.44c828",
+ "type": "other",
+ "name": "other",
+ "xml": "<outcome value='Other'>\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 332,
+ "y": 405,
+ "z": "c053ae12.4067b",
+ "wires": [
+ [
+ "2ceb37d9.a8ba18"
+ ]
+ ]
+ },
+ {
+ "id": "781026e2.01d498",
+ "type": "success",
+ "name": "success",
+ "xml": "<outcome value='200'>\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 711,
+ "y": 398,
+ "z": "c053ae12.4067b",
+ "wires": [
+ [
+ "ce510062.8dcc7"
+ ]
+ ]
+ },
+ {
+ "id": "ce510062.8dcc7",
+ "type": "returnSuccess",
+ "name": "return success",
+ "xml": "<return status='success'>\n<parameter name='output.status.code' value='`$org.openecomp.appc.adapter.saltstack.result.code`' />\n<parameter name='output.status.message' value='`$org.openecomp.appc.adapter.saltstack.message`'/>\n<parameter name='output.status.results' value = '`$org.openecomp.appc.adapter.saltstack.results`'/>\n",
+ "comments": "",
+ "x": 893,
+ "y": 399,
+ "z": "c053ae12.4067b",
+ "wires": []
+ },
+ {
+ "id": "593bd7fb.675368",
+ "type": "dgstart",
+ "name": "DGSTART",
+ "outputs": 1,
+ "x": 295,
+ "y": 216,
+ "z": "c053ae12.4067b",
+ "wires": [
+ [
+ "26f2a2b8.90f58e"
+ ]
+ ]
+ },
+ {
+ "id": "901c8408.5fecb8",
+ "type": "comment",
+ "name": "SaltStack Adaptor DG",
+ "info": "",
+ "comments": "",
+ "x": 673,
+ "y": 103,
+ "z": "c053ae12.4067b",
+ "wires": []
+ },
+ {
+ "id": "cc449713.a1be88",
+ "type": "comment",
+ "name": "request-method = reqExecCommand, req-action = \"execute a single SLS command\"",
+ "info": "Here we just ping to all the minions, and we dont even check if the minions are active. ",
+ "comments": "",
+ "x": 684,
+ "y": 188,
+ "z": "c053ae12.4067b",
+ "wires": []
+ },
+ {
+ "id": "c07fa80e.7f3ac8",
+ "type": "comment",
+ "name": "Assumptions for this DG (example-server)",
+ "info": "Here we assume, the saltstack server is the example-vagrant based server. Where, the master saltstact controlls minion1 and minion2. ",
+ "comments": "",
+ "x": 676,
+ "y": 144,
+ "z": "c053ae12.4067b",
+ "wires": []
+ }
+] \ No newline at end of file
diff --git a/adaptors/saltstack-adapter/saltstack-directed-graphs-sample/reqExecCommand/APPC_saltstack-adapter-1.0-exec-single-SLSComm.xml b/adaptors/saltstack-adapter/saltstack-directed-graphs-sample/reqExecCommand/APPC_saltstack-adapter-1.0-exec-single-SLSComm.xml
new file mode 100644
index 000000000..bd9aea771
--- /dev/null
+++ b/adaptors/saltstack-adapter/saltstack-directed-graphs-sample/reqExecCommand/APPC_saltstack-adapter-1.0-exec-single-SLSComm.xml
@@ -0,0 +1,51 @@
+<service-logic xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
+ xmlns='http://www.onap.org/sdnc/svclogic'
+ xsi:schemaLocation='http://www.onap.org/sdnc/svclogic ./svclogic.xsd'
+ module='APPC' version='2.0.1'>
+ <method rpc='saltstack-adapter-1.0-exec-single-SLSComm' mode='sync'>
+ <execute plugin='org.openecomp.appc.adapter.saltstack.SaltstackAdapter'
+ method='reqExecCommand'>
+ <parameter name='HostName' value='`$AgentUrl`'/>
+ <parameter name='Port' value='`$Port`'/>
+ <parameter name='User' value='`$User`'/>
+ <parameter name='Password' value='`$Password`'/>
+ <parameter name='Id' value='test1'/>
+ <parameter name='Cmd'
+ value='salt &apos;*&apos; test.ping --out=json --static'/>
+ <parameter name='SlsExec' value='false'/>
+ <parameter name='Timeout' value='`$Timeout`'/>
+ <outcome value='failure'>
+ <return status='failure'>
+ <parameter name='error-code' value='200'/>
+ <parameter name='error-message'
+ value='`$org.openecomp.appc.adapter.saltstack.message`'/>
+ <parameter name='output.status.results'
+ value='`$org.openecomp.appc.adapter.saltstack.results`'/>
+ </return>
+ </outcome>
+ <outcome value='Other'>
+ <switch test="`$org.onap.appc.adapter.saltstack.result.code`">
+ <outcome value='200'>
+ <return status='success'>
+ <parameter name='output.status.code'
+ value='`$org.openecomp.appc.adapter.saltstack.result.code`'/>
+ <parameter name='output.status.message'
+ value='`$org.openecomp.appc.adapter.saltstack.message`'/>
+ <parameter name='output.status.results'
+ value='`$org.openecomp.appc.adapter.saltstack.results`'/>
+ </return>
+ </outcome>
+ <outcome value='Other'>
+ <return status='failure'>
+ <parameter name='error-code' value='200'/>
+ <parameter name='error-message'
+ value='`$org.openecomp.appc.adapter.saltstack.message`'/>
+ <parameter name='output.status.results'
+ value='`$org.openecomp.appc.adapter.saltstack.results`'/>
+ </return>
+ </outcome>
+ </switch>
+ </outcome>
+ </execute>
+ </method>
+</service-logic> \ No newline at end of file
diff --git a/adaptors/saltstack-adapter/saltstack-directed-graphs-sample/reqExecSLS/APPC_saltstack-adapter-1.0 IDEAL.json b/adaptors/saltstack-adapter/saltstack-directed-graphs-sample/reqExecSLS/APPC_saltstack-adapter-1.0 IDEAL.json
new file mode 100644
index 000000000..7fe88f063
--- /dev/null
+++ b/adaptors/saltstack-adapter/saltstack-directed-graphs-sample/reqExecSLS/APPC_saltstack-adapter-1.0 IDEAL.json
@@ -0,0 +1,214 @@
+[
+ {
+ "id": "80b83851.e527b8",
+ "type": "method",
+ "name": "saltstack-adapter-1.0",
+ "xml": "<method rpc='saltstack-adapter-1.0' mode='sync'>\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 676,
+ "y": 277,
+ "z": "1f6661d7.1ebd2e",
+ "wires": [
+ [
+ "83c8d47e.cb9c98"
+ ]
+ ]
+ },
+ {
+ "id": "41231c44.5d1324",
+ "type": "service-logic",
+ "name": "APPC 2.0.1",
+ "module": "APPC",
+ "version": "2.0.1",
+ "comments": "",
+ "xml": "<service-logic xmlns='http://www.onap.org/sdnc/svclogic' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xsi:schemaLocation='http://www.onap.org/sdnc/svclogic ./svclogic.xsd' module='APPC' version='2.0.1'>",
+ "outputs": 1,
+ "x": 453,
+ "y": 276,
+ "z": "1f6661d7.1ebd2e",
+ "wires": [
+ [
+ "80b83851.e527b8"
+ ]
+ ]
+ },
+ {
+ "id": "1f4a794d.fb3be7",
+ "type": "returnSuccess",
+ "name": "return success",
+ "xml": "<return status='success'>\n<parameter name='output.status.code' value='`$org.openecomp.appc.adapter.saltstack.result.code`' />\n<parameter name='output.status.message' value='`$org.openecomp.appc.adapter.saltstack.message`'/>\n<parameter name='output.status.results' value = '`$org.openecomp.appc.adapter.saltstack.results`'/>\n",
+ "comments": "",
+ "x": 1055,
+ "y": 369,
+ "z": "1f6661d7.1ebd2e",
+ "wires": []
+ },
+ {
+ "id": "5a85036.5a9e2fc",
+ "type": "dgstart",
+ "name": "DGSTART",
+ "outputs": 1,
+ "x": 284,
+ "y": 275,
+ "z": "1f6661d7.1ebd2e",
+ "wires": [
+ [
+ "41231c44.5d1324"
+ ]
+ ]
+ },
+ {
+ "id": "b38fc61c.a23438",
+ "type": "comment",
+ "name": "SaltStack Adaptor DG",
+ "info": "",
+ "comments": "",
+ "x": 661,
+ "y": 154,
+ "z": "1f6661d7.1ebd2e",
+ "wires": []
+ },
+ {
+ "id": "6a821d83.4070e4",
+ "type": "comment",
+ "name": "request-method = reqExecSLS, req-action = \"execute SLS\"",
+ "info": "This would be the ideal adaptor the orchestrator DG will call, this just takes in SlsName.",
+ "comments": "",
+ "x": 672,
+ "y": 239,
+ "z": "1f6661d7.1ebd2e",
+ "wires": []
+ },
+ {
+ "id": "ba16960c.36bad8",
+ "type": "comment",
+ "name": "Assumptions for this DG (example-server)",
+ "info": "Here we assume, the saltstack server is the example-vagrant based server. Where, the master saltstact controllers minion1 and minion2. ",
+ "comments": "",
+ "x": 664,
+ "y": 195,
+ "z": "1f6661d7.1ebd2e",
+ "wires": []
+ },
+ {
+ "id": "83c8d47e.cb9c98",
+ "type": "execute",
+ "name": "execute",
+ "xml": "<execute plugin='org.openecomp.appc.adapter.saltstack.SaltstackAdapter' method='reqExecCommand' >\n <parameter name='HostName' value='`$AgentUrl`'/>\n <parameter name='Port' value='`$Port`'/>\n <parameter name='User' value='`$User`'/>\n <parameter name='Password' value='`$Password`'/>\n <parameter name='Id' value='test2'/>\n <parameter name='SlsName' value='test-file.sls'/>\n <parameter name='NodeList' value='`$NodeList`'/>\n <parameter name='Timeout' value='`$Timeout`'/>\n <parameter name='FileParameters' value='`$FileParameters`'/>\n <parameter name='EnvParameters' value='`$EnvParameters`'/>\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 366,
+ "y": 406,
+ "z": "1f6661d7.1ebd2e",
+ "wires": [
+ [
+ "b83f5a23.33f938",
+ "3354190.eb450e8"
+ ]
+ ]
+ },
+ {
+ "id": "b83f5a23.33f938",
+ "type": "failure",
+ "name": "failure",
+ "xml": "<outcome value='failure'>\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 559,
+ "y": 367,
+ "z": "1f6661d7.1ebd2e",
+ "wires": [
+ [
+ "efc02e73.0cf1d"
+ ]
+ ]
+ },
+ {
+ "id": "3354190.eb450e8",
+ "type": "other",
+ "name": "other",
+ "xml": "<outcome value='Other'>\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 557,
+ "y": 439,
+ "z": "1f6661d7.1ebd2e",
+ "wires": [
+ [
+ "88b53985.e42758"
+ ]
+ ]
+ },
+ {
+ "id": "88b53985.e42758",
+ "type": "switchNode",
+ "name": "switch",
+ "xml": "<switch test=\"`$org.onap.appc.adapter.saltstack.result.code`\">\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 709,
+ "y": 427,
+ "z": "1f6661d7.1ebd2e",
+ "wires": [
+ [
+ "195a294e.61efb7",
+ "bc1bfd78.146bc"
+ ]
+ ]
+ },
+ {
+ "id": "bc1bfd78.146bc",
+ "type": "success",
+ "name": "success",
+ "xml": "<outcome value='200'>\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 872,
+ "y": 373,
+ "z": "1f6661d7.1ebd2e",
+ "wires": [
+ [
+ "1f4a794d.fb3be7"
+ ]
+ ]
+ },
+ {
+ "id": "195a294e.61efb7",
+ "type": "other",
+ "name": "other",
+ "xml": "<outcome value='Other'>\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 869,
+ "y": 442,
+ "z": "1f6661d7.1ebd2e",
+ "wires": [
+ [
+ "81ddc2e0.dce24"
+ ]
+ ]
+ },
+ {
+ "id": "efc02e73.0cf1d",
+ "type": "returnFailure",
+ "name": "return failure",
+ "xml": "<return status='failure'>\n<parameter name='error-code' value='200' />\n<parameter name='error-message' value='`$org.openecomp.appc.adapter.saltstack.message`' />\n<parameter name='output.status.results' value='`$org.openecomp.appc.adapter.saltstack.results`' />\n",
+ "comments": "",
+ "x": 719,
+ "y": 351,
+ "z": "1f6661d7.1ebd2e",
+ "wires": []
+ },
+ {
+ "id": "81ddc2e0.dce24",
+ "type": "returnFailure",
+ "name": "return failure",
+ "xml": "<return status='failure'>\n<parameter name='error-code' value='200' />\n<parameter name='error-message' value='`$org.openecomp.appc.adapter.saltstack.message`' />\n<parameter name='output.status.results' value='`$org.openecomp.appc.adapter.saltstack.results`' />\n",
+ "comments": "",
+ "x": 1039,
+ "y": 439,
+ "z": "1f6661d7.1ebd2e",
+ "wires": []
+ }
+] \ No newline at end of file
diff --git a/adaptors/saltstack-adapter/saltstack-directed-graphs-sample/reqExecSLS/APPC_saltstack-adapter-1.0 IDEAL.xml b/adaptors/saltstack-adapter/saltstack-directed-graphs-sample/reqExecSLS/APPC_saltstack-adapter-1.0 IDEAL.xml
new file mode 100644
index 000000000..23ec7856b
--- /dev/null
+++ b/adaptors/saltstack-adapter/saltstack-directed-graphs-sample/reqExecSLS/APPC_saltstack-adapter-1.0 IDEAL.xml
@@ -0,0 +1,52 @@
+<service-logic xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
+ xmlns='http://www.onap.org/sdnc/svclogic'
+ xsi:schemaLocation='http://www.onap.org/sdnc/svclogic ./svclogic.xsd'
+ module='APPC' version='2.0.1'>
+ <method rpc='saltstack-adapter-1.0' mode='sync'>
+ <execute plugin='org.openecomp.appc.adapter.saltstack.SaltstackAdapter'
+ method='reqExecCommand'>
+ <parameter name='HostName' value='`$AgentUrl`'/>
+ <parameter name='Port' value='`$Port`'/>
+ <parameter name='User' value='`$User`'/>
+ <parameter name='Password' value='`$Password`'/>
+ <parameter name='Id' value='test2'/>
+ <parameter name='SlsName' value='test-file.sls'/>
+ <parameter name='NodeList' value='`$NodeList`'/>
+ <parameter name='Timeout' value='`$Timeout`'/>
+ <parameter name='FileParameters' value='`$FileParameters`'/>
+ <parameter name='EnvParameters' value='`$EnvParameters`'/>
+ <outcome value='failure'>
+ <return status='failure'>
+ <parameter name='error-code' value='200'/>
+ <parameter name='error-message'
+ value='`$org.openecomp.appc.adapter.saltstack.message`'/>
+ <parameter name='output.status.results'
+ value='`$org.openecomp.appc.adapter.saltstack.results`'/>
+ </return>
+ </outcome>
+ <outcome value='Other'>
+ <switch test="`$org.onap.appc.adapter.saltstack.result.code`">
+ <outcome value='200'>
+ <return status='success'>
+ <parameter name='output.status.code'
+ value='`$org.openecomp.appc.adapter.saltstack.result.code`'/>
+ <parameter name='output.status.message'
+ value='`$org.openecomp.appc.adapter.saltstack.message`'/>
+ <parameter name='output.status.results'
+ value='`$org.openecomp.appc.adapter.saltstack.results`'/>
+ </return>
+ </outcome>
+ <outcome value='Other'>
+ <return status='failure'>
+ <parameter name='error-code' value='200'/>
+ <parameter name='error-message'
+ value='`$org.openecomp.appc.adapter.saltstack.message`'/>
+ <parameter name='output.status.results'
+ value='`$org.openecomp.appc.adapter.saltstack.results`'/>
+ </return>
+ </outcome>
+ </switch>
+ </outcome>
+ </execute>
+ </method>
+</service-logic> \ No newline at end of file
diff --git a/adaptors/saltstack-adapter/saltstack-directed-graphs-sample/reqExecSLS/APPC_saltstack-adapter-1.0-exec-SLS-applyTo.json b/adaptors/saltstack-adapter/saltstack-directed-graphs-sample/reqExecSLS/APPC_saltstack-adapter-1.0-exec-SLS-applyTo.json
new file mode 100644
index 000000000..b276f3815
--- /dev/null
+++ b/adaptors/saltstack-adapter/saltstack-directed-graphs-sample/reqExecSLS/APPC_saltstack-adapter-1.0-exec-SLS-applyTo.json
@@ -0,0 +1,372 @@
+[
+ {
+ "id": "edb39979.b1ccd8",
+ "type": "method",
+ "name": "saltstack-adapter-1.0",
+ "xml": "<method rpc='saltstack-adapter-1.0-exec-SLS-NodeList' mode='sync'>\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 476,
+ "y": 245,
+ "z": "671ca899.284f68",
+ "wires": [
+ [
+ "95c9ba42.6e4aa8"
+ ]
+ ]
+ },
+ {
+ "id": "a16ea11e.f8d1c",
+ "type": "service-logic",
+ "name": "APPC 2.0.1",
+ "module": "APPC",
+ "version": "2.0.1",
+ "comments": "",
+ "xml": "<service-logic xmlns='http://www.onap.org/sdnc/svclogic' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xsi:schemaLocation='http://www.onap.org/sdnc/svclogic ./svclogic.xsd' module='APPC' version='2.0.1'>",
+ "outputs": 1,
+ "x": 267,
+ "y": 323,
+ "z": "671ca899.284f68",
+ "wires": [
+ [
+ "edb39979.b1ccd8"
+ ]
+ ]
+ },
+ {
+ "id": "1591f92e.029ca7",
+ "type": "returnFailure",
+ "name": "return failure",
+ "xml": "<return status='failure'>\n<parameter name='error-code' value='200' />\n<parameter name='error-message' value='`$org.openecomp.appc.adapter.saltstack.message`' />\n<parameter name='output.status.results' value='`$org.openecomp.appc.adapter.saltstack.results`' />\n",
+ "comments": "",
+ "x": 1191,
+ "y": 315,
+ "z": "671ca899.284f68",
+ "wires": []
+ },
+ {
+ "id": "95c9ba42.6e4aa8",
+ "type": "execute",
+ "name": "execute",
+ "xml": "<execute plugin='org.openecomp.appc.adapter.saltstack.SaltstackAdapter' method='reqExecCommand' >\n <parameter name='HostName' value='`$AgentUrl`'/>\n <parameter name='Port' value='`$Port`'/>\n <parameter name='User' value='`$User`'/>\n <parameter name='Password' value='`$Password`'/>\n <parameter name='Id' value='test1'/>\n <parameter name='Cmd' value='salt &apos;*&apos; test.ping --out=json --static'/>\n <parameter name='SlsExec' value='false'/>\n <parameter name='Timeout' value='`$Timeout`'/>\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 684,
+ "y": 251,
+ "z": "671ca899.284f68",
+ "wires": [
+ [
+ "cd0c458a.2430b8",
+ "69e531e3.4efc3"
+ ]
+ ]
+ },
+ {
+ "id": "38b44d70.9c85d2",
+ "type": "switchNode",
+ "name": "switch",
+ "xml": "<switch test=\"`$org.onap.appc.adapter.saltstack.result.code`\">\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 472,
+ "y": 405,
+ "z": "671ca899.284f68",
+ "wires": [
+ [
+ "505df598.069b9c",
+ "5d7292e.22ec06c"
+ ]
+ ]
+ },
+ {
+ "id": "505df598.069b9c",
+ "type": "other",
+ "name": "other",
+ "xml": "<outcome value='Other'>\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 658,
+ "y": 463,
+ "z": "671ca899.284f68",
+ "wires": [
+ [
+ "1591f92e.029ca7"
+ ]
+ ]
+ },
+ {
+ "id": "cd0c458a.2430b8",
+ "type": "failure",
+ "name": "failure",
+ "xml": "<outcome value='failure'>\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 935,
+ "y": 244,
+ "z": "671ca899.284f68",
+ "wires": [
+ [
+ "1591f92e.029ca7"
+ ]
+ ]
+ },
+ {
+ "id": "69e531e3.4efc3",
+ "type": "other",
+ "name": "other",
+ "xml": "<outcome value='Other'>\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 282,
+ "y": 412,
+ "z": "671ca899.284f68",
+ "wires": [
+ [
+ "38b44d70.9c85d2"
+ ]
+ ]
+ },
+ {
+ "id": "5d7292e.22ec06c",
+ "type": "success",
+ "name": "success",
+ "xml": "<outcome value='200'>\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 661,
+ "y": 405,
+ "z": "671ca899.284f68",
+ "wires": [
+ [
+ "c9df0cea.f2361"
+ ]
+ ]
+ },
+ {
+ "id": "e4f7eb59.0abb58",
+ "type": "returnSuccess",
+ "name": "return success",
+ "xml": "<return status='success'>\n<parameter name='output.status.code' value='`$org.openecomp.appc.adapter.saltstack.result.code`' />\n<parameter name='output.status.message' value='`$org.openecomp.appc.adapter.saltstack.message`'/>\n<parameter name='output.status.results' value = '`$org.openecomp.appc.adapter.saltstack.results`'/>\n",
+ "comments": "",
+ "x": 1079,
+ "y": 564,
+ "z": "671ca899.284f68",
+ "wires": []
+ },
+ {
+ "id": "8e586da4.570f1",
+ "type": "dgstart",
+ "name": "DGSTART",
+ "outputs": 1,
+ "x": 245,
+ "y": 223,
+ "z": "671ca899.284f68",
+ "wires": [
+ [
+ "a16ea11e.f8d1c"
+ ]
+ ]
+ },
+ {
+ "id": "71387074.137c1",
+ "type": "comment",
+ "name": "SaltStack Adaptor DG",
+ "info": "",
+ "comments": "",
+ "x": 623,
+ "y": 110,
+ "z": "671ca899.284f68",
+ "wires": []
+ },
+ {
+ "id": "c5e8c62d.021758",
+ "type": "comment",
+ "name": "request-method = reqExecSLS, req-action = \"execute SLS\"",
+ "info": "Here we basically test if minion1 is active by pinging to it, then respective sls file is executed on to it. \n",
+ "comments": "",
+ "x": 634,
+ "y": 195,
+ "z": "671ca899.284f68",
+ "wires": []
+ },
+ {
+ "id": "1805797.a241487",
+ "type": "comment",
+ "name": "Assumptions for this DG (example-server)",
+ "info": "Here we assume, the saltstack server is the example-vagrant based server. Where, the master saltstact controllers minion1 and minion2. ",
+ "comments": "",
+ "x": 626,
+ "y": 151,
+ "z": "671ca899.284f68",
+ "wires": []
+ },
+ {
+ "id": "c9df0cea.f2361",
+ "type": "switchNode",
+ "name": "switch",
+ "xml": "<switch test=\"`$test1.minion1`\">\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 825,
+ "y": 405,
+ "z": "671ca899.284f68",
+ "wires": [
+ [
+ "d83d6024.2454d",
+ "f4d70bbc.f0bc38"
+ ]
+ ]
+ },
+ {
+ "id": "d83d6024.2454d",
+ "type": "other",
+ "name": "other",
+ "xml": "<outcome value='Other'>\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 991,
+ "y": 459,
+ "z": "671ca899.284f68",
+ "wires": [
+ [
+ "1591f92e.029ca7"
+ ]
+ ]
+ },
+ {
+ "id": "f4d70bbc.f0bc38",
+ "type": "other",
+ "name": "outcome",
+ "xml": "<outcome value='true'>\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 994,
+ "y": 401,
+ "z": "671ca899.284f68",
+ "wires": [
+ [
+ "e86d9995.b65c58"
+ ]
+ ]
+ },
+ {
+ "id": "e86d9995.b65c58",
+ "type": "execute",
+ "name": "execute",
+ "xml": "<execute plugin='org.openecomp.appc.adapter.saltstack.SaltstackAdapter' method='reqExecCommand' >\n <parameter name='HostName' value='`$AgentUrl`'/>\n <parameter name='Port' value='`$Port`'/>\n <parameter name='User' value='`$User`'/>\n <parameter name='Password' value='`$Password`'/>\n <parameter name='Id' value='test2'/>\n <parameter name='SlsName' value='test-file.sls'/>\n <parameter name='NodeList' value='minion1'/>\n <parameter name='Timeout' value='`$Timeout`'/>\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 398,
+ "y": 593,
+ "z": "671ca899.284f68",
+ "wires": [
+ [
+ "89ff1c2a.08f52",
+ "e20c4c85.43d3c"
+ ]
+ ]
+ },
+ {
+ "id": "89ff1c2a.08f52",
+ "type": "failure",
+ "name": "failure",
+ "xml": "<outcome value='failure'>\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 583,
+ "y": 562,
+ "z": "671ca899.284f68",
+ "wires": [
+ [
+ "6032e33e.5b044c"
+ ]
+ ]
+ },
+ {
+ "id": "e20c4c85.43d3c",
+ "type": "other",
+ "name": "other",
+ "xml": "<outcome value='Other'>\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 581,
+ "y": 634,
+ "z": "671ca899.284f68",
+ "wires": [
+ [
+ "8bb4c177.499c8"
+ ]
+ ]
+ },
+ {
+ "id": "8bb4c177.499c8",
+ "type": "switchNode",
+ "name": "switch",
+ "xml": "<switch test=\"`$org.onap.appc.adapter.saltstack.result.code`\">\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 733,
+ "y": 622,
+ "z": "671ca899.284f68",
+ "wires": [
+ [
+ "905334fe.934d68",
+ "9c217c10.9d539"
+ ]
+ ]
+ },
+ {
+ "id": "9c217c10.9d539",
+ "type": "success",
+ "name": "success",
+ "xml": "<outcome value='200'>\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 896,
+ "y": 568,
+ "z": "671ca899.284f68",
+ "wires": [
+ [
+ "e4f7eb59.0abb58"
+ ]
+ ]
+ },
+ {
+ "id": "905334fe.934d68",
+ "type": "other",
+ "name": "other",
+ "xml": "<outcome value='Other'>\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 893,
+ "y": 637,
+ "z": "671ca899.284f68",
+ "wires": [
+ [
+ "7026a88c.5bffd8"
+ ]
+ ]
+ },
+ {
+ "id": "6032e33e.5b044c",
+ "type": "returnFailure",
+ "name": "return failure",
+ "xml": "<return status='failure'>\n<parameter name='error-code' value='200' />\n<parameter name='error-message' value='`$org.openecomp.appc.adapter.saltstack.message`' />\n<parameter name='output.status.results' value='`$org.openecomp.appc.adapter.saltstack.results`' />\n",
+ "comments": "",
+ "x": 735,
+ "y": 559,
+ "z": "671ca899.284f68",
+ "wires": []
+ },
+ {
+ "id": "7026a88c.5bffd8",
+ "type": "returnFailure",
+ "name": "return failure",
+ "xml": "<return status='failure'>\n<parameter name='error-code' value='200' />\n<parameter name='error-message' value='`$org.openecomp.appc.adapter.saltstack.message`' />\n<parameter name='output.status.results' value='`$org.openecomp.appc.adapter.saltstack.results`' />\n",
+ "comments": "",
+ "x": 1054,
+ "y": 637,
+ "z": "671ca899.284f68",
+ "wires": []
+ }
+] \ No newline at end of file
diff --git a/adaptors/saltstack-adapter/saltstack-directed-graphs-sample/reqExecSLS/APPC_saltstack-adapter-1.0-exec-SLS-applyTo.xml b/adaptors/saltstack-adapter/saltstack-directed-graphs-sample/reqExecSLS/APPC_saltstack-adapter-1.0-exec-SLS-applyTo.xml
new file mode 100644
index 000000000..cc4538cac
--- /dev/null
+++ b/adaptors/saltstack-adapter/saltstack-directed-graphs-sample/reqExecSLS/APPC_saltstack-adapter-1.0-exec-SLS-applyTo.xml
@@ -0,0 +1,112 @@
+<service-logic xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
+ xmlns='http://www.onap.org/sdnc/svclogic'
+ xsi:schemaLocation='http://www.onap.org/sdnc/svclogic ./svclogic.xsd'
+ module='APPC' version='2.0.1'>
+ <method rpc='saltstack-adapter-1.0-exec-SLS-NodeList' mode='sync'>
+ <execute plugin='org.openecomp.appc.adapter.saltstack.SaltstackAdapter'
+ method='reqExecCommand'>
+ <parameter name='HostName' value='`$AgentUrl`'/>
+ <parameter name='Port' value='`$Port`'/>
+ <parameter name='User' value='`$User`'/>
+ <parameter name='Password' value='`$Password`'/>
+ <parameter name='Id' value='test1'/>
+ <parameter name='Cmd'
+ value='salt &apos;*&apos; test.ping --out=json --static'/>
+ <parameter name='SlsExec' value='false'/>
+ <parameter name='Timeout' value='`$Timeout`'/>
+ <outcome value='failure'>
+ <return status='failure'>
+ <parameter name='error-code' value='200'/>
+ <parameter name='error-message'
+ value='`$org.openecomp.appc.adapter.saltstack.message`'/>
+ <parameter name='output.status.results'
+ value='`$org.openecomp.appc.adapter.saltstack.results`'/>
+ </return>
+ </outcome>
+ <outcome value='Other'>
+ <switch test="`$org.onap.appc.adapter.saltstack.result.code`">
+ <outcome value='200'>
+ <switch test="`$test1.minion1`">
+ <outcome value='true'>
+ <execute
+ plugin='org.openecomp.appc.adapter.saltstack.SaltstackAdapter'
+ method='reqExecCommand'>
+ <parameter name='HostName'
+ value='`$AgentUrl`'/>
+ <parameter name='Port' value='`$Port`'/>
+ <parameter name='User' value='`$User`'/>
+ <parameter name='Password'
+ value='`$Password`'/>
+ <parameter name='Id' value='test2'/>
+ <parameter name='SlsName'
+ value='test-file.sls'/>
+ <parameter name='NodeList' value='minion1'/>
+ <parameter name='Timeout'
+ value='`$Timeout`'/>
+ <outcome value='failure'>
+ <return status='failure'>
+ <parameter name='error-code'
+ value='200'/>
+ <parameter name='error-message'
+ value='`$org.openecomp.appc.adapter.saltstack.message`'/>
+ <parameter
+ name='output.status.results'
+ value='`$org.openecomp.appc.adapter.saltstack.results`'/>
+ </return>
+ </outcome>
+ <outcome value='Other'>
+ <switch test="`$org.onap.appc.adapter.saltstack.result.code`">
+ <outcome value='200'>
+ <return status='success'>
+ <parameter
+ name='output.status.code'
+ value='`$org.openecomp.appc.adapter.saltstack.result.code`'/>
+ <parameter
+ name='output.status.message'
+ value='`$org.openecomp.appc.adapter.saltstack.message`'/>
+ <parameter
+ name='output.status.results'
+ value='`$org.openecomp.appc.adapter.saltstack.results`'/>
+ </return>
+ </outcome>
+ <outcome value='Other'>
+ <return status='failure'>
+ <parameter name='error-code'
+ value='200'/>
+ <parameter
+ name='error-message'
+ value='`$org.openecomp.appc.adapter.saltstack.message`'/>
+ <parameter
+ name='output.status.results'
+ value='`$org.openecomp.appc.adapter.saltstack.results`'/>
+ </return>
+ </outcome>
+ </switch>
+ </outcome>
+ </execute>
+ </outcome>
+ <outcome value='Other'>
+ <return status='failure'>
+ <parameter name='error-code' value='200'/>
+ <parameter name='error-message'
+ value='`$org.openecomp.appc.adapter.saltstack.message`'/>
+ <parameter name='output.status.results'
+ value='`$org.openecomp.appc.adapter.saltstack.results`'/>
+ </return>
+ </outcome>
+ </switch>
+ </outcome>
+ <outcome value='Other'>
+ <return status='failure'>
+ <parameter name='error-code' value='200'/>
+ <parameter name='error-message'
+ value='`$org.openecomp.appc.adapter.saltstack.message`'/>
+ <parameter name='output.status.results'
+ value='`$org.openecomp.appc.adapter.saltstack.results`'/>
+ </return>
+ </outcome>
+ </switch>
+ </outcome>
+ </execute>
+ </method>
+</service-logic> \ No newline at end of file
diff --git a/adaptors/saltstack-adapter/saltstack-directed-graphs-sample/reqExecSLSFile/APPC_saltstack-adapter-1.0-SLSFILE.json b/adaptors/saltstack-adapter/saltstack-directed-graphs-sample/reqExecSLSFile/APPC_saltstack-adapter-1.0-SLSFILE.json
new file mode 100644
index 000000000..b20e7e8da
--- /dev/null
+++ b/adaptors/saltstack-adapter/saltstack-directed-graphs-sample/reqExecSLSFile/APPC_saltstack-adapter-1.0-SLSFILE.json
@@ -0,0 +1,214 @@
+[
+ {
+ "id": "3228200a.5dc1a",
+ "type": "method",
+ "name": "saltstack-adapter-1.0",
+ "xml": "<method rpc='saltstack-adapter-1.0-SLSFILE' mode='sync'>\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 679,
+ "y": 282,
+ "z": "6d4f912d.f07bc",
+ "wires": [
+ [
+ "50b2729f.712eac"
+ ]
+ ]
+ },
+ {
+ "id": "9fb54163.4fb28",
+ "type": "service-logic",
+ "name": "APPC 2.0.1",
+ "module": "APPC",
+ "version": "2.0.1",
+ "comments": "",
+ "xml": "<service-logic xmlns='http://www.onap.org/sdnc/svclogic' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xsi:schemaLocation='http://www.onap.org/sdnc/svclogic ./svclogic.xsd' module='APPC' version='2.0.1'>",
+ "outputs": 1,
+ "x": 456,
+ "y": 281,
+ "z": "6d4f912d.f07bc",
+ "wires": [
+ [
+ "3228200a.5dc1a"
+ ]
+ ]
+ },
+ {
+ "id": "49109fbc.a7a14",
+ "type": "returnSuccess",
+ "name": "return success",
+ "xml": "<return status='success'>\n<parameter name='output.status.code' value='`$org.openecomp.appc.adapter.saltstack.result.code`' />\n<parameter name='output.status.message' value='`$org.openecomp.appc.adapter.saltstack.message`'/>\n<parameter name='output.status.results' value = '`$org.openecomp.appc.adapter.saltstack.results`'/>\n",
+ "comments": "",
+ "x": 1058,
+ "y": 374,
+ "z": "6d4f912d.f07bc",
+ "wires": []
+ },
+ {
+ "id": "d030a396.56232",
+ "type": "dgstart",
+ "name": "DGSTART",
+ "outputs": 1,
+ "x": 287,
+ "y": 280,
+ "z": "6d4f912d.f07bc",
+ "wires": [
+ [
+ "9fb54163.4fb28"
+ ]
+ ]
+ },
+ {
+ "id": "281900c4.fd3e8",
+ "type": "comment",
+ "name": "SaltStack Adaptor DG",
+ "info": "",
+ "comments": "",
+ "x": 664,
+ "y": 159,
+ "z": "6d4f912d.f07bc",
+ "wires": []
+ },
+ {
+ "id": "431a69db.2d2c58",
+ "type": "comment",
+ "name": "request-method = reqExecSLS, req-action = \"execute SLS\"",
+ "info": "This would be the ideal adaptor the orchestrator DG will call, this just takes in SlsName.",
+ "comments": "",
+ "x": 675,
+ "y": 244,
+ "z": "6d4f912d.f07bc",
+ "wires": []
+ },
+ {
+ "id": "4202e1ce.09495",
+ "type": "comment",
+ "name": "Assumptions for this DG (example-server)",
+ "info": "Here we assume, the saltstack server is the example-vagrant based server. Where, the master saltstact controllers minion1 and minion2. ",
+ "comments": "",
+ "x": 667,
+ "y": 200,
+ "z": "6d4f912d.f07bc",
+ "wires": []
+ },
+ {
+ "id": "50b2729f.712eac",
+ "type": "execute",
+ "name": "execute",
+ "xml": "<execute plugin='org.openecomp.appc.adapter.saltstack.SaltstackAdapter' method='reqExecCommand' >\n <parameter name='HostName' value='`$AgentUrl`'/>\n <parameter name='Port' value='`$Port`'/>\n <parameter name='User' value='`$User`'/>\n <parameter name='Password' value='`$Password`'/>\n <parameter name='Id' value='test2'/>\n <parameter name='SlsFile' value='file/location/test-file.sls'/>\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 369,
+ "y": 411,
+ "z": "6d4f912d.f07bc",
+ "wires": [
+ [
+ "71746570.35f0dc",
+ "3e4f7a4a.ae0dc6"
+ ]
+ ]
+ },
+ {
+ "id": "71746570.35f0dc",
+ "type": "failure",
+ "name": "failure",
+ "xml": "<outcome value='failure'>\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 562,
+ "y": 372,
+ "z": "6d4f912d.f07bc",
+ "wires": [
+ [
+ "e59a1a81.112a08"
+ ]
+ ]
+ },
+ {
+ "id": "3e4f7a4a.ae0dc6",
+ "type": "other",
+ "name": "other",
+ "xml": "<outcome value='Other'>\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 560,
+ "y": 444,
+ "z": "6d4f912d.f07bc",
+ "wires": [
+ [
+ "59e320fa.12908"
+ ]
+ ]
+ },
+ {
+ "id": "59e320fa.12908",
+ "type": "switchNode",
+ "name": "switch",
+ "xml": "<switch test=\"`$org.onap.appc.adapter.saltstack.result.code`\">\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 712,
+ "y": 432,
+ "z": "6d4f912d.f07bc",
+ "wires": [
+ [
+ "f81ed07.2135c3",
+ "eb55b5a9.f0d2f8"
+ ]
+ ]
+ },
+ {
+ "id": "eb55b5a9.f0d2f8",
+ "type": "success",
+ "name": "success",
+ "xml": "<outcome value='200'>\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 875,
+ "y": 378,
+ "z": "6d4f912d.f07bc",
+ "wires": [
+ [
+ "49109fbc.a7a14"
+ ]
+ ]
+ },
+ {
+ "id": "f81ed07.2135c3",
+ "type": "other",
+ "name": "other",
+ "xml": "<outcome value='Other'>\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 872,
+ "y": 447,
+ "z": "6d4f912d.f07bc",
+ "wires": [
+ [
+ "6549631f.8e516c"
+ ]
+ ]
+ },
+ {
+ "id": "e59a1a81.112a08",
+ "type": "returnFailure",
+ "name": "return failure",
+ "xml": "<return status='failure'>\n<parameter name='error-code' value='200' />\n<parameter name='error-message' value='`$org.openecomp.appc.adapter.saltstack.message`' />\n<parameter name='output.status.results' value='`$org.openecomp.appc.adapter.saltstack.results`' />\n",
+ "comments": "",
+ "x": 722,
+ "y": 356,
+ "z": "6d4f912d.f07bc",
+ "wires": []
+ },
+ {
+ "id": "6549631f.8e516c",
+ "type": "returnFailure",
+ "name": "return failure",
+ "xml": "<return status='failure'>\n<parameter name='error-code' value='200' />\n<parameter name='error-message' value='`$org.openecomp.appc.adapter.saltstack.message`' />\n<parameter name='output.status.results' value='`$org.openecomp.appc.adapter.saltstack.results`' />\n",
+ "comments": "",
+ "x": 1042,
+ "y": 444,
+ "z": "6d4f912d.f07bc",
+ "wires": []
+ }
+] \ No newline at end of file
diff --git a/adaptors/saltstack-adapter/saltstack-directed-graphs-sample/reqExecSLSFile/APPC_saltstack-adapter-1.0-SLSFILE.xml b/adaptors/saltstack-adapter/saltstack-directed-graphs-sample/reqExecSLSFile/APPC_saltstack-adapter-1.0-SLSFILE.xml
new file mode 100644
index 000000000..2c5e600fc
--- /dev/null
+++ b/adaptors/saltstack-adapter/saltstack-directed-graphs-sample/reqExecSLSFile/APPC_saltstack-adapter-1.0-SLSFILE.xml
@@ -0,0 +1,48 @@
+<service-logic xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
+ xmlns='http://www.onap.org/sdnc/svclogic'
+ xsi:schemaLocation='http://www.onap.org/sdnc/svclogic ./svclogic.xsd'
+ module='APPC' version='2.0.1'>
+ <method rpc='saltstack-adapter-1.0-SLSFILE' mode='sync'>
+ <execute plugin='org.openecomp.appc.adapter.saltstack.SaltstackAdapter'
+ method='reqExecCommand'>
+ <parameter name='HostName' value='`$AgentUrl`'/>
+ <parameter name='Port' value='`$Port`'/>
+ <parameter name='User' value='`$User`'/>
+ <parameter name='Password' value='`$Password`'/>
+ <parameter name='Id' value='test2'/>
+ <parameter name='SlsFile' value='file/location/test-file.sls'/>
+ <outcome value='failure'>
+ <return status='failure'>
+ <parameter name='error-code' value='200'/>
+ <parameter name='error-message'
+ value='`$org.openecomp.appc.adapter.saltstack.message`'/>
+ <parameter name='output.status.results'
+ value='`$org.openecomp.appc.adapter.saltstack.results`'/>
+ </return>
+ </outcome>
+ <outcome value='Other'>
+ <switch test="`$org.onap.appc.adapter.saltstack.result.code`">
+ <outcome value='200'>
+ <return status='success'>
+ <parameter name='output.status.code'
+ value='`$org.openecomp.appc.adapter.saltstack.result.code`'/>
+ <parameter name='output.status.message'
+ value='`$org.openecomp.appc.adapter.saltstack.message`'/>
+ <parameter name='output.status.results'
+ value='`$org.openecomp.appc.adapter.saltstack.results`'/>
+ </return>
+ </outcome>
+ <outcome value='Other'>
+ <return status='failure'>
+ <parameter name='error-code' value='200'/>
+ <parameter name='error-message'
+ value='`$org.openecomp.appc.adapter.saltstack.message`'/>
+ <parameter name='output.status.results'
+ value='`$org.openecomp.appc.adapter.saltstack.results`'/>
+ </return>
+ </outcome>
+ </switch>
+ </outcome>
+ </execute>
+ </method>
+</service-logic> \ No newline at end of file
diff --git a/adaptors/saltstack-adapter/saltstack-directed-graphs-sample/reqExecSLSFile/APPC_saltstack-adapter-1.0-exec-SLSFile-applyTo.json b/adaptors/saltstack-adapter/saltstack-directed-graphs-sample/reqExecSLSFile/APPC_saltstack-adapter-1.0-exec-SLSFile-applyTo.json
new file mode 100644
index 000000000..264950d5e
--- /dev/null
+++ b/adaptors/saltstack-adapter/saltstack-directed-graphs-sample/reqExecSLSFile/APPC_saltstack-adapter-1.0-exec-SLSFile-applyTo.json
@@ -0,0 +1,372 @@
+[
+ {
+ "id": "9a6bf94f.d969f8",
+ "type": "method",
+ "name": "saltstack-adapter-1.0",
+ "xml": "<method rpc='saltstack-adapter-1.0-exec-SLSFile-SlsName' mode='sync'>\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 498,
+ "y": 240,
+ "z": "723548c7.652d78",
+ "wires": [
+ [
+ "138ad7ed.403248"
+ ]
+ ]
+ },
+ {
+ "id": "4bb87049.3f546",
+ "type": "service-logic",
+ "name": "APPC 2.0.1",
+ "module": "APPC",
+ "version": "2.0.1",
+ "comments": "",
+ "xml": "<service-logic xmlns='http://www.onap.org/sdnc/svclogic' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xsi:schemaLocation='http://www.onap.org/sdnc/svclogic ./svclogic.xsd' module='APPC' version='2.0.1'>",
+ "outputs": 1,
+ "x": 289,
+ "y": 318,
+ "z": "723548c7.652d78",
+ "wires": [
+ [
+ "9a6bf94f.d969f8"
+ ]
+ ]
+ },
+ {
+ "id": "6c593992.106038",
+ "type": "returnFailure",
+ "name": "return failure",
+ "xml": "<return status='failure'>\n<parameter name='error-code' value='200' />\n<parameter name='error-message' value='`$org.openecomp.appc.adapter.saltstack.message`' />\n<parameter name='output.status.results' value='`$org.openecomp.appc.adapter.saltstack.results`' />\n",
+ "comments": "",
+ "x": 1202,
+ "y": 280,
+ "z": "723548c7.652d78",
+ "wires": []
+ },
+ {
+ "id": "138ad7ed.403248",
+ "type": "execute",
+ "name": "execute",
+ "xml": "<execute plugin='org.openecomp.appc.adapter.saltstack.SaltstackAdapter' method='reqExecCommand' >\n <parameter name='HostName' value='`$AgentUrl`'/>\n <parameter name='Port' value='`$Port`'/>\n <parameter name='User' value='`$User`'/>\n <parameter name='Password' value='`$Password`'/>\n <parameter name='Id' value='test1'/>\n <parameter name='Cmd' value='salt &apos;*&apos; test.ping --out=json --static'/>\n <parameter name='SlsExec' value='false'/>\n <parameter name='Timeout' value='`$Timeout`'/>\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 706,
+ "y": 246,
+ "z": "723548c7.652d78",
+ "wires": [
+ [
+ "167273ed.f0577c",
+ "954a34ea.701368"
+ ]
+ ]
+ },
+ {
+ "id": "d5841e65.537ba",
+ "type": "switchNode",
+ "name": "switch",
+ "xml": "<switch test=\"`$org.onap.appc.adapter.saltstack.result.code`\">\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 494,
+ "y": 400,
+ "z": "723548c7.652d78",
+ "wires": [
+ [
+ "ede42371.2f52b",
+ "d306d7a0.c830e8"
+ ]
+ ]
+ },
+ {
+ "id": "ede42371.2f52b",
+ "type": "other",
+ "name": "other",
+ "xml": "<outcome value='Other'>\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 680,
+ "y": 458,
+ "z": "723548c7.652d78",
+ "wires": [
+ [
+ "6c593992.106038"
+ ]
+ ]
+ },
+ {
+ "id": "167273ed.f0577c",
+ "type": "failure",
+ "name": "failure",
+ "xml": "<outcome value='failure'>\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 957,
+ "y": 239,
+ "z": "723548c7.652d78",
+ "wires": [
+ [
+ "6c593992.106038"
+ ]
+ ]
+ },
+ {
+ "id": "954a34ea.701368",
+ "type": "other",
+ "name": "other",
+ "xml": "<outcome value='Other'>\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 304,
+ "y": 407,
+ "z": "723548c7.652d78",
+ "wires": [
+ [
+ "d5841e65.537ba"
+ ]
+ ]
+ },
+ {
+ "id": "d306d7a0.c830e8",
+ "type": "success",
+ "name": "success",
+ "xml": "<outcome value='200'>\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 683,
+ "y": 400,
+ "z": "723548c7.652d78",
+ "wires": [
+ [
+ "5b12ba31.94b3b4"
+ ]
+ ]
+ },
+ {
+ "id": "9ef7fcc3.69279",
+ "type": "returnSuccess",
+ "name": "return success",
+ "xml": "<return status='success'>\n<parameter name='output.status.code' value='`$org.openecomp.appc.adapter.saltstack.result.code`' />\n<parameter name='output.status.message' value='`$org.openecomp.appc.adapter.saltstack.message`'/>\n<parameter name='output.status.results' value = '`$org.openecomp.appc.adapter.saltstack.results`'/>\n",
+ "comments": "",
+ "x": 1101,
+ "y": 559,
+ "z": "723548c7.652d78",
+ "wires": []
+ },
+ {
+ "id": "7803eeaf.1e31d",
+ "type": "dgstart",
+ "name": "DGSTART",
+ "outputs": 1,
+ "x": 267,
+ "y": 218,
+ "z": "723548c7.652d78",
+ "wires": [
+ [
+ "4bb87049.3f546"
+ ]
+ ]
+ },
+ {
+ "id": "9c6f1e7c.2a3d9",
+ "type": "comment",
+ "name": "SaltStack Adaptor DG",
+ "info": "",
+ "comments": "",
+ "x": 645,
+ "y": 105,
+ "z": "723548c7.652d78",
+ "wires": []
+ },
+ {
+ "id": "93ea02a5.4e792",
+ "type": "comment",
+ "name": "request-method = reqExecSLS, req-action = \"execute SLS FILE\"",
+ "info": "Here we basically test if minion1 is active by pinging to it, then respective sls file is executed on to it. \n",
+ "comments": "",
+ "x": 656,
+ "y": 190,
+ "z": "723548c7.652d78",
+ "wires": []
+ },
+ {
+ "id": "243edbf.f35fc24",
+ "type": "comment",
+ "name": "Assumptions for this DG (example-server)",
+ "info": "Here we assume, the saltstack server is the example-vagrant based server. Where, the master saltstact controllers minion1 and minion2. ",
+ "comments": "",
+ "x": 648,
+ "y": 146,
+ "z": "723548c7.652d78",
+ "wires": []
+ },
+ {
+ "id": "5b12ba31.94b3b4",
+ "type": "switchNode",
+ "name": "switch",
+ "xml": "<switch test=\"`$test1.minion1`\">\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 847,
+ "y": 400,
+ "z": "723548c7.652d78",
+ "wires": [
+ [
+ "9bf0915.96f217",
+ "f6e533d.95d99d"
+ ]
+ ]
+ },
+ {
+ "id": "9bf0915.96f217",
+ "type": "other",
+ "name": "other",
+ "xml": "<outcome value='Other'>\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 1013,
+ "y": 454,
+ "z": "723548c7.652d78",
+ "wires": [
+ [
+ "6c593992.106038"
+ ]
+ ]
+ },
+ {
+ "id": "f6e533d.95d99d",
+ "type": "other",
+ "name": "outcome",
+ "xml": "<outcome value='true'>\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 1016,
+ "y": 396,
+ "z": "723548c7.652d78",
+ "wires": [
+ [
+ "eb57ba41.1d7328"
+ ]
+ ]
+ },
+ {
+ "id": "eb57ba41.1d7328",
+ "type": "execute",
+ "name": "execute",
+ "xml": "<execute plugin='org.openecomp.appc.adapter.saltstack.SaltstackAdapter' method='reqExecCommand' >\n <parameter name='HostName' value='`$AgentUrl`'/>\n <parameter name='Port' value='`$Port`'/>\n <parameter name='User' value='`$User`'/>\n <parameter name='Password' value='`$Password`'/>\n <parameter name='Id' value='test2'/>\n <parameter name='SlsFile' value='file/location/test.sls'/>\n <parameter name='NodeList' value='minion1'/>\n <parameter name='Timeout' value='`$Timeout`'/>\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 420,
+ "y": 588,
+ "z": "723548c7.652d78",
+ "wires": [
+ [
+ "892a8f1d.7d77f",
+ "74be8a6e.975f24"
+ ]
+ ]
+ },
+ {
+ "id": "892a8f1d.7d77f",
+ "type": "failure",
+ "name": "failure",
+ "xml": "<outcome value='failure'>\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 605,
+ "y": 557,
+ "z": "723548c7.652d78",
+ "wires": [
+ [
+ "8c091fe.c6cbfe"
+ ]
+ ]
+ },
+ {
+ "id": "74be8a6e.975f24",
+ "type": "other",
+ "name": "other",
+ "xml": "<outcome value='Other'>\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 603,
+ "y": 629,
+ "z": "723548c7.652d78",
+ "wires": [
+ [
+ "3875d695.fd37ca"
+ ]
+ ]
+ },
+ {
+ "id": "3875d695.fd37ca",
+ "type": "switchNode",
+ "name": "switch",
+ "xml": "<switch test=\"`$org.onap.appc.adapter.saltstack.result.code`\">\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 755,
+ "y": 617,
+ "z": "723548c7.652d78",
+ "wires": [
+ [
+ "2e60af80.ea3a6",
+ "24ed6dd2.6624c2"
+ ]
+ ]
+ },
+ {
+ "id": "24ed6dd2.6624c2",
+ "type": "success",
+ "name": "success",
+ "xml": "<outcome value='200'>\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 918,
+ "y": 563,
+ "z": "723548c7.652d78",
+ "wires": [
+ [
+ "9ef7fcc3.69279"
+ ]
+ ]
+ },
+ {
+ "id": "2e60af80.ea3a6",
+ "type": "other",
+ "name": "other",
+ "xml": "<outcome value='Other'>\n",
+ "comments": "",
+ "outputs": 1,
+ "x": 915,
+ "y": 632,
+ "z": "723548c7.652d78",
+ "wires": [
+ [
+ "2e4414a7.ba6d4c"
+ ]
+ ]
+ },
+ {
+ "id": "8c091fe.c6cbfe",
+ "type": "returnFailure",
+ "name": "return failure",
+ "xml": "<return status='failure'>\n<parameter name='error-code' value='200' />\n<parameter name='error-message' value='`$org.openecomp.appc.adapter.saltstack.message`' />\n<parameter name='output.status.results' value='`$org.openecomp.appc.adapter.saltstack.results`' />\n",
+ "comments": "",
+ "x": 757,
+ "y": 554,
+ "z": "723548c7.652d78",
+ "wires": []
+ },
+ {
+ "id": "2e4414a7.ba6d4c",
+ "type": "returnFailure",
+ "name": "return failure",
+ "xml": "<return status='failure'>\n<parameter name='error-code' value='200' />\n<parameter name='error-message' value='`$org.openecomp.appc.adapter.saltstack.message`' />\n<parameter name='output.status.results' value='`$org.openecomp.appc.adapter.saltstack.results`' />\n",
+ "comments": "",
+ "x": 1076,
+ "y": 632,
+ "z": "723548c7.652d78",
+ "wires": []
+ }
+] \ No newline at end of file
diff --git a/adaptors/saltstack-adapter/saltstack-directed-graphs-sample/reqExecSLSFile/APPC_saltstack-adapter-1.0-exec-SLSFile-applyTo.xml b/adaptors/saltstack-adapter/saltstack-directed-graphs-sample/reqExecSLSFile/APPC_saltstack-adapter-1.0-exec-SLSFile-applyTo.xml
new file mode 100644
index 000000000..16c573add
--- /dev/null
+++ b/adaptors/saltstack-adapter/saltstack-directed-graphs-sample/reqExecSLSFile/APPC_saltstack-adapter-1.0-exec-SLSFile-applyTo.xml
@@ -0,0 +1,112 @@
+<service-logic xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
+ xmlns='http://www.onap.org/sdnc/svclogic'
+ xsi:schemaLocation='http://www.onap.org/sdnc/svclogic ./svclogic.xsd'
+ module='APPC' version='2.0.1'>
+ <method rpc='saltstack-adapter-1.0-exec-SLSFile-NodeList' mode='sync'>
+ <execute plugin='org.openecomp.appc.adapter.saltstack.SaltstackAdapter'
+ method='reqExecCommand'>
+ <parameter name='HostName' value='`$AgentUrl`'/>
+ <parameter name='Port' value='`$Port`'/>
+ <parameter name='User' value='`$User`'/>
+ <parameter name='Password' value='`$Password`'/>
+ <parameter name='Id' value='test1'/>
+ <parameter name='Cmd'
+ value='salt &apos;*&apos; test.ping --out=json --static'/>
+ <parameter name='SlsExec' value='false'/>
+ <parameter name='Timeout' value='`$Timeout`'/>
+ <outcome value='failure'>
+ <return status='failure'>
+ <parameter name='error-code' value='200'/>
+ <parameter name='error-message'
+ value='`$org.openecomp.appc.adapter.saltstack.message`'/>
+ <parameter name='output.status.results'
+ value='`$org.openecomp.appc.adapter.saltstack.results`'/>
+ </return>
+ </outcome>
+ <outcome value='Other'>
+ <switch test="`$org.onap.appc.adapter.saltstack.result.code`">
+ <outcome value='200'>
+ <switch test="`$test1.minion1`">
+ <outcome value='true'>
+ <execute
+ plugin='org.openecomp.appc.adapter.saltstack.SaltstackAdapter'
+ method='reqExecCommand'>
+ <parameter name='HostName'
+ value='`$AgentUrl`'/>
+ <parameter name='Port' value='`$Port`'/>
+ <parameter name='User' value='`$User`'/>
+ <parameter name='Password'
+ value='`$Password`'/>
+ <parameter name='Id' value='test2'/>
+ <parameter name='SlsFile'
+ value='file/location/test.sls'/>
+ <parameter name='NodeList' value='minion1'/>
+ <parameter name='Timeout'
+ value='`$Timeout`'/>
+ <outcome value='failure'>
+ <return status='failure'>
+ <parameter name='error-code'
+ value='200'/>
+ <parameter name='error-message'
+ value='`$org.openecomp.appc.adapter.saltstack.message`'/>
+ <parameter
+ name='output.status.results'
+ value='`$org.openecomp.appc.adapter.saltstack.results`'/>
+ </return>
+ </outcome>
+ <outcome value='Other'>
+ <switch test="`$org.onap.appc.adapter.saltstack.result.code`">
+ <outcome value='200'>
+ <return status='success'>
+ <parameter
+ name='output.status.code'
+ value='`$org.openecomp.appc.adapter.saltstack.result.code`'/>
+ <parameter
+ name='output.status.message'
+ value='`$org.openecomp.appc.adapter.saltstack.message`'/>
+ <parameter
+ name='output.status.results'
+ value='`$org.openecomp.appc.adapter.saltstack.results`'/>
+ </return>
+ </outcome>
+ <outcome value='Other'>
+ <return status='failure'>
+ <parameter name='error-code'
+ value='200'/>
+ <parameter
+ name='error-message'
+ value='`$org.openecomp.appc.adapter.saltstack.message`'/>
+ <parameter
+ name='output.status.results'
+ value='`$org.openecomp.appc.adapter.saltstack.results`'/>
+ </return>
+ </outcome>
+ </switch>
+ </outcome>
+ </execute>
+ </outcome>
+ <outcome value='Other'>
+ <return status='failure'>
+ <parameter name='error-code' value='200'/>
+ <parameter name='error-message'
+ value='`$org.openecomp.appc.adapter.saltstack.message`'/>
+ <parameter name='output.status.results'
+ value='`$org.openecomp.appc.adapter.saltstack.results`'/>
+ </return>
+ </outcome>
+ </switch>
+ </outcome>
+ <outcome value='Other'>
+ <return status='failure'>
+ <parameter name='error-code' value='200'/>
+ <parameter name='error-message'
+ value='`$org.openecomp.appc.adapter.saltstack.message`'/>
+ <parameter name='output.status.results'
+ value='`$org.openecomp.appc.adapter.saltstack.results`'/>
+ </return>
+ </outcome>
+ </switch>
+ </outcome>
+ </execute>
+ </method>
+</service-logic> \ No newline at end of file
diff --git a/adaptors/sql-resource/.gitignore b/adaptors/sql-resource/.gitignore
new file mode 100755
index 000000000..b73caf31e
--- /dev/null
+++ b/adaptors/sql-resource/.gitignore
@@ -0,0 +1,34 @@
+#####standard .git ignore entries#####
+
+## IDE Specific Files ##
+org.eclipse.core.resources.prefs
+.classpath
+.project
+.settings
+.idea
+.externalToolBuilders
+maven-eclipse.xml
+workspace
+
+## Compilation Files ##
+*.class
+**/target
+target
+target-ide
+MANIFEST.MF
+
+## Misc Ignores (OS specific etc) ##
+bin/
+dist
+*~
+*.ipr
+*.iml
+*.iws
+classes
+out/
+.DS_STORE
+.metadata
+
+## Folders which contain auto generated source code ##
+yang-gen-config
+yang-gen-sal
diff --git a/adaptors/sql-resource/installer/pom.xml b/adaptors/sql-resource/installer/pom.xml
new file mode 100755
index 000000000..5ec885ce0
--- /dev/null
+++ b/adaptors/sql-resource/installer/pom.xml
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>odlparent-lite</artifactId>
+ <version>2.1.0</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.adaptors</groupId>
+ <artifactId>sql-resource-installer</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>pom</packaging>
+
+ <name>ccsdk-sli-adaptors :: sql-resource :: ${project.artifactId}</name>
+
+ <properties>
+ <application.name>ccsdk-sql-resource</application.name>
+ <features.boot>${application.name}</features.boot>
+ <features.repositories>mvn:org.onap.ccsdk.sli.adaptors/${features.boot}/${project.version}/xml/features</features.repositories>
+ <include.transitive.dependencies>false</include.transitive.dependencies>
+ </properties>
+
+ <dependencies>
+
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.adaptors</groupId>
+ <artifactId>sql-resource-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <version>2.6</version>
+ <executions>
+ <execution>
+ <id>maven-repo-zip</id>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ <phase>package</phase>
+ <configuration>
+ <attach>true</attach>
+ <finalName>stage/${application.name}-${project.version}</finalName>
+ <descriptors>
+ <descriptor>src/assembly/assemble_mvnrepo_zip.xml</descriptor>
+ </descriptors>
+ <appendAssemblyId>true</appendAssemblyId>
+ </configuration>
+ </execution>
+ <execution>
+ <id>installer-zip</id>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ <phase>package</phase>
+ <configuration>
+ <attach>true</attach>
+ <finalName>${application.name}-${project.version}-installer</finalName>
+ <descriptors>
+ <descriptor>src/assembly/assemble_installer_zip.xml</descriptor>
+ </descriptors>
+ <appendAssemblyId>false</appendAssemblyId>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>copy-dependencies</id>
+ <goals>
+ <goal>copy-dependencies</goal>
+ </goals>
+ <phase>prepare-package</phase>
+ <configuration>
+ <transitive>false</transitive>
+ <outputDirectory>${project.build.directory}/assembly/system</outputDirectory>
+ <overWriteReleases>false</overWriteReleases>
+ <overWriteSnapshots>true</overWriteSnapshots>
+ <overWriteIfNewer>true</overWriteIfNewer>
+ <useRepositoryLayout>true</useRepositoryLayout>
+ <addParentPoms>false</addParentPoms>
+ <copyPom>false</copyPom>
+ <includeGroupIds>org.onap.ccsdk.sli.adaptor</includeGroupIds>
+ <scope>provided</scope>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <artifactId>maven-resources-plugin</artifactId>
+ <version>2.6</version>
+ <executions>
+ <execution>
+ <id>copy-version</id>
+ <goals>
+ <goal>copy-resources</goal>
+ </goals><!-- here the phase you need -->
+ <phase>validate</phase>
+ <configuration>
+ <outputDirectory>${basedir}/target/stage</outputDirectory>
+ <resources>
+ <resource>
+ <directory>src/main/resources/scripts</directory>
+ <includes>
+ <include>install-feature.sh</include>
+ </includes>
+ <filtering>true</filtering>
+ </resource>
+ </resources>
+ </configuration>
+ </execution>
+
+ </executions>
+ </plugin>
+
+ </plugins>
+ </build>
+</project>
diff --git a/adaptors/sql-resource/installer/src/assembly/assemble_installer_zip.xml b/adaptors/sql-resource/installer/src/assembly/assemble_installer_zip.xml
new file mode 100644
index 000000000..3bed4b5ef
--- /dev/null
+++ b/adaptors/sql-resource/installer/src/assembly/assemble_installer_zip.xml
@@ -0,0 +1,59 @@
+<!--
+ ============LICENSE_START=======================================================
+ openECOMP : SDN-C
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property. All rights
+ reserved.
+ ================================================================================
+ 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.
+ ============LICENSE_END=========================================================
+ -->
+
+<!-- Defines how we build the .zip file which is our distribution. -->
+
+<assembly
+ xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
+ <id>installer_zip</id>
+ <formats>
+ <format>zip</format>
+ </formats>
+
+ <!-- we want "system" and related files right at the root level
+ as this file is suppose to be unzip on top of a karaf
+ distro. -->
+ <includeBaseDirectory>false</includeBaseDirectory>
+
+ <fileSets>
+ <fileSet>
+ <directory>target/stage/</directory>
+ <outputDirectory>${application.name}</outputDirectory>
+ <fileMode>755</fileMode>
+ <includes>
+ <include>*.sh</include>
+ </includes>
+ </fileSet>
+ <fileSet>
+ <directory>target/stage/</directory>
+ <outputDirectory>${application.name}</outputDirectory>
+ <fileMode>644</fileMode>
+ <excludes>
+ <exclude>*.sh</exclude>
+ </excludes>
+ </fileSet>
+ </fileSets>
+
+
+
+</assembly>
diff --git a/adaptors/sql-resource/installer/src/assembly/assemble_mvnrepo_zip.xml b/adaptors/sql-resource/installer/src/assembly/assemble_mvnrepo_zip.xml
new file mode 100644
index 000000000..35e79db18
--- /dev/null
+++ b/adaptors/sql-resource/installer/src/assembly/assemble_mvnrepo_zip.xml
@@ -0,0 +1,49 @@
+<!--
+ ============LICENSE_START=======================================================
+ openECOMP : SDN-C
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property. All rights
+ reserved.
+ ================================================================================
+ 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.
+ ============LICENSE_END=========================================================
+ -->
+
+<!-- Defines how we build the .zip file which is our distribution. -->
+
+<assembly
+ xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
+ <id>repo</id>
+ <formats>
+ <format>zip</format>
+ </formats>
+
+ <!-- we want "system" and related files right at the root level
+ as this file is suppose to be unzip on top of a karaf
+ distro. -->
+ <includeBaseDirectory>false</includeBaseDirectory>
+
+ <fileSets>
+ <fileSet>
+ <directory>target/assembly/</directory>
+ <outputDirectory>.</outputDirectory>
+ <excludes>
+ </excludes>
+ </fileSet>
+ </fileSets>
+
+
+
+</assembly>
diff --git a/adaptors/sql-resource/installer/src/main/resources/scripts/install-feature.sh b/adaptors/sql-resource/installer/src/main/resources/scripts/install-feature.sh
new file mode 100644
index 000000000..cee4a4952
--- /dev/null
+++ b/adaptors/sql-resource/installer/src/main/resources/scripts/install-feature.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+
+###
+# ============LICENSE_START=======================================================
+# openECOMP : SDN-C
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights
+# reserved.
+# ================================================================================
+# 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.
+# ============LICENSE_END=========================================================
+###
+
+ODL_HOME=${ODL_HOME:-/opt/opendaylight/current}
+ODL_KARAF_CLIENT=${ODL_KARAF_CLIENT:-${ODL_HOME}/bin/client}
+INSTALLERDIR=$(dirname $0)
+
+REPOZIP=${INSTALLERDIR}/${features.boot}-${project.version}.zip
+
+if [ -f ${REPOZIP} ]
+then
+ unzip -d ${ODL_HOME} ${REPOZIP}
+else
+ echo "ERROR : repo zip ($REPOZIP) not found"
+ exit 1
+fi
+
+${ODL_KARAF_CLIENT} feature:repo-add ${features.repositories}
+${ODL_KARAF_CLIENT} feature:install ${features.boot}
diff --git a/adaptors/sql-resource/pom.xml b/adaptors/sql-resource/pom.xml
new file mode 100755
index 000000000..5cbee1089
--- /dev/null
+++ b/adaptors/sql-resource/pom.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>odlparent-lite</artifactId>
+ <version>2.1.0</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.adaptors</groupId>
+ <artifactId>sql-resource</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>pom</packaging>
+
+ <name>ccsdk-sli-adaptors :: sql-resource</name>
+ <description>The Sql resource adaptor allows service logic to read/write data from a local database using direct SQL statements</description>
+
+ <modules>
+ <module>provider</module>
+ <module>installer</module>
+ </modules>
+</project>
diff --git a/adaptors/sql-resource/provider/pom.xml b/adaptors/sql-resource/provider/pom.xml
new file mode 100755
index 000000000..94b0225c9
--- /dev/null
+++ b/adaptors/sql-resource/provider/pom.xml
@@ -0,0 +1,83 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>binding-parent</artifactId>
+ <version>2.1.0</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.adaptors</groupId>
+ <artifactId>sql-resource-provider</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>bundle</packaging>
+
+ <name>ccsdk-sli-adaptors :: sql-resource :: ${project.artifactId}</name>
+ <url>http://maven.apache.org</url>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <ccsdk.sli.adaptors.version>${project.version}</ccsdk.sli.adaptors.version>
+ </properties>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sli-core-artifacts</artifactId>
+ <version>${ccsdk.sli.core.version}</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>ch.vorburger.mariaDB4j</groupId>
+ <artifactId>mariaDB4j</artifactId>
+ <version>2.2.3</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sli-common</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sli-provider</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>jcl-over-slf4j</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-simple</artifactId>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>dblib-provider</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.core</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/adaptors/sql-resource/provider/src/main/java/org/onap/ccsdk/sli/adaptors/resource/sql/SqlResource.java b/adaptors/sql-resource/provider/src/main/java/org/onap/ccsdk/sli/adaptors/resource/sql/SqlResource.java
new file mode 100755
index 000000000..435bc5bb1
--- /dev/null
+++ b/adaptors/sql-resource/provider/src/main/java/org/onap/ccsdk/sli/adaptors/resource/sql/SqlResource.java
@@ -0,0 +1,551 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.resource.sql;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Properties;
+
+import javax.sql.rowset.CachedRowSet;
+
+import org.apache.commons.lang3.StringUtils;
+import org.onap.ccsdk.sli.core.dblib.DBResourceManager;
+import org.onap.ccsdk.sli.core.dblib.DbLibService;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.core.sli.SvcLogicJavaPlugin;
+import org.onap.ccsdk.sli.core.sli.SvcLogicResource;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.ServiceReference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class SqlResource implements SvcLogicResource, SvcLogicJavaPlugin {
+
+ private static final Logger LOG = LoggerFactory.getLogger(SqlResource.class);
+
+ private static final String DBLIB_SERVICE = "org.onap.ccsdk.sli.core.dblib.DbLibService";
+
+ private static String CRYPT_KEY = "QtfJMKggVk";
+
+ DbLibService dblibSvc = null;
+
+ public SqlResource() {
+ this(new SqlResourcePropertiesProviderImpl(), null);
+ }
+
+ public SqlResource(SqlResourcePropertiesProvider propProvider) {
+ this(propProvider, null);
+ }
+
+ public SqlResource(SqlResourcePropertiesProvider propProvider, DbLibService dblibSvc) {
+
+ this.dblibSvc = dblibSvc;
+
+ Properties properties = propProvider.getProperties();
+
+ String cryptKey = properties.getProperty("org.onap.sdnc.resource.sql.cryptkey");
+
+ if ((cryptKey == null) || (cryptKey.length() == 0)) {
+ cryptKey = properties.getProperty("org.openecomp.sdnc.resource.sql.cryptkey");
+ }
+
+ SqlResource.setCryptKey(cryptKey);
+ }
+
+ // For sql-resource, is-available is the same as exists
+ @Override
+ public QueryStatus isAvailable(String resource, String key, String prefix, SvcLogicContext ctx)
+ throws SvcLogicException {
+
+ return (exists(resource, key, prefix, ctx));
+
+ }
+
+ @Override
+ public QueryStatus exists(String resource, String key, String prefix, SvcLogicContext ctx)
+ throws SvcLogicException {
+
+ DbLibService dblibSvc = getDbLibService();
+ if (dblibSvc == null) {
+ return (QueryStatus.FAILURE);
+ }
+
+ String theStmt = resolveCtxVars(key, ctx, resource);
+
+ try {
+ CachedRowSet results = dblibSvc.getData(theStmt, null, null);
+
+ if (!results.next()) {
+ return (QueryStatus.NOT_FOUND);
+ }
+
+ int numRows = results.getInt(1);
+
+ if (numRows > 0) {
+ return (QueryStatus.SUCCESS);
+ } else {
+ return (QueryStatus.NOT_FOUND);
+ }
+ } catch (Exception e) {
+ LOG.error("Caught SQL exception", e);
+ return (QueryStatus.FAILURE);
+ }
+ }
+
+ // @Override
+ public QueryStatus query(String resource, boolean localOnly, String select, String key, String prefix,
+ String orderBy, SvcLogicContext ctx) throws SvcLogicException {
+
+ DbLibService dblibSvc = getDbLibService();
+
+ if (dblibSvc == null) {
+ return (QueryStatus.FAILURE);
+ }
+
+ String sqlQuery = resolveCtxVars(key, ctx, resource);
+
+
+ try {
+
+ CachedRowSet results = dblibSvc.getData(sqlQuery, null, null);
+
+ QueryStatus retval = QueryStatus.SUCCESS;
+
+ if (!results.next()) {
+ retval = QueryStatus.NOT_FOUND;
+ LOG.debug("No data found");
+ } else {
+ saveCachedRowSetToCtx(results, ctx, prefix, dblibSvc);
+ }
+ return (retval);
+ } catch (Exception e) {
+ LOG.error("Caught SQL exception", e);
+ return (QueryStatus.FAILURE);
+ }
+ }
+
+ public void saveCachedRowSetToCtx(CachedRowSet results, SvcLogicContext ctx, String prefix, DbLibService dblibSvc)
+ throws SQLException {
+ if (ctx != null) {
+ if ((prefix != null) && prefix.endsWith("[]")) {
+ // Return an array.
+ String pfx = prefix.substring(0, prefix.length() - 2);
+ int idx = 0;
+ do {
+ ResultSetMetaData rsMeta = results.getMetaData();
+ int numCols = rsMeta.getColumnCount();
+
+ for (int i = 0; i < numCols; i++) {
+ String colValue = null;
+ String tableName = rsMeta.getTableName(i + 1);
+ if (rsMeta.getColumnType(i + 1) == java.sql.Types.VARBINARY) {
+ colValue = decryptColumn(tableName, rsMeta.getColumnName(i + 1), results.getBytes(i + 1),
+ dblibSvc);
+ } else {
+ colValue = results.getString(i + 1);
+ }
+ LOG.debug("Setting " + pfx + "[" + idx + "]."
+ + rsMeta.getColumnLabel(i + 1).replaceAll("_", "-") + " = " + colValue);
+ ctx.setAttribute(pfx + "[" + idx + "]." + rsMeta.getColumnLabel(i + 1).replaceAll("_", "-"),
+ colValue);
+ }
+ idx++;
+ } while (results.next());
+ LOG.debug("Setting " + pfx + "_length = " + idx);
+ ctx.setAttribute(pfx + "_length", "" + idx);
+ } else {
+ ResultSetMetaData rsMeta = results.getMetaData();
+ int numCols = rsMeta.getColumnCount();
+
+ for (int i = 0; i < numCols; i++) {
+ String colValue = null;
+ String tableName = rsMeta.getTableName(i + 1);
+ if ("VARBINARY".equalsIgnoreCase(rsMeta.getColumnTypeName(i + 1))) {
+ colValue = decryptColumn(tableName, rsMeta.getColumnName(i + 1), results.getBytes(i + 1),
+ dblibSvc);
+ } else {
+ colValue = results.getString(i + 1);
+ }
+ if (prefix != null) {
+ LOG.debug("Setting " + prefix + "." + rsMeta.getColumnLabel(i + 1).replaceAll("_", "-") + " = "
+ + colValue);
+ ctx.setAttribute(prefix + "." + rsMeta.getColumnLabel(i + 1).replaceAll("_", "-"), colValue);
+ } else {
+ LOG.debug("Setting " + rsMeta.getColumnLabel(i + 1).replaceAll("_", "-") + " = " + colValue);
+ ctx.setAttribute(rsMeta.getColumnLabel(i + 1).replaceAll("_", "-"), colValue);
+ }
+ }
+ }
+ }
+ }
+
+ // reserve is no-op
+ @Override
+ public QueryStatus reserve(String resource, String select, String key, String prefix, SvcLogicContext ctx)
+ throws SvcLogicException {
+ return (QueryStatus.SUCCESS);
+ }
+
+ // release is no-op
+ @Override
+ public QueryStatus release(String resource, String key, SvcLogicContext ctx) throws SvcLogicException {
+ return (QueryStatus.SUCCESS);
+ }
+
+ private QueryStatus executeSqlWrite(String key, SvcLogicContext ctx) throws SvcLogicException {
+ QueryStatus retval = QueryStatus.SUCCESS;
+
+ DbLibService dblibSvc = getDbLibService();
+
+ if (dblibSvc == null) {
+ return (QueryStatus.FAILURE);
+ }
+
+ String sqlStmt = resolveCtxVars(key, ctx, "");
+
+ LOG.debug("key = [" + key + "]; sqlStmt = [" + sqlStmt + "]");
+ try {
+
+ if (!dblibSvc.writeData(sqlStmt, null, null)) {
+ retval = QueryStatus.FAILURE;
+ }
+ } catch (Exception e) {
+ LOG.error("Caught SQL exception", e);
+ retval = QueryStatus.FAILURE;
+ }
+
+ return (retval);
+
+ }
+
+ private String resolveCtxVars(String key, SvcLogicContext ctx, String resource) {
+ if (key == null) {
+ return (null);
+ }
+
+ if (key.startsWith("'") && key.endsWith("'")) {
+ key = key.substring(1, key.length() - 1);
+ LOG.debug("Stripped outer single quotes - key is now [" + key + "]");
+ }
+
+ //"SQL-TRUE" allows for the key to be used as is.
+ if (!resource.equals("SQL-TRUE")) {
+ String[] keyTerms = key.split("\\s+");
+
+ StringBuffer sqlBuffer = new StringBuffer();
+
+ for (int i = 0; i < keyTerms.length; i++) {
+ sqlBuffer.append(resolveTerm(keyTerms[i], ctx));
+ sqlBuffer.append(" ");
+ }
+ key = sqlBuffer.toString();
+ }
+
+ return (key);
+ }
+
+ private String resolveTerm(String term, SvcLogicContext ctx) {
+ if (term == null) {
+ return (null);
+ }
+
+ LOG.trace("resolveTerm: term is " + term);
+
+ if (term.startsWith("$") && (ctx != null)) {
+ // Resolve any index variables.
+ term = resolveCtxVariable(term.substring(1), ctx);
+ // Escape single quote
+ if (term != null) {
+ term = term.replaceAll("'", "''");
+ }
+ return ("'" + term + "'");
+ } else {
+ return (term);
+ }
+
+ }
+
+ private String resolveCtxVariable(String ctxVarName, SvcLogicContext ctx) {
+
+ if (ctxVarName.indexOf('[') == -1) {
+ // Ctx variable contains no arrays
+ if ("CRYPT_KEY".equals(ctxVarName)) {
+ // Handle crypt key as special case. If it's set as a context
+ // variable, use it. Otherwise, use
+ // configured crypt key.
+ String cryptKey = ctx.getAttribute(ctxVarName);
+ if ((cryptKey != null) && (cryptKey.length() > 0)) {
+ return (cryptKey);
+ } else {
+ return (CRYPT_KEY);
+ }
+ }
+ return (ctx.getAttribute(ctxVarName));
+ }
+
+ // Resolve any array references
+ StringBuffer sbuff = new StringBuffer();
+ String[] ctxVarParts = ctxVarName.split("\\[");
+ sbuff.append(ctxVarParts[0]);
+ for (int i = 1; i < ctxVarParts.length; i++) {
+ if (ctxVarParts[i].startsWith("$")) {
+ int endBracketLoc = ctxVarParts[i].indexOf("]");
+ if (endBracketLoc == -1) {
+ // Missing end bracket ... give up parsing
+ LOG.warn("Variable reference " + ctxVarName + " seems to be missing a ']'");
+ return (ctx.getAttribute(ctxVarName));
+ }
+
+ String idxVarName = ctxVarParts[i].substring(1, endBracketLoc);
+ String remainder = ctxVarParts[i].substring(endBracketLoc);
+
+ sbuff.append("[");
+ sbuff.append(ctx.getAttribute(idxVarName));
+ sbuff.append(remainder);
+
+ } else {
+ // Index is not a variable reference
+ sbuff.append("[");
+ sbuff.append(ctxVarParts[i]);
+ }
+ }
+
+ return (ctx.getAttribute(sbuff.toString()));
+ }
+
+ @Override
+ public QueryStatus save(String resource, boolean force, boolean localOnly, String key, Map<String, String> parms,
+ String prefix, SvcLogicContext ctx) throws SvcLogicException {
+ return (executeSqlWrite(key, ctx));
+ }
+
+ private DbLibService getDbLibService() {
+
+ if (dblibSvc != null) {
+ return(dblibSvc);
+ }
+ // Try to get dblib as an OSGI service
+
+ try {
+ BundleContext bctx = null;
+ ServiceReference sref = null;
+
+
+
+ Bundle bundle = FrameworkUtil.getBundle(SqlResource.class);
+
+ if (bundle != null) {
+ bctx = bundle.getBundleContext();
+ }
+
+ if (bctx != null) {
+ sref = bctx.getServiceReference(DBLIB_SERVICE);
+ }
+
+ if (sref == null) {
+ LOG.warn("Could not find service reference for DBLIB service (" + DBLIB_SERVICE + ")");
+ } else {
+ dblibSvc = (DbLibService) bctx.getService(sref);
+ if (dblibSvc == null) {
+ LOG.warn("Could not find service reference for DBLIB service (" + DBLIB_SERVICE + ")");
+ }
+ }
+ } catch (NoClassDefFoundError ex) {
+ LOG.info("OSGI classes not found - must be running outside an OSGi container");
+ }
+
+
+ if (dblibSvc == null) {
+ // Must not be running in an OSGI container. See if you can load it
+ // as a
+ // a POJO then.
+
+ // If $SDNC_CONFIG_DIR/dblib.properties exists, that should
+ // be the properties passed to DBResourceManager constructor.
+ // If not, as default just use system properties.
+ Properties dblibProps = System.getProperties();
+
+ String cfgDir = dblibProps.getProperty("sdnc.config.dir", System.getenv("SDNC_CONFIG_DIR"));
+
+ if ((cfgDir == null) || (cfgDir.length() == 0)) {
+ cfgDir = "/opt/sdnc/data/properties";
+ }
+
+ File dblibPropFile = new File(cfgDir + "/dblib.properties");
+ if (dblibPropFile.exists()) {
+ try {
+ LOG.debug("Loading dblib properties from {}", dblibPropFile.getAbsolutePath());
+ dblibProps = new Properties();
+ dblibProps.load(new FileInputStream(dblibPropFile));
+ } catch (Exception e) {
+ LOG.warn("Could not load properties file {}", dblibPropFile.getAbsolutePath(), e);
+
+ dblibProps = System.getProperties();
+ }
+ }
+
+ try {
+ dblibSvc = new DBResourceManager(dblibProps);
+ } catch (Exception e) {
+ LOG.error("Caught exception trying to create dblib service", e);
+ }
+
+ if (dblibSvc == null) {
+ LOG.warn("Could not create new DBResourceManager");
+ }
+ }
+
+ return (dblibSvc);
+ }
+
+ @Override
+ public QueryStatus notify(String resource, String action, String key, SvcLogicContext ctx)
+ throws SvcLogicException {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("SqlResource.notify called with resource=" + resource + ", action=" + action);
+ }
+ return QueryStatus.SUCCESS;
+ }
+
+ @Override
+ public QueryStatus delete(String resource, String key, SvcLogicContext ctx) throws SvcLogicException {
+ return (executeSqlWrite(key, ctx));
+ }
+
+ public QueryStatus update(String resource, String key, Map<String, String> parms, String prefix,
+ SvcLogicContext ctx) throws SvcLogicException {
+ return (executeSqlWrite(key, ctx));
+ }
+
+ private String decryptColumn(String tableName, String colName, byte[] colValue, DbLibService dblibSvc) {
+ String strValue = new String(colValue);
+
+ if (StringUtils.isAsciiPrintable(strValue)) {
+
+ // If printable, not encrypted
+ return (strValue);
+ } else {
+ ResultSet results = null;
+ try (Connection conn = dblibSvc.getConnection();
+ PreparedStatement stmt = conn.prepareStatement("SELECT CAST(AES_DECRYPT(?, ?) AS CHAR(50)) FROM DUAL")) {
+
+ stmt.setBytes(1, colValue);
+ stmt.setString(2, getCryptKey());
+ results = stmt.executeQuery();
+
+ if ((results != null) && results.next()) {
+ strValue = results.getString(1);
+ LOG.debug("Decrypted value is " + strValue);
+ } else {
+ LOG.warn("Cannot decrypt " + tableName + "." + colName);
+ }
+ } catch (Exception e) {
+ LOG.error("Caught exception trying to decrypt " + tableName + "." + colName, e);
+ }finally {
+ if (results != null) {
+ try {
+ results.close();
+ } catch (SQLException se) {
+ LOG.error("Caught exception trying to close ResultSet",se);
+ }
+ }
+ }
+ }
+ return (strValue);
+ }
+
+ public static String getCryptKey() {
+ return (CRYPT_KEY);
+ }
+
+ public static String setCryptKey(String key) {
+ CRYPT_KEY = key;
+ return (CRYPT_KEY);
+ }
+
+ public String parameterizedQuery(Map<String, String> parameters, SvcLogicContext ctx) throws SvcLogicException {
+ DbLibService dblibSvc = getDbLibService();
+ String prefix = parameters.get("prefix");
+ String query = parameters.get("query");
+
+ ArrayList<String> arguments = new ArrayList<String>();
+ for (Entry<String, String> a : parameters.entrySet()) {
+ if (a.getKey().startsWith("param")) {
+ arguments.add(a.getValue());
+ }
+ }
+
+ try {
+ if (dblibSvc == null) {
+ return mapQueryStatus(QueryStatus.FAILURE);
+ }
+ if (query.contains("count") || query.contains("COUNT")) {
+ CachedRowSet results = dblibSvc.getData(query, arguments, null);
+
+ if (!results.next()) {
+ return mapQueryStatus(QueryStatus.FAILURE);
+ }
+
+ int numRows = results.getInt(1);
+ ctx.setAttribute(prefix + ".count", String.valueOf(numRows));
+ if (numRows > 0) {
+ return "true";
+ } else {
+ return "false";
+ }
+ } else if (query.startsWith("select") || query.startsWith("SELECT")) {
+ CachedRowSet results = dblibSvc.getData(query, arguments, null);
+ if (!results.next()) {
+ return mapQueryStatus(QueryStatus.NOT_FOUND);
+ } else {
+ saveCachedRowSetToCtx(results, ctx, prefix, dblibSvc);
+ }
+ } else {
+ if (!dblibSvc.writeData(query, arguments, null)) {
+ return mapQueryStatus(QueryStatus.FAILURE);
+ }
+ }
+ return mapQueryStatus(QueryStatus.SUCCESS);
+ } catch (SQLException e) {
+ LOG.error("Caught SQL exception", e);
+ return mapQueryStatus(QueryStatus.FAILURE);
+ }
+ }
+
+ protected String mapQueryStatus(QueryStatus status) {
+ String str = status.toString();
+ str = str.toLowerCase();
+ str = str.replaceAll("_", "-");
+ return str;
+ }
+}
diff --git a/adaptors/sql-resource/provider/src/main/java/org/onap/ccsdk/sli/adaptors/resource/sql/SqlResourcePropertiesProvider.java b/adaptors/sql-resource/provider/src/main/java/org/onap/ccsdk/sli/adaptors/resource/sql/SqlResourcePropertiesProvider.java
new file mode 100755
index 000000000..7970151da
--- /dev/null
+++ b/adaptors/sql-resource/provider/src/main/java/org/onap/ccsdk/sli/adaptors/resource/sql/SqlResourcePropertiesProvider.java
@@ -0,0 +1,28 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * onap
+ * ================================================================================
+ * Copyright (C) 2016 - 2017 ONAP
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.resource.sql;
+
+import java.util.Properties;
+
+public interface SqlResourcePropertiesProvider {
+
+ public Properties getProperties();
+}
diff --git a/adaptors/sql-resource/provider/src/main/java/org/onap/ccsdk/sli/adaptors/resource/sql/SqlResourcePropertiesProviderImpl.java b/adaptors/sql-resource/provider/src/main/java/org/onap/ccsdk/sli/adaptors/resource/sql/SqlResourcePropertiesProviderImpl.java
new file mode 100755
index 000000000..7c9f6f161
--- /dev/null
+++ b/adaptors/sql-resource/provider/src/main/java/org/onap/ccsdk/sli/adaptors/resource/sql/SqlResourcePropertiesProviderImpl.java
@@ -0,0 +1,186 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * onap
+ * ================================================================================
+ * Copyright (C) 2016 - 2017 ONAP
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.resource.sql;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Optional;
+import java.util.Properties;
+import java.util.Vector;
+
+import org.onap.ccsdk.sli.core.sli.ConfigurationException;
+import org.onap.ccsdk.sli.core.utils.JREFileResolver;
+import org.onap.ccsdk.sli.core.utils.KarafRootFileResolver;
+import org.onap.ccsdk.sli.core.utils.PropertiesFileResolver;
+import org.onap.ccsdk.sli.core.utils.common.CoreDefaultFileResolver;
+import org.onap.ccsdk.sli.core.utils.common.SdncConfigEnvVarFileResolver;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Responsible for determining the properties file to use and instantiating the
+ * <code>SqlResource</code> Service. The priority for properties file
+ * resolution is as follows:
+ *
+ * <ol>
+ * <li>A directory identified by the system environment variable
+ * <code>SDNC_CONFIG_DIR</code></li>
+ * <li>The default directory <code>DEFAULT_DBLIB_PROP_DIR</code></li>
+ * <li>A directory identified by the JRE argument
+ * <code>sql-resource.properties</code></li>
+ * <li>A <code>sql-resource.properties</code> file located in the karaf root
+ * directory</li>
+ * </ol>
+ */
+public class SqlResourcePropertiesProviderImpl implements SqlResourcePropertiesProvider {
+
+ private static final Logger LOG = LoggerFactory.getLogger(SqlResourcePropertiesProviderImpl.class);
+
+ /**
+ * The name of the properties file for database configuration
+ */
+ private static final String SQLRESOURCE_PROP_FILE_NAME = "sql-resource.properties";
+
+ /**
+ * A prioritized list of strategies for resolving sql-resource properties files.
+ */
+ private Vector<PropertiesFileResolver> sqlResourcePropertiesFileResolvers = new Vector<>();
+
+ /**
+ * The configuration properties for the db connection.
+ */
+ private Properties properties;
+
+ /**
+ * Set up the prioritized list of strategies for resolving dblib properties
+ * files.
+ */
+ public SqlResourcePropertiesProviderImpl() {
+ sqlResourcePropertiesFileResolvers
+ .add(new SdncConfigEnvVarFileResolver("Using property file (1) from environment variable"));
+ sqlResourcePropertiesFileResolvers.add(new CoreDefaultFileResolver("Using property file (2) from default directory"));
+
+ sqlResourcePropertiesFileResolvers.add(
+ new JREFileResolver("Using property file (3) from JRE argument", SqlResourcePropertiesProviderImpl.class));
+ sqlResourcePropertiesFileResolvers.add(new KarafRootFileResolver("Using property file (4) from karaf root", this));
+
+ // determines properties file as according to the priority described in the
+ // class header comment
+ final File propertiesFile = determinePropertiesFile(this);
+ if (propertiesFile != null) {
+ try (FileInputStream fileInputStream = new FileInputStream(propertiesFile)) {
+ properties = new Properties();
+ properties.load(fileInputStream);
+ } catch (final IOException e) {
+ LOG.error("Failed to load properties for file: {}", propertiesFile.toString(),
+ new ConfigurationException("Failed to load properties for file: " + propertiesFile.toString(),
+ e));
+ }
+ } else {
+ // Try to read properties as resource
+
+ InputStream propStr = getClass().getResourceAsStream("/" + SQLRESOURCE_PROP_FILE_NAME);
+ if (propStr != null) {
+ properties = new Properties();
+ try {
+ properties.load(propStr);
+ propStr.close();
+ } catch (IOException e) {
+ properties = null;
+ }
+ }
+
+ }
+
+ if (properties == null) {
+ reportFailure("Missing configuration properties resource(3)", new ConfigurationException(
+ "Missing configuration properties resource(3): " + SQLRESOURCE_PROP_FILE_NAME));
+ }
+ }
+
+ /**
+ * Extract svclogic config properties.
+ *
+ * @return the svclogic config properties
+ */
+ public Properties getProperties() {
+ return properties;
+ }
+
+ /**
+ * Reports the method chosen for properties resolution to the
+ * <code>Logger</code>.
+ *
+ * @param message
+ * Some user friendly message
+ * @param fileOptional
+ * The file location of the chosen properties file
+ * @return the file location of the chosen properties file
+ */
+ private static File reportSuccess(final String message, final Optional<File> fileOptional) {
+ if (fileOptional.isPresent()) {
+ final File file = fileOptional.get();
+ LOG.info("{} {}", message, file.getPath());
+ return file;
+ }
+ return null;
+ }
+
+ /**
+ * Reports fatal errors. This is the case in which no properties file could be
+ * found.
+ *
+ * @param message
+ * An appropriate fatal error message
+ * @param configurationException
+ * An exception describing what went wrong during resolution
+ */
+ private static void reportFailure(final String message, final ConfigurationException configurationException) {
+
+ LOG.error("{}", message, configurationException);
+ }
+
+ /**
+ * Determines the sql-resource properties file to use based on the following priority:
+ * <ol>
+ * <li>A directory identified by the system environment variable
+ * <code>SDNC_CONFIG_DIR</code></li>
+ * <li>The default directory <code>DEFAULT_DBLIB_PROP_DIR</code></li>
+ * <li>A directory identified by the JRE argument
+ * <code>sql-resource.properties</code></li>
+ * <li>A <code>sql-resource.properties</code> file located in the karaf root
+ * directory</li>
+ * </ol>
+ */
+ File determinePropertiesFile(final SqlResourcePropertiesProviderImpl resourceProvider) {
+
+ for (final PropertiesFileResolver sliPropertiesFileResolver : sqlResourcePropertiesFileResolvers) {
+ final Optional<File> fileOptional = sliPropertiesFileResolver.resolveFile(SQLRESOURCE_PROP_FILE_NAME);
+ if (fileOptional.isPresent()) {
+ return reportSuccess(sliPropertiesFileResolver.getSuccessfulResolutionMessage(), fileOptional);
+ }
+ }
+
+ return null;
+ }
+}
diff --git a/adaptors/sql-resource/provider/src/main/resources/OSGI-INF/blueprint/sql-resource-blueprint.xml b/adaptors/sql-resource/provider/src/main/resources/OSGI-INF/blueprint/sql-resource-blueprint.xml
new file mode 100755
index 000000000..5e8d33946
--- /dev/null
+++ b/adaptors/sql-resource/provider/src/main/resources/OSGI-INF/blueprint/sql-resource-blueprint.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ============LICENSE_START=======================================================
+ openECOMP : SDN-C
+ ================================================================================
+ Copyright (C) 2017 - 2018 AT&T Intellectual Property. All rights
+ reserved.
+ ================================================================================
+ 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.
+ ============LICENSE_END=========================================================
+ -->
+
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+ xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0"
+ odl:use-default-for-reference-types="true">
+
+ <bean id="propProvider" class="org.onap.ccsdk.sli.adaptors.resource.sql.SqlResourcePropertiesProviderImpl" />
+ <reference id="dblibService" interface="org.onap.ccsdk.sli.core.dblib.DbLibService" />
+
+ <bean id="sqlResourceInstance" class="org.onap.ccsdk.sli.adaptors.resource.sql.SqlResource">
+ <argument ref="propProvider"/>
+ <argument ref="dblibService"/>
+ </bean>
+
+ <service ref="sqlResourceInstance">
+ <interfaces>
+ <value>org.onap.ccsdk.sli.adaptors.resource.sql.SqlResource</value>
+ </interfaces>
+ </service>
+
+</blueprint>
diff --git a/adaptors/sql-resource/provider/src/main/resources/org/opendaylight/blueprint/sql-resource-blueprint.xml b/adaptors/sql-resource/provider/src/main/resources/org/opendaylight/blueprint/sql-resource-blueprint.xml
new file mode 100755
index 000000000..5e8d33946
--- /dev/null
+++ b/adaptors/sql-resource/provider/src/main/resources/org/opendaylight/blueprint/sql-resource-blueprint.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ============LICENSE_START=======================================================
+ openECOMP : SDN-C
+ ================================================================================
+ Copyright (C) 2017 - 2018 AT&T Intellectual Property. All rights
+ reserved.
+ ================================================================================
+ 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.
+ ============LICENSE_END=========================================================
+ -->
+
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+ xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0"
+ odl:use-default-for-reference-types="true">
+
+ <bean id="propProvider" class="org.onap.ccsdk.sli.adaptors.resource.sql.SqlResourcePropertiesProviderImpl" />
+ <reference id="dblibService" interface="org.onap.ccsdk.sli.core.dblib.DbLibService" />
+
+ <bean id="sqlResourceInstance" class="org.onap.ccsdk.sli.adaptors.resource.sql.SqlResource">
+ <argument ref="propProvider"/>
+ <argument ref="dblibService"/>
+ </bean>
+
+ <service ref="sqlResourceInstance">
+ <interfaces>
+ <value>org.onap.ccsdk.sli.adaptors.resource.sql.SqlResource</value>
+ </interfaces>
+ </service>
+
+</blueprint>
diff --git a/adaptors/sql-resource/provider/src/main/resources/sql-resource.properties b/adaptors/sql-resource/provider/src/main/resources/sql-resource.properties
new file mode 100755
index 000000000..ac32f7734
--- /dev/null
+++ b/adaptors/sql-resource/provider/src/main/resources/sql-resource.properties
@@ -0,0 +1,23 @@
+###
+# ============LICENSE_START=======================================================
+# openECOMP : SDN-C
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights
+# reserved.
+# ================================================================================
+# 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.
+# ============LICENSE_END=========================================================
+###
+
+org.openecomp.sdnc.resource.sql.cryptkey=QtfJMKggVk
+
diff --git a/adaptors/sql-resource/provider/src/main/resources/svclogic.properties b/adaptors/sql-resource/provider/src/main/resources/svclogic.properties
new file mode 100644
index 000000000..18718b869
--- /dev/null
+++ b/adaptors/sql-resource/provider/src/main/resources/svclogic.properties
@@ -0,0 +1,34 @@
+###
+# ============LICENSE_START=======================================================
+# openECOMP : SDN-C
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights
+# reserved.
+# ================================================================================
+# 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.
+# ============LICENSE_END=========================================================
+###
+
+org.onap.ccsdk.sli.adaptors.dbtype=jdbc
+org.onap.ccsdk.sli.adaptors.jdbc.hosts=sdnctldb01,sdnctldb02
+org.onap.ccsdk.sli.adaptors.jdbc.url=jdbc:mysql://DBHOST:3306/sdnctl
+org.onap.ccsdk.sli.adaptors.jdbc.database=sdnctl
+org.onap.ccsdk.sli.adaptors.jdbc.user=sdnctl
+org.onap.ccsdk.sli.adaptors.jdbc.password=gamma
+org.onap.ccsdk.sli.adaptors.jdbc.connection.name=sdnctldb01
+
+org.onap.ccsdk.sli.adaptors.jdbc.connection.timeout=50
+org.onap.ccsdk.sli.adaptors.jdbc.request.timeout=100
+org.onap.ccsdk.sli.adaptors.jdbc.limit.init=10
+org.onap.ccsdk.sli.adaptors.jdbc.limit.min=10
+org.onap.ccsdk.sli.adaptors.jdbc.limit.max=20
diff --git a/adaptors/sql-resource/provider/src/test/java/org/onap/ccsdk/sli/adaptors/resource/sql/ITCaseSqlResource.java b/adaptors/sql-resource/provider/src/test/java/org/onap/ccsdk/sli/adaptors/resource/sql/ITCaseSqlResource.java
new file mode 100755
index 000000000..2863c6c96
--- /dev/null
+++ b/adaptors/sql-resource/provider/src/test/java/org/onap/ccsdk/sli/adaptors/resource/sql/ITCaseSqlResource.java
@@ -0,0 +1,231 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.adaptors.resource.sql;
+
+import java.io.BufferedReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.Enumeration;
+import java.util.Properties;
+
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicResource.QueryStatus;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import ch.vorburger.mariadb4j.DB;
+import ch.vorburger.mariadb4j.DBConfigurationBuilder;
+import junit.framework.TestCase;
+
+public class ITCaseSqlResource extends TestCase {
+
+ private static final Logger LOG = LoggerFactory
+ .getLogger(ITCaseSqlResource.class);
+
+
+ public void testExists() throws Exception {
+
+
+ Properties props = new Properties();
+ InputStream propStr = getClass().getResourceAsStream("/svclogic.properties");
+ if (propStr == null) {
+ fail("src/test/resources/svclogic.properties missing");
+ }
+
+ try {
+ props.load(propStr);
+ propStr.close();
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail("Could not initialize properties");
+ }
+
+
+ // Start MariaDB4j database
+ DBConfigurationBuilder config = DBConfigurationBuilder.newBuilder();
+ config.setPort(0); // 0 => autom. detect free port
+ DB db = DB.newEmbeddedDB(config.build());
+ db.start();
+
+ // Override jdbc URL and database name
+ props.setProperty("org.onap.ccsdk.sli.jdbc.database", "test");
+ props.setProperty("org.onap.ccsdk.sli.jdbc.url", config.getURL("test"));
+
+ // Add properties to global properties
+
+ Enumeration propNames = props.keys();
+
+ while (propNames.hasMoreElements()) {
+ String propName = (String) propNames.nextElement();
+
+ System.setProperty(propName, props.getProperty(propName));
+ }
+
+ SqlResource sqlResource = new SqlResource(new SqlResourcePropertiesProviderImpl());
+
+
+
+ InputStream testStr = getClass().getResourceAsStream("/save.tests");
+ BufferedReader testsReader = new BufferedReader(new InputStreamReader(testStr));
+ SvcLogicContext ctx = new SvcLogicContext();
+
+ try {
+ String testExpr = null;
+
+ int testNum = 0;
+ while ((testExpr = testsReader.readLine()) != null) {
+ testExpr = testExpr.trim();
+
+ if (testExpr.startsWith("#")) {
+ testExpr = testExpr.substring(1).trim();
+ String[] nameValue = testExpr.split("=");
+ String name = nameValue[0].trim();
+ String value = nameValue[1].trim();
+
+ LOG.info("Setting context attribute " + name + " = "
+ + value);
+ ctx.setAttribute(name, value);
+
+ } else {
+
+ testNum++;
+ String sqlStmt = testExpr;
+ QueryStatus status = sqlResource.save("SQL", true, false, sqlStmt, null, "savetest"+testNum, ctx);
+
+ switch (status) {
+ case SUCCESS:
+ LOG.info("Found data for query [" + sqlStmt + "]");
+ break;
+ case NOT_FOUND:
+ LOG.info("Did not data for query [" + sqlStmt + "]");
+ break;
+ default:
+ fail("Failure executing query [" + sqlStmt + "]");
+
+ }
+ }
+ }
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail("Caught exception running tests");
+ }
+
+
+ testStr = getClass().getResourceAsStream("/query.tests");
+ testsReader = new BufferedReader(new InputStreamReader(testStr));
+
+ try {
+ String testExpr = null;
+
+ int testNum = 0;
+ while ((testExpr = testsReader.readLine()) != null) {
+ testExpr = testExpr.trim();
+ if (testExpr.startsWith("#")) {
+ testExpr = testExpr.substring(1).trim();
+ String[] nameValue = testExpr.split("=");
+ String name = nameValue[0].trim();
+ String value = nameValue[1].trim();
+
+ LOG.info("Setting context attribute " + name + " = "
+ + value);
+ ctx.setAttribute(name, value);
+
+ } else {
+
+ testNum++;
+
+ String sqlStmt = testExpr;
+ QueryStatus status = sqlResource.query("SQL", false, null,
+ sqlStmt, "querytest" + testNum, null, ctx);
+
+ switch (status) {
+ case SUCCESS:
+ LOG.info("Found data for query [" + sqlStmt + "]");
+ break;
+ case NOT_FOUND:
+ LOG.info("Did not data for query [" + sqlStmt + "]");
+ break;
+ default:
+ fail("Failure executing query [" + sqlStmt + "]");
+
+ }
+ }
+ }
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail("Caught exception running tests");
+ }
+
+
+ testStr = getClass().getResourceAsStream("/delete.tests");
+ testsReader = new BufferedReader(new InputStreamReader(testStr));
+
+ try {
+ String testExpr = null;
+
+ int testNum = 0;
+ while ((testExpr = testsReader.readLine()) != null) {
+ testExpr = testExpr.trim();
+ if (testExpr.startsWith("#")) {
+ testExpr = testExpr.substring(1).trim();
+ String[] nameValue = testExpr.split("=");
+ String name = nameValue[0].trim();
+ String value = nameValue[1].trim();
+
+ LOG.info("Setting context attribute " + name + " = "
+ + value);
+ ctx.setAttribute(name, value);
+
+ } else {
+
+ testNum++;
+
+ String sqlStmt = testExpr;
+ QueryStatus status = sqlResource.delete("SQL", sqlStmt, ctx);
+
+ switch (status) {
+ case SUCCESS:
+ LOG.info("Found data for query [" + sqlStmt + "]");
+ break;
+ case NOT_FOUND:
+ LOG.info("Did not data for query [" + sqlStmt + "]");
+ break;
+ default:
+ fail("Failure executing query [" + sqlStmt + "]");
+
+ }
+ }
+ }
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ fail("Caught exception running tests");
+ }
+
+ for (String attrName : ctx.getAttributeKeySet()) {
+ LOG.info("ctx.getAttribute("+attrName+") = "+ctx.getAttribute(attrName));
+ }
+ }
+
+}
diff --git a/adaptors/sql-resource/provider/src/test/java/org/onap/ccsdk/sli/adaptors/resource/sql/SqlResourceProviderTest.java b/adaptors/sql-resource/provider/src/test/java/org/onap/ccsdk/sli/adaptors/resource/sql/SqlResourceProviderTest.java
new file mode 100755
index 000000000..b261b9f7d
--- /dev/null
+++ b/adaptors/sql-resource/provider/src/test/java/org/onap/ccsdk/sli/adaptors/resource/sql/SqlResourceProviderTest.java
@@ -0,0 +1,38 @@
+package org.onap.ccsdk.sli.adaptors.resource.sql;
+
+import static org.junit.Assert.assertNotNull;
+import java.lang.reflect.Field;
+import java.util.Map;
+import java.util.Properties;
+
+import org.junit.Test;
+
+public class SqlResourceProviderTest {
+
+ private static SqlResourcePropertiesProvider provider;
+ private static final String SDNC_CONFIG_DIR = "SDNC_CONFIG_DIR";
+
+ @Test
+ public void testSqlResourceProvider() {
+ try{
+ Map<String, String> env = System.getenv();
+ Class<?> cl = env.getClass();
+ Field field = cl.getDeclaredField("m");
+ field.setAccessible(true);
+ Map<String, String> writableEnv = (Map<String, String>) field.get(env);
+ writableEnv.put(SDNC_CONFIG_DIR, "./src/test/resources");
+ } catch (Exception e) {
+ throw new IllegalStateException("Failed to set environment variable", e);
+ }
+
+ provider = new SqlResourcePropertiesProviderImpl();
+ assertNotNull(provider);
+ }
+
+ @Test
+ public void testGetProperties() {
+ Properties properties = provider.getProperties();
+ assertNotNull(properties);
+ }
+
+}
diff --git a/adaptors/sql-resource/provider/src/test/resources/delete.tests b/adaptors/sql-resource/provider/src/test/resources/delete.tests
new file mode 100755
index 000000000..a60a3bc73
--- /dev/null
+++ b/adaptors/sql-resource/provider/src/test/resources/delete.tests
@@ -0,0 +1,2 @@
+DROP TABLE SQLRESOURCE_ORDER;
+DROP TABLE SQLRESOURCE_ORDER_ITEM;
diff --git a/adaptors/sql-resource/provider/src/test/resources/query.tests b/adaptors/sql-resource/provider/src/test/resources/query.tests
new file mode 100755
index 000000000..ec05c22e3
--- /dev/null
+++ b/adaptors/sql-resource/provider/src/test/resources/query.tests
@@ -0,0 +1,5 @@
+# max-price = 100
+SELECT * FROM SQLRESOURCE_ORDER where placed_on < now();
+SELECT SQLRESOURCE_ORDER.order_number, clli, service, price FROM SQLRESOURCE_ORDER, SQLRESOURCE_ORDER_ITEM where SQLRESOURCE_ORDER.order_number = SQLRESOURCE_ORDER_ITEM.order_number and price > $max-price ;
+SELECT SQLRESOURCE_ORDER.order_number, clli, service, price FROM SQLRESOURCE_ORDER, SQLRESOURCE_ORDER_ITEM where SQLRESOURCE_ORDER.order_number = SQLRESOURCE_ORDER_ITEM.order_number and price < $max-price ;
+SELECT SQLRESOURCE_ORDER.order_number AS ordernum, clli, service, price FROM SQLRESOURCE_ORDER, SQLRESOURCE_ORDER_ITEM where SQLRESOURCE_ORDER.order_number = SQLRESOURCE_ORDER_ITEM.order_number and price < $max-price ;
diff --git a/adaptors/sql-resource/provider/src/test/resources/save.tests b/adaptors/sql-resource/provider/src/test/resources/save.tests
new file mode 100755
index 000000000..e2c42217d
--- /dev/null
+++ b/adaptors/sql-resource/provider/src/test/resources/save.tests
@@ -0,0 +1,13 @@
+# order-number = 1234
+# zero = 0
+# item[0].clli = MTJNJA14
+# item[0].service = NoD
+# item[0].price = 1000000
+# item[1].clli = MTJNJA14
+# item[1].service = Pizza
+# item[1].price = 10
+CREATE TABLE IF NOT EXISTS SQLRESOURCE_ORDER (order_number VARCHAR(40), placed_on TIMESTAMP);
+CREATE TABLE IF NOT EXISTS SQLRESOURCE_ORDER_ITEM (order_number VARCHAR(40), clli VARCHAR(40), service VARCHAR(40), price INTEGER(4));
+INSERT INTO SQLRESOURCE_ORDER VALUES ( $order-number , now());
+INSERT INTO SQLRESOURCE_ORDER_ITEM VALUES( $order-number , $item[$zero].clli , $item[0].service , $item[0].price );
+INSERT INTO SQLRESOURCE_ORDER_ITEM VALUES( $order-number , $item[1].clli , $item[1].service , $item[1].price );
diff --git a/adaptors/sql-resource/provider/src/test/resources/simplelogger.properties b/adaptors/sql-resource/provider/src/test/resources/simplelogger.properties
new file mode 100644
index 000000000..61d82660f
--- /dev/null
+++ b/adaptors/sql-resource/provider/src/test/resources/simplelogger.properties
@@ -0,0 +1,22 @@
+###
+# ============LICENSE_START=======================================================
+# openECOMP : SDN-C
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights
+# reserved.
+# ================================================================================
+# 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.
+# ============LICENSE_END=========================================================
+###
+
+org.slf4j.simpleLogger.defaultLogLevel=debug
diff --git a/adaptors/sql-resource/provider/src/test/resources/sql-resource.properties b/adaptors/sql-resource/provider/src/test/resources/sql-resource.properties
new file mode 100755
index 000000000..ac32f7734
--- /dev/null
+++ b/adaptors/sql-resource/provider/src/test/resources/sql-resource.properties
@@ -0,0 +1,23 @@
+###
+# ============LICENSE_START=======================================================
+# openECOMP : SDN-C
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights
+# reserved.
+# ================================================================================
+# 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.
+# ============LICENSE_END=========================================================
+###
+
+org.openecomp.sdnc.resource.sql.cryptkey=QtfJMKggVk
+
diff --git a/adaptors/sql-resource/provider/src/test/resources/svclogic.properties b/adaptors/sql-resource/provider/src/test/resources/svclogic.properties
new file mode 100644
index 000000000..6504e1aec
--- /dev/null
+++ b/adaptors/sql-resource/provider/src/test/resources/svclogic.properties
@@ -0,0 +1,35 @@
+###
+# ============LICENSE_START=======================================================
+# openECOMP : SDN-C
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights
+# reserved.
+# ================================================================================
+# 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.
+# ============LICENSE_END=========================================================
+###
+org.onap.ccsdk.sli.dbtype=jdbc
+
+org.onap.ccsdk.sli.jdbc.hosts=sdnctldb01
+org.onap.ccsdk.sli.jdbc.url=jdbc:mysql://dbhost:3306/sdnctl
+org.onap.ccsdk.sli.jdbc.driver=org.mariadb.jdbc.Driver
+org.onap.ccsdk.sli.jdbc.database=sdnctl
+org.onap.ccsdk.sli.jdbc.user=sdnctl
+org.onap.ccsdk.sli.jdbc.password=gamma
+org.onap.ccsdk.sli.jdbc.connection.name=sdnctldb01
+org.onap.ccsdk.sli.jdbc.connection.timeout=50
+org.onap.ccsdk.sli.jdbc.request.timeout=100
+org.onap.ccsdk.sli.jdbc.limit.init=10
+org.onap.ccsdk.sli.jdbc.limit.min=10
+org.onap.ccsdk.sli.jdbc.limit.max=20
+org.onap.dblib.connection.recovery=false
diff --git a/core/LICENSE.txt b/core/LICENSE.txt
new file mode 100644
index 000000000..3ea5081a0
--- /dev/null
+++ b/core/LICENSE.txt
@@ -0,0 +1,22 @@
+/*
+ * ============LICENSE_START==========================================
+ * ===================================================================
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ * 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.
+ * ============LICENSE_END============================================
+ *
+ * ECOMP and OpenECOMP are trademarks
+ * and service marks of AT&T Intellectual Property.
+ *
+ */
diff --git a/core/README.md b/core/README.md
new file mode 100644
index 000000000..262339dde
--- /dev/null
+++ b/core/README.md
@@ -0,0 +1,7 @@
+This source repository contains the code for the core SDN Controller components.
+To compile this code:
+
+1. Make sure your local Maven settings file ($HOME/.m2/settings.xml) contains references to the ONAP repositories and OpenDaylight repositories.
+
+2. To compile, run "mvn clean install".
+
diff --git a/core/artifacts/pom.xml b/core/artifacts/pom.xml
new file mode 100755
index 000000000..9b5f92fd5
--- /dev/null
+++ b/core/artifacts/pom.xml
@@ -0,0 +1,152 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>parent</artifactId>
+ <version>2.1.0-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sli-core-artifacts</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>pom</packaging>
+
+ <name>ccsdk-sli-core :: sli-core-artifacts</name>
+ <description>CCSDK core components Bill of Materials (BOM)</description>
+ <url>https://wiki.onap.org</url>
+ <organization>
+ <name>ONAP</name>
+ </organization>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>ccsdk-dblib</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>ccsdk-filters</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>ccsdk-sli</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>ccsdk-sli-core-all</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>ccsdk-sliapi</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>ccsdk-slicore-utils</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>ccsdk-sliPluginUtils</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>dblib-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>dblib-installer</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>filters-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>filters-installer</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sli-common</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sli-model</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sli-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sli-provider-base</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sliapi-model</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sliapi-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sliapi-installer</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sliPluginUtils-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sliPluginUtils-installer</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>utils-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>utils-installer</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+</project>
diff --git a/core/dblib/.gitignore b/core/dblib/.gitignore
new file mode 100755
index 000000000..b73caf31e
--- /dev/null
+++ b/core/dblib/.gitignore
@@ -0,0 +1,34 @@
+#####standard .git ignore entries#####
+
+## IDE Specific Files ##
+org.eclipse.core.resources.prefs
+.classpath
+.project
+.settings
+.idea
+.externalToolBuilders
+maven-eclipse.xml
+workspace
+
+## Compilation Files ##
+*.class
+**/target
+target
+target-ide
+MANIFEST.MF
+
+## Misc Ignores (OS specific etc) ##
+bin/
+dist
+*~
+*.ipr
+*.iml
+*.iws
+classes
+out/
+.DS_STORE
+.metadata
+
+## Folders which contain auto generated source code ##
+yang-gen-config
+yang-gen-sal
diff --git a/core/dblib/README.md b/core/dblib/README.md
new file mode 100755
index 000000000..ab2c5130e
--- /dev/null
+++ b/core/dblib/README.md
@@ -0,0 +1,6 @@
+DBLIB Utility
+---------------------
+
+DBLIB utility is designed as a high availability connection manager.
+It is configured to use multiple databases, and based on the configured rules
+always provide the connection to the active database.
diff --git a/core/dblib/installer/pom.xml b/core/dblib/installer/pom.xml
new file mode 100755
index 000000000..44779753d
--- /dev/null
+++ b/core/dblib/installer/pom.xml
@@ -0,0 +1,128 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>odlparent-lite</artifactId>
+ <version>2.1.0-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>dblib-installer</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>pom</packaging>
+
+ <name>ccsdk-sli-core :: dblib :: ${project.artifactId}</name>
+
+ <properties>
+ <application.name>ccsdk-dblib</application.name>
+ <features.boot>${application.name}</features.boot>
+ <features.repositories>mvn:org.onap.ccsdk.sli.core/${features.boot}/${project.version}/xml/features</features.repositories>
+ <include.transitive.dependencies>false</include.transitive.dependencies>
+ </properties>
+
+ <dependencies>
+
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>dblib-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>maven-repo-zip</id>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ <phase>package</phase>
+ <configuration>
+ <attach>true</attach>
+ <finalName>stage/${application.name}-${project.version}</finalName>
+ <descriptors>
+ <descriptor>src/assembly/assemble_mvnrepo_zip.xml</descriptor>
+ </descriptors>
+ <appendAssemblyId>true</appendAssemblyId>
+ </configuration>
+ </execution>
+ <execution>
+ <id>installer-zip</id>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ <phase>package</phase>
+ <configuration>
+ <attach>true</attach>
+ <finalName>${application.name}-${project.version}-installer</finalName>
+ <descriptors>
+ <descriptor>src/assembly/assemble_installer_zip.xml</descriptor>
+ </descriptors>
+ <appendAssemblyId>false</appendAssemblyId>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>copy-dependencies</id>
+ <goals>
+ <goal>copy-dependencies</goal>
+ </goals>
+ <phase>prepare-package</phase>
+ <configuration>
+ <transitive>false</transitive>
+ <outputDirectory>${project.build.directory}/assembly/system</outputDirectory>
+ <overWriteReleases>false</overWriteReleases>
+ <overWriteSnapshots>true</overWriteSnapshots>
+ <overWriteIfNewer>true</overWriteIfNewer>
+ <useRepositoryLayout>true</useRepositoryLayout>
+ <addParentPoms>false</addParentPoms>
+ <copyPom>false</copyPom>
+ <includeGroupIds>org.onap.ccsdk.sli.core</includeGroupIds>
+ <excludeArtifactIds>utils-provider</excludeArtifactIds>
+ <scope>provided</scope>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <artifactId>maven-resources-plugin</artifactId>
+ <version>2.6</version>
+ <executions>
+ <execution>
+ <id>copy-version</id>
+ <goals>
+ <goal>copy-resources</goal>
+ </goals><!-- here the phase you need -->
+ <phase>validate</phase>
+ <configuration>
+ <outputDirectory>${basedir}/target/stage</outputDirectory>
+ <resources>
+ <resource>
+ <directory>src/main/resources/scripts</directory>
+ <includes>
+ <include>install-feature.sh</include>
+ </includes>
+ <filtering>true</filtering>
+ </resource>
+ </resources>
+ </configuration>
+ </execution>
+
+ </executions>
+ </plugin>
+
+ </plugins>
+ </build>
+</project>
diff --git a/core/dblib/installer/src/assembly/assemble_installer_zip.xml b/core/dblib/installer/src/assembly/assemble_installer_zip.xml
new file mode 100755
index 000000000..a6a22a9ba
--- /dev/null
+++ b/core/dblib/installer/src/assembly/assemble_installer_zip.xml
@@ -0,0 +1,39 @@
+<!-- Defines how we build the .zip file which is our distribution. -->
+
+<assembly
+ xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
+ <id>bin</id>
+
+ <formats>
+ <format>zip</format>
+ </formats>
+
+ <!-- we want "system" and related files right at the root level
+ as this file is suppose to be unzip on top of a karaf
+ distro. -->
+ <includeBaseDirectory>false</includeBaseDirectory>
+
+ <fileSets>
+ <fileSet>
+ <directory>target/stage/</directory>
+ <outputDirectory>${application.name}</outputDirectory>
+ <fileMode>755</fileMode>
+ <includes>
+ <include>*.sh</include>
+ </includes>
+ </fileSet>
+ <fileSet>
+ <directory>target/stage/</directory>
+ <outputDirectory>${application.name}</outputDirectory>
+ <fileMode>644</fileMode>
+ <excludes>
+ <exclude>*.sh</exclude>
+ </excludes>
+ </fileSet>
+ </fileSets>
+
+
+
+</assembly>
diff --git a/core/dblib/installer/src/assembly/assemble_mvnrepo_zip.xml b/core/dblib/installer/src/assembly/assemble_mvnrepo_zip.xml
new file mode 100755
index 000000000..86b07f1f3
--- /dev/null
+++ b/core/dblib/installer/src/assembly/assemble_mvnrepo_zip.xml
@@ -0,0 +1,29 @@
+<!-- Defines how we build the .zip file which is our distribution. -->
+
+<assembly
+ xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
+ <id>repo</id>
+
+ <formats>
+ <format>zip</format>
+ </formats>
+
+ <!-- we want "system" and related files right at the root level
+ as this file is suppose to be unzip on top of a karaf
+ distro. -->
+ <includeBaseDirectory>false</includeBaseDirectory>
+
+ <fileSets>
+ <fileSet>
+ <directory>target/assembly/</directory>
+ <outputDirectory>.</outputDirectory>
+ <excludes>
+ </excludes>
+ </fileSet>
+ </fileSets>
+
+
+
+</assembly>
diff --git a/core/dblib/installer/src/main/resources/scripts/install-feature.sh b/core/dblib/installer/src/main/resources/scripts/install-feature.sh
new file mode 100644
index 000000000..e16e79a12
--- /dev/null
+++ b/core/dblib/installer/src/main/resources/scripts/install-feature.sh
@@ -0,0 +1,18 @@
+#!/bin/bash
+
+ODL_HOME=${ODL_HOME:-/opt/opendaylight/current}
+ODL_KARAF_CLIENT=${ODL_KARAF_CLIENT:-${ODL_HOME}/bin/client}
+INSTALLERDIR=$(dirname $0)
+
+REPOZIP=${INSTALLERDIR}/${features.boot}-${project.version}.zip
+
+if [ -f ${REPOZIP} ]
+then
+ unzip -d ${ODL_HOME} ${REPOZIP}
+else
+ echo "ERROR : repo zip ($REPOZIP) not found"
+ exit 1
+fi
+
+${ODL_KARAF_CLIENT} feature:repo-add ${features.repositories}
+${ODL_KARAF_CLIENT} feature:install ${features.boot}
diff --git a/core/dblib/pom.xml b/core/dblib/pom.xml
new file mode 100755
index 000000000..00f4d5b37
--- /dev/null
+++ b/core/dblib/pom.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>odlparent-lite</artifactId>
+ <version>2.1.0-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>dblib</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>pom</packaging>
+
+ <name>ccsdk-sli-core :: dblib</name>
+ <description>The DBLIB adaptor allows service logic to access persistent data in a local sql database</description>
+ <organization>
+ <name>ONAP</name>
+ </organization>
+
+ <modules>
+ <module>provider</module>
+ <module>installer</module>
+ </modules>
+</project>
diff --git a/core/dblib/provider/pom.xml b/core/dblib/provider/pom.xml
new file mode 100755
index 000000000..c45513794
--- /dev/null
+++ b/core/dblib/provider/pom.xml
@@ -0,0 +1,64 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>binding-parent</artifactId>
+ <version>2.1.0-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>dblib-provider</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>bundle</packaging>
+
+ <name>ccsdk-sli-core :: dblib :: ${project.artifactId}</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>ch.vorburger.mariaDB4j</groupId>
+ <artifactId>mariaDB4j</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-simple</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.mariadb.jdbc</groupId>
+ <artifactId>mariadb-java-client</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.tomcat</groupId>
+ <artifactId>tomcat-jdbc</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>utils-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <!-- Testing related dependencies -->
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/CachedDataSource.java b/core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/CachedDataSource.java
new file mode 100755
index 000000000..b9a0f071b
--- /dev/null
+++ b/core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/CachedDataSource.java
@@ -0,0 +1,593 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * onap
+ * ================================================================================
+ * Copyright (C) 2016 - 2017 ONAP
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.dblib;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.sql.Blob;
+import java.sql.Connection;
+import java.sql.Date;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.sql.Timestamp;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Observer;
+import javax.sql.DataSource;
+import javax.sql.rowset.CachedRowSet;
+import javax.sql.rowset.RowSetProvider;
+import org.apache.tomcat.jdbc.pool.PoolExhaustedException;
+import org.onap.ccsdk.sli.core.dblib.config.BaseDBConfiguration;
+import org.onap.ccsdk.sli.core.dblib.pm.SQLExecutionMonitor;
+import org.onap.ccsdk.sli.core.dblib.pm.SQLExecutionMonitor.TestObject;
+import org.onap.ccsdk.sli.core.dblib.pm.SQLExecutionMonitorObserver;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @version $Revision: 1.14 $
+ * Change Log
+ * Author Date Comments
+ * ============== ======== ====================================================
+ * Rich Tabedzki
+ */
+
+public abstract class CachedDataSource implements DataSource, SQLExecutionMonitorObserver {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(CachedDataSource.class);
+
+ private static final String SQL_FAILURE = "SQL FAILURE. time(ms): ";
+ private static final String FAILED_TO_EXECUTE = "> Failed to execute: ";
+ private static final String WITH_ARGUMENTS = " with arguments: ";
+ private static final String WITH_NO_ARGUMENTS = " with no arguments. ";
+ private static final String DATA_SOURCE_CONNECT_SUCCESS = "SQL DataSource < {} > connected to {}, read-only is {}, tested successfully";
+ private static final String DATA_SOURCE_CONNECT_FAILURE = "SQL DataSource < {} > test failed. Cause : {}> test failed. Cause : {}";
+
+ protected long connReqTimeout = 30L;
+ protected long dataReqTimeout = 100L;
+
+ private final SQLExecutionMonitor monitor;
+ protected final DataSource ds;
+ protected String connectionName = null;
+ protected boolean initialized = false;
+
+ private long interval = 1000;
+ private long initialDelay = 5000;
+ private long expectedCompletionTime = 50L;
+ private boolean canTakeOffLine = true;
+ private long unprocessedFailoverThreshold = 3L;
+
+ private long nextErrorReportTime = 0L;
+
+ private String globalHostName = null;
+ private final int index;
+
+ private boolean isDerby = false;
+
+ public CachedDataSource(BaseDBConfiguration jdbcElem) throws DBConfigException {
+ ds = configure(jdbcElem);
+ index = initializeIndex(jdbcElem);
+ if ("org.apache.derby.jdbc.EmbeddedDriver".equals(jdbcElem.getDriverName())) {
+ isDerby = true;
+ }
+ monitor = new SQLExecutionMonitor(this);
+ }
+
+ protected abstract DataSource configure(BaseDBConfiguration jdbcElem) throws DBConfigException;
+ protected abstract int getAvailableConnections();
+
+ protected int initializeIndex(BaseDBConfiguration jdbcElem) {
+ if(jdbcElem.containsKey(BaseDBConfiguration.DATABASE_HOSTS)) {
+ String hosts = jdbcElem.getProperty(BaseDBConfiguration.DATABASE_HOSTS);
+ String name = jdbcElem.getProperty(BaseDBConfiguration.CONNECTION_NAME);
+ List<String> numbers = Arrays.asList(hosts.split(","));
+ return numbers.indexOf(name);
+ } else
+ return -1;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see javax.sql.DataSource#getConnection()
+ */
+ @Override
+ public Connection getConnection() throws SQLException {
+ LapsedTimer lt = new LapsedTimer();
+ try {
+ return ds.getConnection();
+ } finally {
+ if(LOGGER.isTraceEnabled()) {
+ LOGGER.trace(String.format("SQL Connection aquisition time : %s", lt.lapsedTime()));
+ }
+ }
+ }
+
+ public CachedRowSet getData(String statement, List<Object> arguments) throws SQLException {
+ TestObject testObject = monitor.registerRequest();
+
+ try (Connection connection = this.getConnection()) {
+ if (connection == null) {
+ throw new SQLException("Connection invalid");
+ }
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("Obtained connection <{}>: {}", connectionName, connection);
+ }
+ return executePreparedStatement(connection, statement, arguments, true);
+ } finally {
+ monitor.deregisterRequest(testObject);
+ }
+ }
+
+ public boolean writeData(String statement, List<Object> arguments) throws SQLException {
+ TestObject testObject = monitor.registerRequest();
+
+ try (Connection connection = this.getConnection()) {
+ if (connection == null) {
+ throw new SQLException("Connection invalid");
+ }
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("Obtained connection <{}>: {}", connectionName, connection);
+ }
+ return executeUpdatePreparedStatement(connection, statement, arguments, true);
+ } finally {
+ monitor.deregisterRequest(testObject);
+ }
+ }
+
+ CachedRowSet executePreparedStatement(Connection conn, String statement, List<Object> arguments, boolean close)
+ throws SQLException {
+ long time = System.currentTimeMillis();
+
+ CachedRowSet data = null;
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("SQL Statement: {}", statement);
+ if (arguments != null && !arguments.isEmpty()) {
+ LOGGER.debug("Argunments: {}", arguments);
+ }
+ }
+
+ ResultSet rs = null;
+ try (PreparedStatement ps = conn.prepareStatement(statement)) {
+ data = RowSetProvider.newFactory().createCachedRowSet();
+ if (arguments != null) {
+ for (int i = 0, max = arguments.size(); i < max; i++) {
+ ps.setObject(i + 1, arguments.get(i));
+ }
+ }
+ rs = ps.executeQuery();
+ data.populate(rs);
+ // Point the rowset Cursor to the start
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("SQL SUCCESS. rows returned: {}, time(ms): {}", data.size(),
+ (System.currentTimeMillis() - time));
+ }
+ } catch (SQLException exc) {
+ handleSqlExceptionForExecuteStatement(conn, statement, arguments, exc, time);
+ } finally {
+ handleFinallyBlockForExecutePreparedStatement(rs, conn, close);
+ }
+
+ return data;
+ }
+
+ private void handleSqlExceptionForExecuteStatement(Connection conn, String statement, List<Object> arguments,
+ SQLException exc, long time) throws SQLException {
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug(SQL_FAILURE + (System.currentTimeMillis() - time));
+ }
+ try {
+ conn.rollback();
+ } catch (Exception thr) {
+ LOGGER.error(thr.getLocalizedMessage(), thr);
+ }
+ if (arguments != null && !arguments.isEmpty()) {
+ LOGGER.error(String.format("<%s%s%s%s%s", connectionName, FAILED_TO_EXECUTE, statement, WITH_ARGUMENTS,
+ arguments), exc);
+ } else {
+ LOGGER.error(String.format("<%s%s%s%s", connectionName, FAILED_TO_EXECUTE, statement, WITH_NO_ARGUMENTS),
+ exc);
+ }
+ throw exc;
+ }
+
+ private void handleFinallyBlockForExecutePreparedStatement(ResultSet rs, Connection conn, boolean close) {
+ try {
+ if (rs != null) {
+ rs.close();
+ }
+ } catch (Exception exc) {
+ LOGGER.error(exc.getLocalizedMessage(), exc);
+ }
+ try {
+ if (conn != null && close) {
+ conn.close();
+ }
+ } catch (Exception exc) {
+ LOGGER.error(exc.getLocalizedMessage(), exc);
+ }
+ }
+
+ boolean executeUpdatePreparedStatement(Connection conn, String statement, List<Object> arguments, boolean close)
+ throws SQLException {
+ long time = System.currentTimeMillis();
+
+ try (PreparedStatement ps = conn.prepareStatement(statement);
+ CachedRowSet data = RowSetProvider.newFactory().createCachedRowSet()) {
+ if (arguments != null) {
+ prepareStatementForExecuteUpdate(arguments, ps);
+ }
+ ps.executeUpdate();
+ // Point the rowset Cursor to the start
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("SQL SUCCESS. rows returned: {}, time(ms): {}", data.size(),
+ (System.currentTimeMillis() - time));
+ }
+ } catch (SQLException exc) {
+ handleSqlExceptionForExecuteStatement(conn, statement, arguments, exc, time);
+ } finally {
+ try {
+ if (close) {
+ conn.close();
+ }
+ } catch (Exception exc) {
+ LOGGER.error(exc.getLocalizedMessage(), exc);
+ }
+ }
+
+ return true;
+ }
+
+ private void prepareStatementForExecuteUpdate(List<Object> arguments, PreparedStatement ps) throws SQLException {
+ for (int i = 0, max = arguments.size(); i < max; i++) {
+ Object value = arguments.get(i);
+ if (value instanceof Blob) {
+ ps.setBlob(i + 1, (Blob) value);
+ } else if (value instanceof Timestamp) {
+ ps.setTimestamp(i + 1, (Timestamp) value);
+ } else if (value instanceof Integer) {
+ ps.setInt(i + 1, (Integer) value);
+ } else if (value instanceof Long) {
+ ps.setLong(i + 1, (Long) value);
+ } else if (value instanceof Date) {
+ ps.setDate(i + 1, (Date) value);
+ } else {
+ ps.setObject(i + 1, value);
+ }
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see javax.sql.DataSource#getConnection(java.lang.String, java.lang.String)
+ */
+ @Override
+ public Connection getConnection(String username, String password) throws SQLException {
+ return ds.getConnection(username, password);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see javax.sql.DataSource#getLogWriter()
+ */
+ @Override
+ public PrintWriter getLogWriter() throws SQLException {
+ return ds.getLogWriter();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see javax.sql.DataSource#getLoginTimeout()
+ */
+ @Override
+ public int getLoginTimeout() throws SQLException {
+ return ds.getLoginTimeout();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see javax.sql.DataSource#setLogWriter(java.io.PrintWriter)
+ */
+ @Override
+ public void setLogWriter(PrintWriter out) throws SQLException {
+ ds.setLogWriter(out);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see javax.sql.DataSource#setLoginTimeout(int)
+ */
+ @Override
+ public void setLoginTimeout(int seconds) throws SQLException {
+ ds.setLoginTimeout(seconds);
+ }
+
+ @Override
+ public final String getDbConnectionName() {
+ return connectionName;
+ }
+
+ protected final void setDbConnectionName(String name) {
+ this.connectionName = name;
+ }
+
+ public void cleanUp() {
+ if (ds != null && ds instanceof Closeable) {
+ try {
+ ((Closeable) ds).close();
+ } catch (IOException e) {
+ LOGGER.warn(e.getMessage());
+ }
+ }
+ monitor.deleteObservers();
+ monitor.cleanup();
+ }
+
+ public boolean isInitialized() {
+ return initialized;
+ }
+
+ protected boolean testConnection() {
+ return testConnection(false);
+ }
+
+ protected boolean testConnection(boolean errorLevel) {
+
+ String testQuery = "SELECT @@global.read_only, @@global.hostname";
+ if (isDerby) {
+ testQuery = "SELECT 'false', 'localhost' FROM SYSIBM.SYSDUMMY1";
+ }
+ ResultSet rs = null;
+ try (Connection conn = this.getConnection(); Statement stmt = conn.createStatement()) {
+ Boolean readOnly;
+ String hostname;
+ rs = stmt.executeQuery(testQuery); // ("SELECT 1 FROM DUAL"); //"select
+ // BANNER from SYS.V_$VERSION"
+ while (rs.next()) {
+ readOnly = rs.getBoolean(1);
+ hostname = rs.getString(2);
+
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug(DATA_SOURCE_CONNECT_SUCCESS,getDbConnectionName(),hostname,readOnly);
+ }
+ }
+ } catch (Exception exc) {
+ if (errorLevel) {
+ LOGGER.error(DATA_SOURCE_CONNECT_FAILURE, this.getDbConnectionName(),exc.getMessage());
+ } else {
+ LOGGER.info(DATA_SOURCE_CONNECT_FAILURE, this.getDbConnectionName(),exc.getMessage());
+ }
+ return false;
+ } finally {
+ if (rs != null) {
+ try {
+ rs.close();
+ } catch (SQLException e) {
+ LOGGER.error(e.getLocalizedMessage(), e);
+ }
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public boolean isWrapperFor(Class<?> iface) throws SQLException {
+ return false;
+ }
+
+ @Override
+ public <T> T unwrap(Class<T> iface) throws SQLException {
+ return null;
+ }
+
+ public void addObserver(Observer observer) {
+ monitor.addObserver(observer);
+ }
+
+ public void deleteObserver(Observer observer) {
+ monitor.deleteObserver(observer);
+ }
+
+ public int getIndex() {
+ return index;
+ }
+
+ @Override
+ public long getInterval() {
+ return interval;
+ }
+
+ @Override
+ public long getInitialDelay() {
+ return initialDelay;
+ }
+
+ @Override
+ public void setInterval(long value) {
+ interval = value;
+ }
+
+ @Override
+ public void setInitialDelay(long value) {
+ initialDelay = value;
+ }
+
+ @Override
+ public long getExpectedCompletionTime() {
+ return expectedCompletionTime;
+ }
+
+ @Override
+ public void setExpectedCompletionTime(long value) {
+ expectedCompletionTime = value;
+ }
+
+ @Override
+ public long getUnprocessedFailoverThreshold() {
+ return unprocessedFailoverThreshold;
+ }
+
+ @Override
+ public void setUnprocessedFailoverThreshold(long value) {
+ this.unprocessedFailoverThreshold = value;
+ }
+
+ public boolean canTakeOffLine() {
+ return canTakeOffLine;
+ }
+
+ public void blockImmediateOffLine() {
+ canTakeOffLine = false;
+ final Thread offLineTimer = new Thread(() -> {
+ try {
+ Thread.sleep(30000L);
+ } catch (Exception exc) {
+ LOGGER.error(exc.getLocalizedMessage(), exc);
+ } finally {
+ canTakeOffLine = true;
+ }
+ });
+ offLineTimer.setDaemon(true);
+ offLineTimer.start();
+ }
+
+ /**
+ * @return the monitor
+ */
+ final SQLExecutionMonitor getMonitor() {
+ return monitor;
+ }
+
+ protected boolean isSlave() throws PoolExhaustedException {
+
+ // If using Apache derby, just return false
+ if (isDerby) {
+ return false;
+ }
+ CachedRowSet rs;
+ boolean isSlave;
+ String hostname = "UNDETERMINED";
+ try {
+ boolean localSlave = true;
+ rs = this.getData("SELECT @@global.read_only, @@global.hostname", new ArrayList<>());
+ while (rs.next()) {
+ localSlave = rs.getBoolean(1);
+ hostname = rs.getString(2);
+ }
+ isSlave = localSlave;
+ } catch (PoolExhaustedException peexc) {
+ throw peexc;
+ } catch (Exception e) {
+ LOGGER.error("", e);
+ isSlave = true;
+ }
+ if (isSlave) {
+ LOGGER.debug("SQL SLAVE : {} on server {}, pool {}", connectionName, getDbConnectionName(), getAvailableConnections());
+ } else {
+ LOGGER.debug("SQL MASTER : {} on server {}, pool {}", connectionName, getDbConnectionName(), getAvailableConnections());
+ }
+ return isSlave;
+ }
+
+ public boolean isFabric() {
+ return false;
+ }
+
+ protected boolean lockTable(Connection conn, String tableName) {
+ boolean retValue = false;
+ String query = "LOCK TABLES " + tableName + " WRITE";
+ try (Statement preStmt = conn.createStatement();
+ Statement lock = conn.prepareStatement(query)) {
+ if (tableName != null) {
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("Executing 'LOCK TABLES " + tableName + " WRITE' on connection " + conn.toString());
+ if ("SVC_LOGIC".equals(tableName)) {
+ Exception e = new Exception();
+ StringWriter sw = new StringWriter();
+ PrintWriter pw = new PrintWriter(sw);
+ e.printStackTrace(pw);
+ LOGGER.debug(sw.toString());
+ }
+ }
+ lock.execute(query);
+ retValue = true;
+ }
+ } catch (Exception exc) {
+ LOGGER.error("", exc);
+ retValue = false;
+ }
+ return retValue;
+ }
+
+ protected boolean unlockTable(Connection conn) {
+ boolean retValue;
+ try (Statement lock = conn.createStatement()) {
+ if (LOGGER.isDebugEnabled()) {
+ LOGGER.debug("Executing 'UNLOCK TABLES' on connection {}", conn);
+ }
+ retValue = lock.execute("UNLOCK TABLES");
+ } catch (Exception exc) {
+ LOGGER.error("", exc);
+ retValue = false;
+ }
+ return retValue;
+ }
+
+ public void getPoolInfo(boolean allocation) {
+
+ }
+
+ public long getNextErrorReportTime() {
+ return nextErrorReportTime;
+ }
+
+ public void setNextErrorReportTime(long nextTime) {
+ this.nextErrorReportTime = nextTime;
+ }
+
+ public void setGlobalHostName(String hostname) {
+ this.globalHostName = hostname;
+ }
+
+ public String getGlobalHostName() {
+ return globalHostName;
+ }
+
+ static class LapsedTimer {
+ private final long msTime = System.currentTimeMillis();
+
+ public String lapsedTime() {
+ double timediff = System.currentTimeMillis() - msTime;
+ timediff = timediff/1000;
+ return String.valueOf( timediff)+"s";
+ }
+ }
+}
diff --git a/core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/CachedDataSourceFactory.java b/core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/CachedDataSourceFactory.java
new file mode 100644
index 000000000..15aa7a1d0
--- /dev/null
+++ b/core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/CachedDataSourceFactory.java
@@ -0,0 +1,46 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * onap
+ * ================================================================================
+ * Copyright (C) 2016 - 2017 ONAP
+ * ================================================================================
+ * Modifications Copyright (C) 2018 IBM.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.dblib;
+
+
+import org.onap.ccsdk.sli.core.dblib.config.BaseDBConfiguration;
+import org.onap.ccsdk.sli.core.dblib.config.JDBCConfiguration;
+import org.onap.ccsdk.sli.core.dblib.jdbc.JdbcDBCachedDataSource;
+
+/**
+ * @version $Revision: 1.1 $
+ * Change Log
+ * Author Date Comments
+ * ============== ======== ====================================================
+ * Rich Tabedzki
+ */
+public class CachedDataSourceFactory {
+
+ public static CachedDataSource createDataSource(BaseDBConfiguration config) {
+ if(config instanceof JDBCConfiguration)
+ return JdbcDBCachedDataSource.createInstance(config);
+
+ return null;
+ }
+
+}
diff --git a/core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/DBConfigException.java b/core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/DBConfigException.java
new file mode 100644
index 000000000..e41e29b5d
--- /dev/null
+++ b/core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/DBConfigException.java
@@ -0,0 +1,47 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * onap
+ * ================================================================================
+ * Copyright (C) 2016 - 2017 ONAP
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.dblib;
+
+
+/**
+ * @version $Revision: 1.1 $
+ * Change Log
+ * Author Date Comments
+ * ============== ======== ====================================================
+ * Rich Tabedzki
+ */
+public class DBConfigException extends RuntimeException
+{
+ /**
+ *
+ */
+ private static final long serialVersionUID = 4752405152537680257L;
+
+ public DBConfigException(Exception e)
+ {
+ super(e.toString());
+ }
+
+ public DBConfigException(String msg)
+ {
+ super(msg);
+ }
+}
diff --git a/core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/DBLIBResourceProvider.java b/core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/DBLIBResourceProvider.java
new file mode 100755
index 000000000..45e5a7870
--- /dev/null
+++ b/core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/DBLIBResourceProvider.java
@@ -0,0 +1,165 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * onap
+ * ================================================================================
+ * Copyright (C) 2016 - 2017 ONAP
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.dblib;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.Optional;
+import java.util.Properties;
+import java.util.Vector;
+import org.onap.ccsdk.sli.core.utils.JREFileResolver;
+import org.onap.ccsdk.sli.core.utils.KarafRootFileResolver;
+import org.onap.ccsdk.sli.core.utils.PropertiesFileResolver;
+import org.onap.ccsdk.sli.core.utils.common.CoreDefaultFileResolver;
+import org.onap.ccsdk.sli.core.utils.common.SdncConfigEnvVarFileResolver;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Responsible for determining the properties file to use and instantiating the <code>DBResourceManager</code>
+ * Service. The priority for properties file resolution is as follows:
+ *
+ * <ol>
+ * <li>A directory identified by the system environment variable <code>SDNC_CONFIG_DIR</code></li>
+ * <li>The default directory <code>DEFAULT_DBLIB_PROP_DIR</code></li>
+ * <li>A directory identified by the JRE argument <code>dblib.properties</code></li>
+ * <li>A <code>dblib.properties</code> file located in the karaf root directory</li>
+ * </ol>
+ *
+ * Encryption Support
+ * <ol>
+ * <li>Uses ecryption provided by <code>AAAEncryptionService</code></li>
+ * <li>AAA Configuration file is <code>aaa-cert-config.xml</code></li>
+ * </ol>
+ */
+public class DBLIBResourceProvider {
+
+ private static final Logger LOG = LoggerFactory.getLogger(DBLIBResourceProvider.class);
+
+ /**
+ * The name of the properties file for database configuration
+ */
+ private static final String DBLIB_PROP_FILE_NAME = "dblib.properties";
+
+ private static final String DBLIB_PROPERTY_NAME = "org.onap.ccsdk.sli.jdbc.password";
+
+ /**
+ * A prioritized list of strategies for resolving dblib properties files.
+ */
+ private Vector<PropertiesFileResolver> dblibPropertiesFileResolvers = new Vector<>();
+
+ /**
+ * The configuration properties for the db connection.
+ */
+ private Properties properties;
+
+ /**
+ * Set up the prioritized list of strategies for resolving dblib properties files.
+ */
+ public DBLIBResourceProvider() {
+ dblibPropertiesFileResolvers.add(new SdncConfigEnvVarFileResolver(
+ "Using property file (1) from environment variable"
+ ));
+ dblibPropertiesFileResolvers.add(new CoreDefaultFileResolver(
+ "Using property file (2) from default directory"
+ ));
+ dblibPropertiesFileResolvers.add(new JREFileResolver(
+ "Using property file (3) from JRE argument", DBLIBResourceProvider.class
+ ));
+ dblibPropertiesFileResolvers.add(new KarafRootFileResolver(
+ "Using property file (4) from karaf root", this));
+
+ // determines properties file as according to the priority described in the class header comment
+ final File propertiesFile = determinePropertiesFile(this);
+ if (propertiesFile != null) {
+ try(FileInputStream fileInputStream = new FileInputStream(propertiesFile)) {
+ properties = new Properties();
+ properties.load(fileInputStream);
+ } catch (final IOException e) {
+ LOG.error("Failed to load properties for file: {}", propertiesFile.toString(),
+ new DblibConfigurationException("Failed to load properties for file: "
+ + propertiesFile.toString(), e));
+ }
+ }
+ }
+
+ /**
+ * Extract db config properties.
+ *
+ * @return the db config properties
+ */
+ public Properties getProperties() {
+ return properties;
+ }
+
+ /**
+ * Reports the method chosen for properties resolution to the <code>Logger</code>.
+ *
+ * @param message Some user friendly message
+ * @param fileOptional The file location of the chosen properties file
+ * @return the file location of the chosen properties file
+ */
+ private static File reportSuccess(final String message, final Optional<File> fileOptional) {
+ if(fileOptional.isPresent()) {
+ final File file = fileOptional.get();
+ LOG.info("{} {}", message, file.getPath());
+ return file;
+ }
+ return null;
+ }
+
+ /**
+ * Reports fatal errors. This is the case in which no properties file could be found.
+ *
+ * @param message An appropriate fatal error message
+ * @param dblibConfigurationException An exception describing what went wrong during resolution
+ */
+ private static void reportFailure(final String message,
+ final DblibConfigurationException dblibConfigurationException) {
+
+ LOG.error("{}", message, dblibConfigurationException);
+ }
+
+ /**
+ * Determines the dblib properties file to use based on the following priority:
+ * <ol>
+ * <li>A directory identified by the system environment variable <code>SDNC_CONFIG_DIR</code></li>
+ * <li>The default directory <code>DEFAULT_DBLIB_PROP_DIR</code></li>
+ * <li>A directory identified by the JRE argument <code>dblib.properties</code></li>
+ * <li>A <code>dblib.properties</code> file located in the karaf root directory</li>
+ * </ol>
+ */
+ File determinePropertiesFile(final DBLIBResourceProvider dblibResourceProvider) {
+
+ for (final PropertiesFileResolver dblibPropertiesFileResolver : dblibPropertiesFileResolvers) {
+ final Optional<File> fileOptional = dblibPropertiesFileResolver.resolveFile(DBLIB_PROP_FILE_NAME);
+ if (fileOptional.isPresent()) {
+ return reportSuccess(dblibPropertiesFileResolver.getSuccessfulResolutionMessage(), fileOptional);
+ }
+ }
+
+ reportFailure("Missing configuration properties resource(3)",
+ new DblibConfigurationException("Missing configuration properties resource(3): "
+ + DBLIB_PROP_FILE_NAME));
+ return null;
+ }
+}
diff --git a/core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/DBLibConnection.java b/core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/DBLibConnection.java
new file mode 100644
index 000000000..65d0b9512
--- /dev/null
+++ b/core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/DBLibConnection.java
@@ -0,0 +1,387 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * onap
+ * ================================================================================
+ * Copyright (C) 2016 - 2017 ONAP
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.dblib;
+
+import java.sql.Array;
+import java.sql.Blob;
+import java.sql.CallableStatement;
+import java.sql.Clob;
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.NClob;
+import java.sql.PreparedStatement;
+import java.sql.SQLClientInfoException;
+import java.sql.SQLException;
+import java.sql.SQLWarning;
+import java.sql.SQLXML;
+import java.sql.Savepoint;
+import java.sql.Statement;
+import java.sql.Struct;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.concurrent.Executor;
+import javax.sql.rowset.CachedRowSet;
+import org.apache.tomcat.jdbc.pool.PooledConnection;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class DBLibConnection implements Connection {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(DBLibConnection.class);
+
+ private final Connection connection;
+ private final CachedDataSource dataSource;
+ private boolean locked = false;
+ private String tableName = null;
+
+ public DBLibConnection(Connection con, CachedDataSource dataSource) {
+ this.connection = con;
+ this.dataSource = dataSource;
+ locked = false;
+ dataSource.getPoolInfo(true);
+ }
+
+ public boolean lockTable(String tablename) {
+ this.tableName = tablename;
+ locked = dataSource.lockTable(connection, tableName);
+ return locked;
+ }
+
+ public void resetInactivityTimer() {
+ Class<org.apache.tomcat.jdbc.pool.PooledConnection> iface = PooledConnection.class;
+ try {
+ PooledConnection pc = connection.unwrap(iface);
+ pc.setTimestamp(System.currentTimeMillis());
+ } catch (SQLException e) {
+ LOGGER.warn("Failed resetting timeout timer", e);
+ }
+ }
+
+ public boolean unlock() {
+ dataSource.unlockTable(connection);
+ locked = false;
+ return false;
+ }
+
+ public boolean writeData(String statement, List<String> arguments) throws Throwable {
+ ArrayList<Object> newList = new ArrayList<>();
+ if (arguments != null && !arguments.isEmpty()) {
+ newList.addAll(arguments);
+ }
+ resetInactivityTimer();
+ return dataSource.executeUpdatePreparedStatement(connection, statement, newList, false);
+ }
+
+ public CachedRowSet getData(String statement, List<String> arguments) throws Throwable {
+ ArrayList<Object> newList = new ArrayList<>();
+ if (arguments != null && !arguments.isEmpty()) {
+ newList.addAll(arguments);
+ }
+ resetInactivityTimer();
+ return dataSource.executePreparedStatement(connection, statement, newList, false);
+ }
+
+ @Override
+ public <T> T unwrap(Class<T> iFace) throws SQLException {
+ return connection.unwrap(iFace);
+ }
+
+ @Override
+ public boolean isWrapperFor(Class<?> iFace) throws SQLException {
+ return connection.isWrapperFor(iFace);
+ }
+
+ @Override
+ public Statement createStatement() throws SQLException {
+ return connection.createStatement();
+ }
+
+ @Override
+ public PreparedStatement prepareStatement(String sql) throws SQLException {
+ return connection.prepareStatement(sql);
+ }
+
+ @Override
+ public CallableStatement prepareCall(String sql) throws SQLException {
+ return connection.prepareCall(sql);
+ }
+
+ @Override
+ public String nativeSQL(String sql) throws SQLException {
+ return connection.nativeSQL(sql);
+ }
+
+ @Override
+ public void setAutoCommit(boolean autoCommit) throws SQLException {
+ connection.setAutoCommit(autoCommit);
+ }
+
+ @Override
+ public boolean getAutoCommit() throws SQLException {
+ return connection.getAutoCommit();
+ }
+
+ @Override
+ public void commit() throws SQLException {
+ connection.commit();
+ }
+
+ @Override
+ public void rollback() throws SQLException {
+ connection.rollback();
+ }
+
+ @Override
+ public void close() throws SQLException {
+ if (this.locked) {
+ try {
+ this.unlock();
+ } catch (Exception th) {
+ LOGGER.error("Failed unlocking", th);
+ }
+ }
+ if (connection != null && !connection.isClosed()) {
+ connection.close();
+ }
+ dataSource.getPoolInfo(false);
+ }
+
+ @Override
+ public boolean isClosed() throws SQLException {
+ return connection.isClosed();
+ }
+
+ @Override
+ public DatabaseMetaData getMetaData() throws SQLException {
+ return connection.getMetaData();
+ }
+
+ @Override
+ public void setReadOnly(boolean readOnly) throws SQLException {
+ connection.setReadOnly(readOnly);
+ }
+
+ @Override
+ public boolean isReadOnly() throws SQLException {
+ return connection.isReadOnly();
+ }
+
+ @Override
+ public void setCatalog(String catalog) throws SQLException {
+ connection.setCatalog(catalog);
+ }
+
+ @Override
+ public String getCatalog() throws SQLException {
+ return connection.getCatalog();
+ }
+
+ @Override
+ public void setTransactionIsolation(int level) throws SQLException {
+ connection.setTransactionIsolation(level);
+ }
+
+ @Override
+ public int getTransactionIsolation() throws SQLException {
+ return connection.getTransactionIsolation();
+ }
+
+ @Override
+ public SQLWarning getWarnings() throws SQLException {
+ return connection.getWarnings();
+ }
+
+ @Override
+ public void clearWarnings() throws SQLException {
+ connection.clearWarnings();
+ }
+
+ @Override
+ public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException {
+ return connection.createStatement(resultSetType, resultSetConcurrency);
+ }
+
+ @Override
+ public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency)
+ throws SQLException {
+ return connection.prepareStatement(sql, resultSetType, resultSetConcurrency);
+ }
+
+ @Override
+ public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
+ return connection.prepareCall(sql, resultSetType, resultSetConcurrency);
+ }
+
+ @Override
+ public Map<String, Class<?>> getTypeMap() throws SQLException {
+ return connection.getTypeMap();
+ }
+
+ @Override
+ public void setTypeMap(Map<String, Class<?>> map) throws SQLException {
+ connection.setTypeMap(map);
+ }
+
+ @Override
+ public void setHoldability(int holdability) throws SQLException {
+ connection.setHoldability(holdability);
+ }
+
+ @Override
+ public int getHoldability() throws SQLException {
+ return connection.getHoldability();
+ }
+
+ @Override
+ public Savepoint setSavepoint() throws SQLException {
+ return connection.setSavepoint();
+ }
+
+ @Override
+ public Savepoint setSavepoint(String name) throws SQLException {
+ return connection.setSavepoint(name);
+ }
+
+ @Override
+ public void rollback(Savepoint savepoint) throws SQLException {
+ connection.rollback(savepoint);
+ }
+
+ @Override
+ public void releaseSavepoint(Savepoint savepoint) throws SQLException {
+ connection.releaseSavepoint(savepoint);
+ }
+
+ @Override
+ public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability)
+ throws SQLException {
+ return connection.createStatement(resultSetType, resultSetConcurrency, resultSetHoldability);
+ }
+
+ @Override
+ public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency,
+ int resultSetHoldability) throws SQLException {
+ return connection.prepareStatement(sql, resultSetType, resultSetConcurrency, resultSetHoldability);
+ }
+
+ @Override
+ public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency,
+ int resultSetHoldability) throws SQLException {
+ return connection.prepareCall(sql, resultSetType, resultSetConcurrency, resultSetHoldability);
+ }
+
+ @Override
+ public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException {
+ return connection.prepareStatement(sql, autoGeneratedKeys);
+ }
+
+ @Override
+ public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException {
+ return connection.prepareStatement(sql, columnIndexes);
+ }
+
+ @Override
+ public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException {
+ return connection.prepareStatement(sql, columnNames);
+ }
+
+ @Override
+ public Clob createClob() throws SQLException {
+ return connection.createClob();
+ }
+
+ @Override
+ public Blob createBlob() throws SQLException {
+ return connection.createBlob();
+ }
+
+ @Override
+ public NClob createNClob() throws SQLException {
+ return connection.createNClob();
+ }
+
+ @Override
+ public SQLXML createSQLXML() throws SQLException {
+ return connection.createSQLXML();
+ }
+
+ @Override
+ public boolean isValid(int timeout) throws SQLException {
+ return connection.isValid(timeout);
+ }
+
+ @Override
+ public void setClientInfo(String name, String value) throws SQLClientInfoException {
+ connection.setClientInfo(name, value);
+ }
+
+ @Override
+ public void setClientInfo(Properties properties) throws SQLClientInfoException {
+ connection.setClientInfo(properties);
+ }
+
+ @Override
+ public String getClientInfo(String name) throws SQLException {
+ return connection.getClientInfo(name);
+ }
+
+ @Override
+ public Properties getClientInfo() throws SQLException {
+ return connection.getClientInfo();
+ }
+
+ @Override
+ public Array createArrayOf(String typeName, Object[] elements) throws SQLException {
+ return connection.createArrayOf(typeName, elements);
+ }
+
+ @Override
+ public Struct createStruct(String typeName, Object[] attributes) throws SQLException {
+ return connection.createStruct(typeName, attributes);
+ }
+
+ @Override
+ public void setSchema(String schema) throws SQLException {
+ connection.setSchema(schema);
+ }
+
+ @Override
+ public String getSchema() throws SQLException {
+ return connection.getSchema();
+ }
+
+ @Override
+ public void abort(Executor executor) throws SQLException {
+ connection.abort(executor);
+ }
+
+ @Override
+ public void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException {
+ connection.setNetworkTimeout(executor, milliseconds);
+ }
+
+ @Override
+ public int getNetworkTimeout() throws SQLException {
+ return connection.getNetworkTimeout();
+ }
+}
diff --git a/core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/DBLibException.java b/core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/DBLibException.java
new file mode 100644
index 000000000..de241f478
--- /dev/null
+++ b/core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/DBLibException.java
@@ -0,0 +1,39 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * onap
+ * ================================================================================
+ * Copyright (C) 2016 - 2017 ONAP
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.dblib;
+
+import java.sql.SQLException;
+
+/**
+ * An exception time for handling DBLIB specific error handling.
+ */
+public class DBLibException extends SQLException {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -5345059355083984696L;
+
+ public DBLibException(String message){
+ super(message);
+ }
+
+}
diff --git a/core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/DBResourceManager.java b/core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/DBResourceManager.java
new file mode 100755
index 000000000..7c71bcc81
--- /dev/null
+++ b/core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/DBResourceManager.java
@@ -0,0 +1,983 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * onap
+ * ================================================================================
+ * Copyright (C) 2016 - 2017 ONAP
+ * ================================================================================
+ * Modifications Copyright (C) 2018 IBM.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.dblib;
+
+import java.io.PrintWriter;
+import java.sql.Connection;
+import java.sql.Driver;
+import java.sql.SQLDataException;
+import java.sql.SQLException;
+import java.sql.SQLFeatureNotSupportedException;
+import java.sql.SQLIntegrityConstraintViolationException;
+import java.sql.SQLNonTransientConnectionException;
+import java.sql.SQLSyntaxErrorException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Map;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Observable;
+import java.util.Properties;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TimerTask;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.ConcurrentSkipListSet;
+import java.util.stream.Collectors;
+
+import javax.sql.DataSource;
+import javax.sql.rowset.CachedRowSet;
+
+import org.apache.tomcat.jdbc.pool.PoolExhaustedException;
+import org.onap.ccsdk.sli.core.dblib.config.DbConfigPool;
+import org.onap.ccsdk.sli.core.dblib.config.JDBCConfiguration;
+import org.onap.ccsdk.sli.core.dblib.config.TerminatingConfiguration;
+import org.onap.ccsdk.sli.core.dblib.factory.DBConfigFactory;
+import org.onap.ccsdk.sli.core.dblib.pm.PollingWorker;
+import org.onap.ccsdk.sli.core.dblib.pm.SQLExecutionMonitor;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @version $Revision: 1.15 $
+ * Change Log
+ * Author Date Comments
+ * ============== ======== ====================================================
+ * Rich Tabedzki
+ */
+public class DBResourceManager implements DataSource, DataAccessor, DBResourceObserver, DbLibService {
+ private static final Logger LOGGER = LoggerFactory.getLogger(DBResourceManager.class);
+ private static final String DATABASE_URL = "org.onap.ccsdk.sli.jdbc.url";
+
+ transient boolean terminating = false;
+ transient protected long retryInterval = 10000L;
+ transient boolean recoveryMode = true;
+
+ SortedSet<CachedDataSource> dsQueue = new ConcurrentSkipListSet<>(new DataSourceComparator());
+ protected final Set<CachedDataSource> broken = Collections.synchronizedSet(new HashSet<CachedDataSource>());
+ protected final Object monitor = new Object();
+ protected final Properties configProps;
+ protected final Thread worker;
+
+ protected final long terminationTimeOut;
+ protected final boolean monitorDbResponse;
+ protected final long monitoringInterval;
+ protected final long monitoringInitialDelay;
+ protected final long expectedCompletionTime;
+ protected final long unprocessedFailoverThreshold;
+ private static final String LOGGER_ALARM_MSG="Generated alarm: DBResourceManager.getData - No active DB connection pools are available.";
+ private static final String EXCEPTION_MSG= "No active DB connection pools are available in RequestDataNoRecovery call.";
+
+ public DBResourceManager(final DBLIBResourceProvider configuration) {
+ this(configuration.getProperties());
+ }
+
+ public DBResourceManager(final Properties properties) {
+ this.configProps = processSystemVariables(properties);
+
+ // TODO : hack to force classloader to cache mariadb driver. This shouldnt be necessary,
+ // but for some reason it is (without this, dblib throws ClassNotFound on mariadb driver
+ // and fails to load).
+ LOGGER.info("Creating dummy instance of org.mariadb.jdbc.Driver");
+ Driver dvr = new org.mariadb.jdbc.Driver();
+ dvr = null;
+
+ // get retry interval value
+ retryInterval = getLongFromProperties(configProps, "org.onap.dblib.connection.retry", 10000L);
+
+ // get recovery mode flag
+ recoveryMode = getBooleanFromProperties(configProps, "org.onap.dblib.connection.recovery", true);
+ if(!recoveryMode)
+ {
+ recoveryMode = false;
+ LOGGER.info("Recovery Mode disabled");
+ }
+ // get time out value for thread cleanup
+ terminationTimeOut = getLongFromProperties(configProps, "org.onap.dblib.termination.timeout", 300000L);
+ // get properties for monitoring
+ monitorDbResponse = getBooleanFromProperties(configProps, "org.onap.dblib.connection.monitor", false);
+ monitoringInterval = getLongFromProperties(configProps, "org.onap.dblib.connection.monitor.interval", 1000L);
+ monitoringInitialDelay = getLongFromProperties(configProps, "org.onap.dblib.connection.monitor.startdelay", 5000L);
+ expectedCompletionTime = getLongFromProperties(configProps, "org.onap.dblib.connection.monitor.expectedcompletiontime", 5000L);
+ unprocessedFailoverThreshold = getLongFromProperties(configProps, "org.onap.dblib.connection.monitor.unprocessedfailoverthreshold", 3L);
+
+ // initialize performance monitor
+ PollingWorker.createInistance(configProps);
+
+ // initialize recovery thread
+ worker = new RecoveryMgr();
+ worker.setName("DBResourcemanagerWatchThread");
+ worker.setDaemon(true);
+ worker.start();
+
+ try {
+ this.config(configProps);
+ } catch (final Exception e) {
+ // TODO: config throws <code>Exception</code> which is poor practice. Eliminate this in a separate patch.
+ LOGGER.error("Fatal Exception encountered while configuring DBResourceManager", e);
+ }
+ }
+
+ public static Properties processSystemVariables(Properties properties) {
+ Map<Object, Object> hmap = new Properties();
+ hmap.putAll(properties);
+
+ Map<Object, Object> result = hmap.entrySet().stream()
+ .filter(map -> map.getValue().toString().startsWith("${"))
+ .filter(map -> map.getValue().toString().endsWith("}"))
+ .collect(Collectors.toMap(map -> map.getKey(), map -> map.getValue()));
+
+ result.forEach((name, propEntries) -> {
+ hmap.put(name, replace(propEntries.toString()));
+ });
+
+ if(hmap.containsKey(DATABASE_URL) && hmap.get(DATABASE_URL).toString().contains("${")) {
+ String url = hmap.get(DATABASE_URL).toString();
+ String[] innerChunks = url.split("\\$\\{");
+ for(String chunk : innerChunks) {
+ if(chunk.contains("}")) {
+ String subChunk = chunk.substring(0, chunk.indexOf("}"));
+ String varValue = System.getenv(subChunk);
+ url = url.replace("${"+subChunk+"}", varValue);
+ }
+ }
+ hmap.put(DATABASE_URL, url);
+ }
+ return Properties.class.cast(hmap);
+ }
+
+
+ private static String replace(String value) {
+ String globalVariable = value.substring(2, value.length() -1);
+ String varValue = System.getenv(globalVariable);
+ return (varValue != null) ? varValue : value;
+ }
+
+
+ private void config(Properties configProps) throws Exception {
+ final ConcurrentLinkedQueue<CachedDataSource> semaphore = new ConcurrentLinkedQueue<>();
+ final DbConfigPool dbConfig = DBConfigFactory.createConfig(configProps);
+
+ long startTime = System.currentTimeMillis();
+
+ try {
+ JDBCConfiguration[] config = dbConfig.getJDBCbSourceArray();
+ CachedDataSource[] cachedDS = new CachedDataSource[config.length];
+ if (cachedDS == null || cachedDS.length == 0) {
+ LOGGER.error("Initialization of CachedDataSources failed. No instance was created.");
+ throw new Exception("Failed to initialize DB Library. No data source was created.");
+ }
+
+ for(int i = 0; i < config.length; i++) {
+ cachedDS[i] = CachedDataSourceFactory.createDataSource(config[i]);
+ if(cachedDS[i] == null)
+ continue;
+ semaphore.add(cachedDS[i]);
+ cachedDS[i].setInterval(monitoringInterval);
+ cachedDS[i].setInitialDelay(monitoringInitialDelay);
+ cachedDS[i].setExpectedCompletionTime(expectedCompletionTime);
+ cachedDS[i].setUnprocessedFailoverThreshold(unprocessedFailoverThreshold);
+ cachedDS[i].addObserver(DBResourceManager.this);
+ }
+
+ DataSourceTester[] tester = new DataSourceTester[config.length];
+
+ for(int i=0; i<tester.length; i++){
+ tester[i] = new DataSourceTester(cachedDS[i], DBResourceManager.this, semaphore);
+ tester[i].start();
+ }
+
+ // the timeout param is set is seconds.
+ long timeout = ((dbConfig.getTimeout() <= 0) ? 60L : dbConfig.getTimeout());
+ LOGGER.debug("Timeout set to {} seconds", timeout);
+ timeout *= 1000;
+
+
+ synchronized (semaphore) {
+ semaphore.wait(timeout);
+ }
+ } catch(Exception exc){
+ LOGGER.warn("DBResourceManager.initWorker", exc);
+ } finally {
+ startTime = System.currentTimeMillis() - startTime;
+ LOGGER.info("Completed wait with {} active datasource(s) in {} ms", dsQueue.size(), startTime);
+ }
+ }
+
+
+ private final class DataSourceComparator implements Comparator<CachedDataSource> {
+ @Override
+ public int compare(CachedDataSource left, CachedDataSource right) {
+ if(LOGGER.isTraceEnabled())
+ LOGGER.trace("----------SORTING-------- () : ()", left.getDbConnectionName(), right.getDbConnectionName());
+ try {
+ if(left == right) {
+ return 0;
+ }
+ if(left == null){
+ return 1;
+ }
+ if(right == null){
+ return -1;
+ }
+
+ boolean leftMaster = !left.isSlave();
+ if(leftMaster) {
+ if(left.getIndex() <= right.getIndex())
+ return -1;
+ else {
+ boolean rightMaster = !right.isSlave();
+ if(rightMaster) {
+ if(left.getIndex() <= right.getIndex())
+ return -1;
+// if(left.getIndex() > right.getIndex())
+ else {
+ return 1;
+ }
+ } else {
+ return -1;
+ }
+ }
+ }
+ if(!right.isSlave())
+ return 1;
+
+ if(left.getIndex() <= right.getIndex())
+ return -1;
+ if(left.getIndex() > right.getIndex())
+ return 1;
+
+
+ } catch (Throwable e) {
+ LOGGER.warn("", e);
+ }
+ return -1;
+ }
+ }
+
+ class DataSourceTester extends Thread {
+
+ private final CachedDataSource ds;
+ private final DBResourceManager manager;
+ private final ConcurrentLinkedQueue<CachedDataSource> semaphoreQ;
+
+ public DataSourceTester(CachedDataSource ds, DBResourceManager manager, ConcurrentLinkedQueue<CachedDataSource> semaphore) {
+ this.ds = ds;
+ this.manager = manager;
+ this.semaphoreQ = semaphore;
+ }
+
+ @Override
+ public void run() {
+ manager.setDataSource(ds);
+ boolean slave = true;
+ if(ds != null) {
+ try {
+ slave = ds.isSlave();
+ } catch (Exception exc) {
+ LOGGER.warn("", exc);
+ }
+ }
+ if(!slave) {
+ LOGGER.info("Adding MASTER {} to active queue", ds.getDbConnectionName());
+ try {
+ synchronized (semaphoreQ) {
+ semaphoreQ.notifyAll();
+ }
+ } catch(Exception exc) {
+ LOGGER.warn("", exc);
+ }
+ }
+ try {
+ synchronized (semaphoreQ) {
+ semaphoreQ.remove(ds);
+ }
+ if(semaphoreQ.isEmpty()) {
+ synchronized (semaphoreQ) {
+ semaphoreQ.notifyAll();
+ }
+ }
+ } catch(Exception exc) {
+ LOGGER.warn("", exc);
+ }
+ if(ds != null)
+ LOGGER.info("Thread DataSourceTester terminated {} for {}", this.getName(), ds.getDbConnectionName());
+ }
+
+ }
+
+
+ private long getLongFromProperties(Properties props, String property, long defaultValue)
+ {
+ String value = null;
+ long tmpLongValue = defaultValue;
+ try {
+ value = props.getProperty(property);
+ if(value != null)
+ tmpLongValue = Long.parseLong(value);
+
+ } catch(NumberFormatException exc) {
+ if(LOGGER.isWarnEnabled()){
+ LOGGER.warn("'"+property+"'=" + value+" is invalid. It should be a numeric value");
+ }
+ } catch(Exception exc) {
+ }
+ return tmpLongValue;
+
+ }
+
+ private boolean getBooleanFromProperties(Properties props, String property, boolean defaultValue)
+ {
+ boolean tmpValue = defaultValue;
+ String value = null;
+
+ try {
+ value = props.getProperty(property);
+ if(value != null)
+ tmpValue = Boolean.parseBoolean(value);
+
+ } catch(NumberFormatException exc) {
+ if(LOGGER.isWarnEnabled()){
+ LOGGER.warn("'"+property+"'=" + value+" is invalid. It should be a boolean value");
+ }
+ } catch(Exception exc) {
+ }
+ return tmpValue;
+
+ }
+
+
+ @Override
+ public void update(Observable observable, Object data) {
+ // if observable is active and there is a standby available, switch
+ if(observable instanceof SQLExecutionMonitor)
+ {
+ SQLExecutionMonitor monitor = (SQLExecutionMonitor)observable;
+ if(monitor.getParent() instanceof CachedDataSource)
+ {
+ CachedDataSource dataSource = (CachedDataSource)monitor.getParent();
+ if(dataSource == dsQueue.first())
+ {
+ if(recoveryMode && dsQueue.size() > 1){
+ handleGetConnectionException(dataSource, new Exception(data.toString()));
+ }
+ }
+ }
+ }
+ }
+
+ public void testForceRecovery()
+ {
+ CachedDataSource active = this.dsQueue.first();
+ handleGetConnectionException(active, new Exception("test"));
+ }
+
+ class RecoveryMgr extends Thread {
+
+ @Override
+ public void run() {
+ while(!terminating)
+ {
+ try {
+ Thread.sleep(retryInterval);
+ } catch (InterruptedException e1) { }
+ CachedDataSource brokenSource = null;
+ try {
+ if (!broken.isEmpty()) {
+ CachedDataSource[] sourceArray = broken.toArray(new CachedDataSource[0]);
+ for (int i = 0; i < sourceArray.length; i++)
+ {
+ brokenSource = sourceArray[i];
+ if (brokenSource instanceof TerminatingCachedDataSource)
+ break;
+ if (resetConnectionPool(brokenSource)) {
+ broken.remove(brokenSource);
+ brokenSource.blockImmediateOffLine();
+ dsQueue.add(brokenSource);
+ LOGGER.info("DataSource <"
+ + brokenSource.getDbConnectionName()
+ + "> recovered.");
+ }
+ brokenSource = null;
+ }
+ }
+ } catch (Exception exc) {
+ LOGGER.warn(exc.getMessage());
+ if(brokenSource != null){
+ try {
+ if(!broken.contains(brokenSource))
+ broken.add(brokenSource);
+ brokenSource = null;
+ } catch (Exception e1) { }
+ }
+ }
+ }
+ LOGGER.info("DBResourceManager.RecoveryMgr <"+this.toString() +"> terminated." );
+ }
+
+ private boolean resetConnectionPool(CachedDataSource dataSource){
+ try {
+ return dataSource.testConnection();
+ } catch (Exception exc) {
+ LOGGER.info("DataSource <" + dataSource.getDbConnectionName() + "> resetCache failed with error: "+ exc.getMessage());
+ return false;
+ }
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.onap.ccsdk.sli.resource.dblib.DbLibService#getData(java.lang.String, java.util.ArrayList, java.lang.String)
+ */
+ @Override
+ public CachedRowSet getData(String statement, ArrayList<String> arguments, String preferredDS) throws SQLException {
+ ArrayList<Object> newList= new ArrayList<>();
+ if(arguments != null && !arguments.isEmpty()) {
+ newList.addAll(arguments);
+ }
+ if(recoveryMode)
+ return requestDataWithRecovery(statement, newList, preferredDS);
+ else
+ return requestDataNoRecovery(statement, newList, preferredDS);
+ }
+
+ private CachedRowSet requestDataWithRecovery(String statement, ArrayList<Object> arguments, String preferredDS) throws SQLException {
+ Throwable lastException = null;
+
+ // test if there are any connection pools available
+ if(this.dsQueue.isEmpty()){
+ LOGGER.error(LOGGER_ALARM_MSG);
+ throw new DBLibException("No active DB connection pools are available in RequestDataWithRecovery call.");
+ }
+
+ // loop through available data sources to retrieve data.
+ for(int i=0; i< 2; i++)
+ {
+ CachedDataSource active = this.dsQueue.first();
+
+ long time = System.currentTimeMillis();
+ try {
+ if(!active.isFabric()) {
+ if(this.dsQueue.size() > 1 && active.isSlave()) {
+ CachedDataSource master = findMaster();
+ if(master != null) {
+ active = master;
+ }
+ }
+ }
+
+ return active.getData(statement, arguments);
+ } catch(SQLDataException | SQLSyntaxErrorException | SQLIntegrityConstraintViolationException exc){
+ throw exc;
+ } catch(Throwable exc){
+ if(exc instanceof SQLException) {
+ SQLException sqlExc = (SQLException)exc;
+ int code = sqlExc.getErrorCode();
+ String state = sqlExc.getSQLState();
+ LOGGER.debug("SQLException code: {} state: {}", code, state);
+ if("07001".equals(sqlExc.getSQLState())) {
+ throw sqlExc;
+ }
+ }
+ lastException = exc;
+ LOGGER.error("Generated alarm: {}", active.getDbConnectionName(), exc);
+ handleGetConnectionException(active, exc);
+ } finally {
+ if(LOGGER.isDebugEnabled()){
+ time = System.currentTimeMillis() - time;
+ LOGGER.debug("getData processing time : {} {} miliseconds.", active.getDbConnectionName(), time);
+ }
+ }
+ }
+ if(lastException instanceof SQLException){
+ throw (SQLException)lastException;
+ }
+ // repackage the exception
+ // you are here because either you run out of available data sources
+ // or the last exception was not of SQLException type.
+ // repackage the exception
+ if(lastException == null) {
+ throw new DBLibException("The operation timed out while waiting to acquire a new connection." );
+ } else {
+ SQLException exception = new DBLibException(lastException.getMessage());
+ exception.setStackTrace(lastException.getStackTrace());
+ if(lastException.getCause() instanceof SQLException) {
+ throw (SQLException)lastException.getCause();
+ }
+ throw exception;
+ }
+ }
+
+ private CachedRowSet requestDataNoRecovery(String statement, ArrayList<Object> arguments, String preferredDS) throws SQLException {
+ if(dsQueue.isEmpty()){
+ LOGGER.error(LOGGER_ALARM_MSG);
+ throw new DBLibException(EXCEPTION_MSG);
+ }
+ CachedDataSource active = this.dsQueue.first();
+ long time = System.currentTimeMillis();
+ try {
+ if(!active.isFabric()) {
+ if(this.dsQueue.size() > 1 && active.isSlave()) {
+ CachedDataSource master = findMaster();
+ if(master != null) {
+ active = master;
+ }
+ }
+ }
+ return active.getData(statement, arguments);
+
+ } catch(Throwable exc){
+ String message = exc.getMessage();
+ if(message == null)
+ message = exc.getClass().getName();
+ LOGGER.error("Generated alarm: {} - {}",active.getDbConnectionName(), message);
+ if(exc instanceof SQLException)
+ throw (SQLException)exc;
+ else {
+ DBLibException excptn = new DBLibException(exc.getMessage());
+ excptn.setStackTrace(exc.getStackTrace());
+ throw excptn;
+ }
+ } finally {
+ if(LOGGER.isDebugEnabled()){
+ time = System.currentTimeMillis() - time;
+ LOGGER.debug(">> getData : {} {} miliseconds.", active.getDbConnectionName(), time);
+ }
+ }
+ }
+
+
+ /* (non-Javadoc)
+ * @see org.onap.ccsdk.sli.resource.dblib.DbLibService#writeData(java.lang.String, java.util.ArrayList, java.lang.String)
+ */
+ @Override
+ public boolean writeData(String statement, ArrayList<String> arguments, String preferredDS) throws SQLException
+ {
+ ArrayList<Object> newList= new ArrayList<>();
+ if(arguments != null && !arguments.isEmpty()) {
+ newList.addAll(arguments);
+ }
+
+ return writeDataNoRecovery(statement, newList, preferredDS);
+ }
+
+ synchronized CachedDataSource findMaster() throws SQLException {
+ final CachedDataSource[] clone = this.dsQueue.toArray(new CachedDataSource[0]);
+
+ for(final CachedDataSource dss : clone) {
+ if(!dss.isSlave()) {
+ final CachedDataSource first = this.dsQueue.first();
+ if(first != dss) {
+ if(LOGGER.isDebugEnabled())
+ LOGGER.debug("----------REODRERING--------");
+ dsQueue.clear();
+ if(!dsQueue.addAll(Arrays.asList(clone))) {
+ LOGGER.error("Failed adding datasources");
+ }
+ }
+ return dss;
+ }
+ }
+ LOGGER.warn("MASTER not found.");
+ return null;
+ }
+
+
+ private boolean writeDataNoRecovery(String statement, ArrayList<Object> arguments, String preferredDS) throws SQLException {
+ if(dsQueue.isEmpty()){
+ LOGGER.error(LOGGER_ALARM_MSG);
+ throw new DBLibException(EXCEPTION_MSG);
+ }
+
+ boolean initialRequest = true;
+ boolean retryAllowed = true;
+ CachedDataSource active = this.dsQueue.first();
+ long time = System.currentTimeMillis();
+ while(initialRequest) {
+ initialRequest = false;
+ try {
+ if(!active.isFabric()) {
+ if(this.dsQueue.size() > 1 && active.isSlave()) {
+ CachedDataSource master = findMaster();
+ if(master != null) {
+ active = master;
+ }
+ }
+ }
+
+ return active.writeData(statement, arguments);
+ } catch(Throwable exc){
+ String message = exc.getMessage();
+ if(message == null)
+ message = exc.getClass().getName();
+ LOGGER.error("Generated alarm: {} - {}", active.getDbConnectionName(), message);
+ if(exc instanceof SQLException) {
+ SQLException sqlExc = SQLException.class.cast(exc);
+ // handle read-only exception
+ if(sqlExc.getErrorCode() == 1290 && "HY000".equals(sqlExc.getSQLState())) {
+ LOGGER.warn("retrying due to: {}", sqlExc.getMessage());
+ this.findMaster();
+ if(retryAllowed){
+ retryAllowed = false;
+ initialRequest = true;
+ continue;
+ }
+ }
+ throw (SQLException)exc;
+ } else {
+ DBLibException excptn = new DBLibException(exc.getMessage());
+ excptn.setStackTrace(exc.getStackTrace());
+ throw excptn;
+ }
+ } finally {
+ if(LOGGER.isDebugEnabled()){
+ time = System.currentTimeMillis() - time;
+ LOGGER.debug("writeData processing time : {} {} miliseconds.", active.getDbConnectionName(), time);
+ }
+ }
+ }
+ return true;
+ }
+
+ public void setDataSource(CachedDataSource dataSource) {
+ if(this.dsQueue.contains(dataSource))
+ return;
+ if(this.broken.contains(dataSource))
+ return;
+
+ if(dataSource.testConnection(true)){
+ this.dsQueue.add(dataSource);
+ } else {
+ this.broken.add(dataSource);
+ }
+ }
+
+ @Override
+ public Connection getConnection() throws SQLException {
+ Throwable lastException = null;
+ CachedDataSource active = null;
+
+ if(dsQueue.isEmpty()){
+ throw new DBLibException("No active DB connection pools are available in GetConnection call.");
+ }
+
+ try {
+ active = dsQueue.first();
+
+ if(!active.isFabric()) {
+ if(this.dsQueue.size() > 1 && active.isSlave()) {
+ LOGGER.debug("Forcing reorder on: {}", dsQueue.toString());
+ CachedDataSource master = findMaster();
+ if(master != null) {
+ active = master;
+ }
+ }
+ }
+ return new DBLibConnection(active.getConnection(), active);
+ } catch(javax.sql.rowset.spi.SyncFactoryException exc){
+ LOGGER.debug("Free memory (bytes): " + Runtime.getRuntime().freeMemory());
+ LOGGER.warn("CLASSPATH issue. Allowing retry", exc);
+ lastException = exc;
+ } catch(PoolExhaustedException exc) {
+ throw new NoAvailableConnectionsException(exc);
+ } catch(SQLNonTransientConnectionException exc){
+ throw new NoAvailableConnectionsException(exc);
+ } catch(Exception exc){
+ lastException = exc;
+ if(recoveryMode){
+ handleGetConnectionException(active, exc);
+ } else {
+ if(exc instanceof SQLException) {
+ throw (SQLException)exc;
+ } else {
+ DBLibException excptn = new DBLibException(exc.getMessage());
+ excptn.setStackTrace(exc.getStackTrace());
+ throw excptn;
+ }
+ }
+ } catch (Throwable trwb) {
+ DBLibException excptn = new DBLibException(trwb.getMessage());
+ excptn.setStackTrace(trwb.getStackTrace());
+ throw excptn;
+ } finally {
+ if(LOGGER.isDebugEnabled()){
+ displayState();
+ }
+ }
+
+ if(lastException instanceof SQLException){
+ throw (SQLException)lastException;
+ }
+ // repackage the exception
+ if(lastException == null) {
+ throw new DBLibException("The operation timed out while waiting to acquire a new connection." );
+ } else {
+ SQLException exception = new DBLibException(lastException.getMessage());
+ exception.setStackTrace(lastException.getStackTrace());
+ if(lastException.getCause() instanceof SQLException) {
+
+ throw (SQLException)lastException.getCause();
+ }
+ throw exception;
+ }
+ }
+
+ @Override
+ public Connection getConnection(String username, String password)
+ throws SQLException {
+ CachedDataSource active = null;
+
+ if(dsQueue.isEmpty()){
+ throw new DBLibException("No active DB connection pools are available in GetConnection call.");
+ }
+
+
+ try {
+ active = dsQueue.first();
+ if(!active.isFabric()) {
+ if(this.dsQueue.size() > 1 && active.isSlave()) {
+ CachedDataSource master = findMaster();
+ if(master != null) {
+ active = master;
+ }
+ }
+ }
+ return active.getConnection(username, password);
+ } catch(Throwable exc){
+ if(recoveryMode){
+ handleGetConnectionException(active, exc);
+ } else {
+ if(exc instanceof SQLException)
+ throw (SQLException)exc;
+ else {
+ DBLibException excptn = new DBLibException(exc.getMessage());
+ excptn.setStackTrace(exc.getStackTrace());
+ throw excptn;
+ }
+ }
+
+ }
+
+ throw new DBLibException("No connections available in DBResourceManager in GetConnection call.");
+ }
+
+ private void handleGetConnectionException(final CachedDataSource source, Throwable exc) {
+ try {
+ if(!source.canTakeOffLine())
+ {
+ LOGGER.error("Could not switch due to blocking");
+ return;
+ }
+
+ boolean removed = dsQueue.remove(source);
+ if(!broken.contains(source))
+ {
+ if(broken.add(source))
+ {
+ LOGGER.warn("DB Recovery: DataSource <" + source.getDbConnectionName() + "> put in the recovery mode. Reason : " + exc.getMessage());
+ } else {
+ LOGGER.warn("Error putting DataSource <" +source.getDbConnectionName()+ "> in recovery mode.");
+ }
+ } else {
+ LOGGER.info("DB Recovery: DataSource <" + source.getDbConnectionName() + "> already in recovery queue");
+ }
+ if(removed)
+ {
+ if(!dsQueue.isEmpty())
+ {
+ LOGGER.warn("DB DataSource <" + dsQueue.first().getDbConnectionName() + "> became active");
+ }
+ }
+ } catch (Exception e) {
+ LOGGER.error("", e);
+ }
+ }
+
+ public void cleanUp() {
+ for(Iterator<CachedDataSource> it=dsQueue.iterator();it.hasNext();){
+ CachedDataSource cds = it.next();
+ it.remove();
+ cds.cleanUp();
+ }
+
+ try {
+ this.terminating = true;
+ if(broken != null)
+ {
+ try {
+ broken.add( new TerminatingCachedDataSource(new TerminatingConfiguration()));
+ } catch(Exception exc){
+ LOGGER.error("Waiting for Worker to stop", exc);
+ }
+ }
+ worker.join(terminationTimeOut);
+ LOGGER.info("DBResourceManager.RecoveryMgr <"+worker.toString() +"> termination was successful: " + worker.getState());
+ } catch(Exception exc){
+ LOGGER.error("Waiting for Worker thread to terminate ", exc);
+ }
+ }
+
+ @Override
+ public PrintWriter getLogWriter() throws SQLException {
+ return this.dsQueue.first().getLogWriter();
+ }
+
+ @Override
+ public int getLoginTimeout() throws SQLException {
+ return this.dsQueue.first().getLoginTimeout();
+ }
+
+ @Override
+ public void setLogWriter(PrintWriter out) throws SQLException {
+ this.dsQueue.first().setLogWriter(out);
+ }
+
+ @Override
+ public void setLoginTimeout(int seconds) throws SQLException {
+ this.dsQueue.first().setLoginTimeout(seconds);
+ }
+
+ public void displayState(){
+ if(LOGGER.isDebugEnabled()){
+ LOGGER.debug("POOLS : Active = "+dsQueue.size() + ";\t Broken = "+broken.size());
+ CachedDataSource current = dsQueue.first();
+ if(current != null) {
+ LOGGER.debug("POOL : Active name = \'"+current.getDbConnectionName()+ "\'");
+ }
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.onap.ccsdk.sli.resource.dblib.DbLibService#isActive()
+ */
+ @Override
+ public boolean isActive() {
+ return this.dsQueue.size()>0;
+ }
+
+ public String getActiveStatus(){
+ return "Connected: " + dsQueue.size()+"\tIn-recovery: "+broken.size();
+ }
+
+ public String getDBStatus(boolean htmlFormat) {
+ StringBuilder buffer = new StringBuilder();
+
+ ArrayList<CachedDataSource> list = new ArrayList<>();
+ list.addAll(dsQueue);
+ list.addAll(broken);
+ if (htmlFormat)
+ {
+ buffer.append("<tr class=\"headerRow\"><th id=\"header1\">")
+ .append("Name:").append("</th>");
+ for (int i = 0; i < list.size(); i++) {
+ buffer.append("<th id=\"header").append(2 + i).append("\">");
+ buffer.append(list.get(i).getDbConnectionName()).append("</th>");
+ }
+ buffer.append("</tr>");
+
+ buffer.append("<tr><td>State:</td>");
+ for (int i = 0; i < list.size(); i++) {
+ if (broken.contains(list.get(i))) {
+ buffer.append("<td>in recovery</td>");
+ }
+ if (dsQueue.contains(list.get(i))) {
+ if (dsQueue.first() == list.get(i))
+ buffer.append("<td>active</td>");
+ else
+ buffer.append("<td>standby</td>");
+ }
+ }
+ buffer.append("</tr>");
+
+ } else {
+ for (int i = 0; i < list.size(); i++) {
+ buffer.append("Name: ").append(list.get(i).getDbConnectionName());
+ buffer.append("\tState: ");
+ if (broken.contains(list.get(i))) {
+ buffer.append("in recovery");
+ } else
+ if (dsQueue.contains(list.get(i))) {
+ if (dsQueue.first() == list.get(i))
+ buffer.append("active");
+ else
+ buffer.append("standby");
+ }
+
+ buffer.append("\n");
+
+ }
+ }
+ return buffer.toString();
+ }
+
+ @Override
+ public boolean isWrapperFor(Class<?> iface) throws SQLException {
+ return false;
+ }
+
+ @Override
+ public <T> T unwrap(Class<T> iface) throws SQLException {
+ return null;
+ }
+
+ /**
+ * @return the monitorDbResponse
+ */
+ @Override
+ public final boolean isMonitorDbResponse() {
+ return recoveryMode && monitorDbResponse;
+ }
+
+ public void test(){
+ CachedDataSource obj = dsQueue.first();
+ Exception ption = new Exception();
+ try {
+ for(int i=0; i<5; i++)
+ {
+ handleGetConnectionException(obj, ption);
+ }
+ } catch(Throwable exc){
+ LOGGER.warn("", exc);
+ }
+ }
+
+ @Override
+ public java.util.logging.Logger getParentLogger()
+ throws SQLFeatureNotSupportedException {
+ return null;
+ }
+
+ class RemindTask extends TimerTask {
+ @Override
+ public void run() {
+ CachedDataSource ds = dsQueue.first();
+ if(ds != null)
+ ds.getPoolInfo(false);
+ }
+ }
+
+ public int poolSize() {
+ return dsQueue.size();
+ }
+}
diff --git a/core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/DBResourceObserver.java b/core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/DBResourceObserver.java
new file mode 100644
index 000000000..f30212dca
--- /dev/null
+++ b/core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/DBResourceObserver.java
@@ -0,0 +1,27 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * onap
+ * ================================================================================
+ * Copyright (C) 2016 - 2017 ONAP
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.dblib;
+
+import java.util.Observer;
+
+public interface DBResourceObserver extends Observer {
+ boolean isMonitorDbResponse();
+}
diff --git a/core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/DataAccessor.java b/core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/DataAccessor.java
new file mode 100644
index 000000000..93d8b6bf5
--- /dev/null
+++ b/core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/DataAccessor.java
@@ -0,0 +1,34 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * onap
+ * ================================================================================
+ * Copyright (C) 2016 - 2017 ONAP
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.dblib;
+
+import java.sql.SQLException;
+import java.util.ArrayList;
+
+import javax.sql.rowset.CachedRowSet;
+
+@FunctionalInterface
+public interface DataAccessor {
+
+ CachedRowSet getData(String statement, ArrayList<String> arguments, String preferredDS)
+ throws SQLException;
+
+}
diff --git a/core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/DataSourceComparator.java b/core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/DataSourceComparator.java
new file mode 100644
index 000000000..4cfcc7318
--- /dev/null
+++ b/core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/DataSourceComparator.java
@@ -0,0 +1,33 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * onap
+ * ================================================================================
+ * Copyright (C) 2016 - 2017 ONAP
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.dblib;
+
+import java.util.Comparator;
+
+public interface DataSourceComparator extends Comparator <CachedDataSource>{
+
+ CachedDataSource getLastUsed();
+
+ void setLastUsed(CachedDataSource lastUsed);
+
+ int compare(CachedDataSource ds1, CachedDataSource ds2);
+
+}
diff --git a/core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/DbLibService.java b/core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/DbLibService.java
new file mode 100644
index 000000000..b30ad7bbf
--- /dev/null
+++ b/core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/DbLibService.java
@@ -0,0 +1,50 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * onap
+ * ================================================================================
+ * Copyright (C) 2016 - 2017 ONAP
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.dblib;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.ArrayList;
+
+import javax.sql.DataSource;
+import javax.sql.rowset.CachedRowSet;
+
+public interface DbLibService extends DataSource {
+
+ /* (non-Javadoc)
+ * @see DataAccessor#getData(java.lang.String, java.util.ArrayList)
+ */
+ CachedRowSet getData(String statement,
+ ArrayList<String> arguments, String preferredDS)
+ throws SQLException;
+
+ /* (non-Javadoc)
+ * @see DataAccessor#writeData(java.lang.String, java.util.ArrayList)
+ */
+ boolean writeData(String statement,
+ ArrayList<String> arguments, String preferredDS)
+ throws SQLException;
+
+ boolean isActive();
+
+ Connection getConnection() throws SQLException;
+
+}
diff --git a/core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/DblibConfigurationException.java b/core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/DblibConfigurationException.java
new file mode 100644
index 000000000..be493aa1f
--- /dev/null
+++ b/core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/DblibConfigurationException.java
@@ -0,0 +1,45 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * onap
+ * ================================================================================
+ * Copyright (C) 2016 - 2017 ONAP
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.dblib;
+
+
+public class DblibConfigurationException extends Exception {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1L;
+
+ public DblibConfigurationException()
+ {
+ super();
+ }
+
+ public DblibConfigurationException(String msg)
+ {
+ super(msg);
+ }
+
+ public DblibConfigurationException(String msg, Throwable t)
+ {
+ super(msg, t);
+ }
+}
diff --git a/core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/NoAvailableConnectionsException.java b/core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/NoAvailableConnectionsException.java
new file mode 100644
index 000000000..a39e5c5b4
--- /dev/null
+++ b/core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/NoAvailableConnectionsException.java
@@ -0,0 +1,36 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * onap
+ * ================================================================================
+ * Copyright (C) 2016 - 2017 ONAP
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.dblib;
+
+import java.sql.SQLException;
+
+public class NoAvailableConnectionsException extends SQLException {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -6259205931674413018L;
+
+ public NoAvailableConnectionsException(Exception exc) {
+ super(exc);
+ }
+
+}
diff --git a/core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/TerminatingCachedDataSource.java b/core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/TerminatingCachedDataSource.java
new file mode 100755
index 000000000..852dda3c7
--- /dev/null
+++ b/core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/TerminatingCachedDataSource.java
@@ -0,0 +1,59 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * onap
+ * ================================================================================
+ * Copyright (C) 2016 - 2017 ONAP
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.dblib;
+
+import java.sql.SQLFeatureNotSupportedException;
+import java.util.logging.Logger;
+import javax.sql.DataSource;
+import org.onap.ccsdk.sli.core.dblib.config.BaseDBConfiguration;
+import org.onap.ccsdk.sli.core.dblib.pm.SQLExecutionMonitorObserver;
+
+
+public class TerminatingCachedDataSource extends CachedDataSource implements SQLExecutionMonitorObserver {
+
+ private static final int DEFAULT_AVAILABLE_CONNECTIONS = 0;
+ private static final int DEFAULT_INDEX = -1;
+
+ public TerminatingCachedDataSource(BaseDBConfiguration jdbcElem) throws DBConfigException {
+ super(jdbcElem);
+ }
+
+ @Override
+ protected DataSource configure(BaseDBConfiguration jdbcElem) throws DBConfigException {
+ return null;
+ }
+
+ @Override
+ public Logger getParentLogger() throws SQLFeatureNotSupportedException {
+ return null;
+ }
+
+ @Override
+ protected int getAvailableConnections() {
+ return DEFAULT_AVAILABLE_CONNECTIONS;
+ }
+
+ @Override
+ protected int initializeIndex(BaseDBConfiguration jdbcElem) {
+ return DEFAULT_INDEX;
+ }
+
+}
diff --git a/core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/config/BaseDBConfiguration.java b/core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/config/BaseDBConfiguration.java
new file mode 100755
index 000000000..ea6bc450d
--- /dev/null
+++ b/core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/config/BaseDBConfiguration.java
@@ -0,0 +1,258 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * onap
+ * ================================================================================
+ * Copyright (C) 2016 - 2017 ONAP
+ * Modifications Copyright (C) 2018 IBM.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.dblib.config;
+
+import java.util.Properties;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+/**
+ * Base class responsible for parsing business logic for database configuration from given <code>Properties</code>.
+ */
+public abstract class BaseDBConfiguration {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(BaseDBConfiguration.class);
+ /**
+ * Property key within a properties configuration File for db type
+ */
+ public static final String DATABASE_TYPE = "org.onap.ccsdk.sli.dbtype";
+
+ /**
+ * Property key with a properties configuration File for db url
+ */
+ public static final String DATABASE_URL = "org.onap.ccsdk.sli.jdbc.url";
+
+ /**
+ * Property key with a properties configuration File for database name
+ */
+ public static final String DATABASE_NAME = "org.onap.ccsdk.sli.jdbc.database";
+
+ /**
+ * Property key with a properties configuration File for jdbc driver
+ */
+ public static final String DRIVER_NAME = "org.onap.ccsdk.sli.jdbc.driver";
+
+ /**
+ * Property key with a properties configuration File for db database connection name
+ */
+ public static final String CONNECTION_NAME = "org.onap.ccsdk.sli.jdbc.connection.name";
+
+ /**
+ * Property key with a properties configuration File for database user
+ */
+ public static final String DATABASE_USER = "org.onap.ccsdk.sli.jdbc.user";
+
+ /**
+ * Property key with a properties configuration File for database password
+ * for associated with <code>org.onap.ccsdk.sli.jdbc.user</code>.
+ */
+ public static final String DATABASE_PSSWD = "org.onap.ccsdk.sli.jdbc.password";
+
+ /**
+ * Property key with a properties configuration File for database connection
+ * timeout
+ */
+ public static final String CONNECTION_TIMEOUT="org.onap.ccsdk.sli.jdbc.connection.timeout";
+
+ /**
+ * Property key with a properties configuration File for database request
+ * timeout
+ */
+ public static final String REQUEST_TIMEOUT = "org.onap.ccsdk.sli.jdbc.request.timeout";
+
+ /**
+ * Property key with a properties configuration File for database minimum
+ * limit
+ */
+ public static final String MIN_LIMIT = "org.onap.ccsdk.sli.jdbc.limit.min";
+
+ /**
+ * Property key with a properties configuration File for database maximum
+ * limit
+ */
+ public static final String MAX_LIMIT = "org.onap.ccsdk.sli.jdbc.limit.max";
+
+ /**
+ * Property key with a properties configuration File for database initial
+ * limit
+ */
+ public static final String INIT_LIMIT = "org.onap.ccsdk.sli.jdbc.limit.init";
+
+ /**
+ * Property key with a properties configuration File for database hosts
+ */
+ public static final String DATABASE_HOSTS = "org.onap.ccsdk.sli.jdbc.hosts";
+
+ /**
+ * default value when the connection timeout is not present or cannot be
+ * parsed.
+ */
+ private static final String DEFAULT_REJECT_CHANGE_VALUE = "-1";
+
+ /**
+ * A set of properties with database configuration information.
+ */
+ protected final Properties properties;
+
+ /**
+ * Builds a configuration based on given properties
+ *
+ * @param properties
+ * properties represented by the public constant keys defined by
+ * this class
+ */
+ public BaseDBConfiguration(final Properties properties) {
+ this.properties = properties;
+ }
+
+ /**
+ * Extracts the connection timeout.
+ *
+ * @return the connection timeout, or
+ * <code>DEFAULT_REJECT_CHANGE_VALUE</code> if not present
+ */
+ public int getConnTimeout() {
+ try {
+ String value = properties.getProperty(CONNECTION_TIMEOUT, DEFAULT_REJECT_CHANGE_VALUE);
+ return Integer.parseInt(value);
+ } catch (Exception exc) {
+ LOGGER.error("Exception",exc);
+ return Integer.parseInt(DEFAULT_REJECT_CHANGE_VALUE);
+ }
+ }
+
+ /**
+ * Extracts the request timeout.
+ *
+ * @return the request timeout, or <code>DEFAULT_REQUEST_TIMEOUT</code> if
+ * not present
+ */
+ public int getRequestTimeout() {
+ try {
+ String value = properties.getProperty(REQUEST_TIMEOUT, DEFAULT_REJECT_CHANGE_VALUE);
+ return Integer.parseInt(value);
+ } catch (Exception exc) {
+ LOGGER.error("Exception",exc);
+ return Integer.parseInt(DEFAULT_REJECT_CHANGE_VALUE);
+ }
+ }
+
+ /**
+ * Extracts the db connection name.
+ *
+ * @return the db connection name, or <code>null</code> if not present
+ */
+ public String getDbConnectionName() {
+ return properties.getProperty(CONNECTION_NAME);
+ }
+
+ /**
+ * Extracts the db name.
+ *
+ * @return the db name, or <code>null</code> if not present
+ */
+ public String getDatabaseName() {
+ return properties.getProperty(DATABASE_NAME);
+ }
+
+ /**
+ * Extracts the jdbc driver's name.
+ *
+ * @return the jdbc name, or <code>com.mysql.jdbc.Driver</code> if not present
+ */
+ public String getDriverName() {
+ return properties.getProperty(DRIVER_NAME, "com.mysql.jdbc.Driver");
+ }
+
+ /**
+ * Extracts the db user id.
+ *
+ * @return the db user id, or <code>null</code> if not present
+ */
+ public String getDbUserId() {
+ return properties.getProperty(DATABASE_USER);
+ }
+
+ /**
+ * Extracts the db password.
+ *
+ * @return the db password, or <code>null</code> if not present
+ */
+ public String getDbPasswd() {
+ return properties.getProperty(DATABASE_PSSWD);
+ }
+
+ /**
+ * Extracts the db min limit.
+ *
+ * @return the db min limit
+ * @throws NumberFormatException
+ * if the property is not specified, or cannot be parsed as an
+ * <code>Integer</code>.
+ */
+ public int getDbMinLimit() throws NumberFormatException {
+ String value = properties.getProperty(MIN_LIMIT, "-1");
+ return Integer.parseInt(value);
+ }
+
+ /**
+ * Extracts the db max limit.
+ *
+ * @return the db max limit
+ * @throws NumberFormatException
+ * if the property is not specified, or cannot be parsed as an
+ * <code>Integer</code>.
+ */
+ public int getDbMaxLimit() throws NumberFormatException {
+ String value = properties.getProperty(MAX_LIMIT, "-1");
+ return Integer.parseInt(value);
+ }
+
+ /**
+ * Extracts the db initial limit.
+ *
+ * @return the db initial limit
+ * @throws NumberFormatException
+ * if the property is not specified, or cannot be parsed as an
+ * <code>Integer</code>.
+ */
+ public int getDbInitialLimit() throws NumberFormatException {
+ String value = properties.getProperty(INIT_LIMIT, "-1");
+ return Integer.parseInt(value);
+ }
+
+ /**
+ * Extracts the db url.
+ *
+ * @return the db url, or <code>null</code> if not present
+ */
+ public String getDbUrl() {
+ return properties.getProperty(DATABASE_URL);
+ }
+
+ public boolean containsKey(String propertyname) {
+ return properties.containsKey(propertyname);
+ }
+
+ public String getProperty(String propertyname) {
+ return properties.getProperty(propertyname);
+ }
+}
diff --git a/core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/config/DbConfigPool.java b/core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/config/DbConfigPool.java
new file mode 100644
index 000000000..ea7b3fdc8
--- /dev/null
+++ b/core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/config/DbConfigPool.java
@@ -0,0 +1,63 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * onap
+ * ================================================================================
+ * Copyright (C) 2016 - 2017 ONAP
+ * ================================================================================
+ * Modifications Copyright (C) 2018 IBM.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.dblib.config;
+
+import java.util.ArrayList;
+import java.util.Properties;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @version $Revision: 1.15 $
+ * Change Log
+ * Author Date Comments
+ * ============== ======== ====================================================
+ * Rich Tabedzki
+ */
+public class DbConfigPool {
+ private static final Logger LOGGER = LoggerFactory.getLogger(DbConfigPool.class);
+ private final String type;
+ private static final int timeOut=0;
+ private ArrayList<BaseDBConfiguration> configurations = new ArrayList<>();
+
+ public DbConfigPool(Properties properties) {
+ LOGGER.debug("Initializing DbConfigType");
+ type = properties.getProperty(BaseDBConfiguration.DATABASE_TYPE, "JDBC").toUpperCase();
+ }
+
+ public int getTimeout() {
+ return timeOut;
+ }
+
+ public String getType() {
+ return type;
+ }
+
+ public JDBCConfiguration[] getJDBCbSourceArray() {
+ return configurations.toArray(new JDBCConfiguration[configurations.size()]);
+ }
+
+ public void addConfiguration(BaseDBConfiguration config) {
+ configurations.add(config);
+ }
+}
diff --git a/core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/config/JDBCConfiguration.java b/core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/config/JDBCConfiguration.java
new file mode 100644
index 000000000..fea103569
--- /dev/null
+++ b/core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/config/JDBCConfiguration.java
@@ -0,0 +1,31 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * onap
+ * ================================================================================
+ * Copyright (C) 2016 - 2017 ONAP
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.dblib.config;
+
+import java.util.Properties;
+
+public class JDBCConfiguration extends BaseDBConfiguration {
+
+ public JDBCConfiguration(Properties xmlElem) {
+ super(xmlElem);
+ }
+
+}
diff --git a/core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/config/TerminatingConfiguration.java b/core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/config/TerminatingConfiguration.java
new file mode 100755
index 000000000..1ebd1441f
--- /dev/null
+++ b/core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/config/TerminatingConfiguration.java
@@ -0,0 +1,33 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * onap
+ * ================================================================================
+ * Copyright (C) 2016 - 2017 ONAP
+ * ================================================================================
+ * Modifications Copyright (C) 2018 IBM.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.dblib.config;
+
+import java.util.Properties;
+
+public class TerminatingConfiguration extends BaseDBConfiguration {
+
+ public TerminatingConfiguration() {
+ super(new Properties());
+ }
+
+}
diff --git a/core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/factory/DBConfigFactory.java b/core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/factory/DBConfigFactory.java
new file mode 100644
index 000000000..1aa907837
--- /dev/null
+++ b/core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/factory/DBConfigFactory.java
@@ -0,0 +1,105 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * onap
+ * ================================================================================
+ * Copyright (C) 2016 - 2017 ONAP
+ * ================================================================================
+ * Modifications Copyright (C) 2018 IBM.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.dblib.factory;
+
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.Properties;
+import org.onap.ccsdk.sli.core.dblib.config.BaseDBConfiguration;
+import org.onap.ccsdk.sli.core.dblib.config.DbConfigPool;
+import org.onap.ccsdk.sli.core.dblib.config.JDBCConfiguration;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @version $Revision: 1.1 $
+ * Change Log
+ * Author Date Comments
+ * ============== ======== ====================================================
+ * Rich Tabedzki 01/17/08 Initial version
+ */
+public class DBConfigFactory {
+
+ public static DbConfigPool createConfig(Properties resource) {
+ return getConfigparams(resource);
+ }
+
+ static DbConfigPool getConfigparams(Properties properties) {
+ DbConfigPool xmlConfig = new DbConfigPool(properties);
+ ArrayList<Properties> propertySets = new ArrayList<>();
+
+ if ("JDBC".equalsIgnoreCase(xmlConfig.getType())) {
+ String hosts = properties.getProperty(BaseDBConfiguration.DATABASE_HOSTS);
+ if (hosts == null || hosts.isEmpty()) {
+ propertySets.add(properties);
+ } else {
+ setPropertyWhenHostsNonEmpty(hosts, properties, propertySets);
+ }
+ } else {
+ propertySets.add(properties);
+ }
+ try {
+ Iterator<Properties> it = propertySets.iterator();
+ while (it.hasNext()) {
+ BaseDBConfiguration config = parse(it.next());
+ xmlConfig.addConfiguration(config);
+ }
+ } catch (Exception e) {
+ LoggerFactory.getLogger(DBConfigFactory.class).warn("", e);
+ }
+
+ return xmlConfig;
+ }
+
+ private static void setPropertyWhenHostsNonEmpty(String hosts, Properties properties, ArrayList<Properties>
+ propertySets) {
+ String[] newhost = hosts.split(",");
+ for (String aNewhost : newhost) {
+ Properties localSet = new Properties();
+ localSet.putAll(properties);
+ String url = localSet.getProperty(BaseDBConfiguration.DATABASE_URL);
+ if (url.contains("DBHOST")) {
+ url = url.replace("DBHOST", aNewhost);
+ }
+ if (url.contains("dbhost")) {
+ url = url.replace("dbhost", aNewhost);
+ }
+ localSet.setProperty(BaseDBConfiguration.DATABASE_URL, url);
+ localSet.setProperty(BaseDBConfiguration.CONNECTION_NAME, aNewhost);
+ propertySets.add(localSet);
+ }
+ }
+
+ public static BaseDBConfiguration parse(Properties props) throws Exception {
+
+ String type = props.getProperty(BaseDBConfiguration.DATABASE_TYPE);
+
+ BaseDBConfiguration config = null;
+
+ if ("JDBC".equalsIgnoreCase(type)) {
+ config = new JDBCConfiguration(props);
+ }
+
+ return config;
+ }
+}
diff --git a/core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/jdbc/JdbcDBCachedDataSource.java b/core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/jdbc/JdbcDBCachedDataSource.java
new file mode 100755
index 000000000..a53d18639
--- /dev/null
+++ b/core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/jdbc/JdbcDBCachedDataSource.java
@@ -0,0 +1,201 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * onap
+ * ================================================================================
+ * Copyright (C) 2016 - 2017 ONAP
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.dblib.jdbc;
+
+import java.sql.SQLFeatureNotSupportedException;
+import org.apache.tomcat.jdbc.pool.DataSource;
+import org.apache.tomcat.jdbc.pool.PoolProperties;
+import org.onap.ccsdk.sli.core.dblib.CachedDataSource;
+import org.onap.ccsdk.sli.core.dblib.DBConfigException;
+import org.onap.ccsdk.sli.core.dblib.config.BaseDBConfiguration;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+public class JdbcDBCachedDataSource extends CachedDataSource {
+
+ private String dbDriver;
+ private String dbUserId;
+ private String dbPasswd;
+ private String dbUrl;
+
+ private int minLimit;
+ private int maxLimit;
+ private int initialLimit;
+
+ private static final String AS_CONF_ERROR = "AS_CONF_ERROR: ";
+ private static final int MIN_LIMIT = 5;
+ private static final int MAX_LIMIT = 10;
+ private static final int INITIAL_LIMIT = 10;
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(JdbcDBCachedDataSource.class);
+
+ /**
+ * @param jdbcElem
+ */
+ public JdbcDBCachedDataSource(BaseDBConfiguration jdbcElem) {
+ super(jdbcElem);
+ }
+
+ @Override
+ protected DataSource configure(BaseDBConfiguration xmlElem) throws DBConfigException {
+ BaseDBConfiguration jdbcConfig = xmlElem;
+ if (jdbcConfig.getConnTimeout() > 0) {
+ this.connReqTimeout = jdbcConfig.getConnTimeout();
+ }
+ if (jdbcConfig.getRequestTimeout() > 0) {
+ this.dataReqTimeout = jdbcConfig.getRequestTimeout();
+ }
+
+ // set connection pool name
+ String dbConnectionName = jdbcConfig.getDbConnectionName();
+ super.setDbConnectionName(dbConnectionName);
+ // Configure the JDBC connection
+ dbUserId = jdbcConfig.getDbUserId();
+ if (dbUserId == null) {
+ String errorMsg = "Invalid XML contents: JDBCConnection missing dbUserId attribute";
+ LOGGER.error(AS_CONF_ERROR + errorMsg);
+ throw new DBConfigException(errorMsg);
+ }
+
+ dbPasswd = jdbcConfig.getDbPasswd();
+ if (dbPasswd == null) {
+ String errorMsg = "Invalid XML contents: JDBCConnection missing dbPasswd attribute";
+ LOGGER.error(AS_CONF_ERROR + errorMsg);
+ throw new DBConfigException(errorMsg);
+ }
+
+ dbDriver = jdbcConfig.getDriverName();
+ if (dbDriver == null) {
+ String errorMsg = "Invalid XML contents: JDBCConnection missing dbDriver attribute";
+ LOGGER.error(AS_CONF_ERROR + errorMsg);
+ throw new DBConfigException(errorMsg);
+ }
+
+ minLimit = jdbcConfig.getDbMinLimit();
+ if (minLimit == -1)
+ {
+ String errorMsg = "Invalid XML contents: JDBC Connection missing minLimit attribute";
+ LOGGER.error(AS_CONF_ERROR + errorMsg);
+ minLimit = MIN_LIMIT;
+ }
+ maxLimit = jdbcConfig.getDbMaxLimit();
+ if (maxLimit == -1)
+ {
+ String errorMsg = "Invalid XML contents: JDBC Connection missing maxLimit attribute";
+ LOGGER.error(AS_CONF_ERROR + errorMsg);
+ maxLimit = MAX_LIMIT;
+ }
+ initialLimit = jdbcConfig.getDbInitialLimit();
+ if (initialLimit == -1)
+ {
+ String errorMsg = "Invalid XML contents: JDBC Connection missing initialLimit attribute";
+ LOGGER.error(AS_CONF_ERROR + errorMsg);
+ initialLimit = INITIAL_LIMIT;
+ }
+
+ dbUrl = jdbcConfig.getDbUrl();
+ if (dbUrl == null) {
+ String errorMsg = "Invalid XML contents: JDBCConnection missing dbUrl attribute";
+ LOGGER.error(AS_CONF_ERROR + errorMsg);
+ throw new DBConfigException(errorMsg);
+ }
+
+ try {
+
+ PoolProperties p = new PoolProperties();
+ p.setDriverClassName(dbDriver);
+ p.setUrl(dbUrl);
+ p.setUsername(dbUserId);
+ p.setPassword(dbPasswd);
+ p.setJmxEnabled(true);
+ p.setTestWhileIdle(false);
+ p.setTestOnBorrow(true);
+ p.setValidationQuery("SELECT 1");
+ p.setTestOnReturn(false);
+ p.setValidationInterval(30000);
+ p.setTimeBetweenEvictionRunsMillis(30000);
+ p.setInitialSize(initialLimit);
+ p.setMaxActive(maxLimit);
+ p.setMaxIdle(maxLimit);
+ p.setMaxWait(10000);
+ p.setRemoveAbandonedTimeout(60);
+ p.setMinEvictableIdleTimeMillis(30000);
+ p.setMinIdle(minLimit);
+ p.setLogAbandoned(true);
+ p.setRemoveAbandoned(true);
+ p.setJdbcInterceptors("org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;"
+ + "org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer");
+
+ final DataSource dataSource = new DataSource(p);
+
+ synchronized (this) {
+ initialized = true;
+ }
+ LOGGER.info(String.format("JdbcDBCachedDataSource <%s> configured successfully. Using URL: %s",
+ dbConnectionName, dbUrl));
+ return dataSource;
+ } catch (Exception exc) {
+ initialized = false;
+ LOGGER.error(String.format("AS_CONF_ERROR: Failed to initialize MySQLCachedDataSource <%s>. Reason: %s",
+ dbConnectionName, exc.getMessage()));
+ return null;
+ }
+ }
+
+ public final String getDbUrl() {
+ return dbUrl;
+ }
+
+ public final String getDbUserId() {
+ return dbUserId;
+ }
+
+ public final String getDbPasswd() {
+ return dbPasswd;
+ }
+
+ public static JdbcDBCachedDataSource createInstance(BaseDBConfiguration config) /*throws Exception*/ {
+ return new JdbcDBCachedDataSource(config);
+ }
+
+ public String toString() {
+ return getDbConnectionName();
+ }
+
+ public java.util.logging.Logger getParentLogger()
+ throws SQLFeatureNotSupportedException {
+ return null;
+ }
+
+ @Override
+ public void cleanUp() {
+ DataSource dataSource = (DataSource) ds;
+ dataSource.getPool().purge();
+ dataSource.close(true);
+ super.cleanUp();
+ }
+
+ @Override
+ protected int getAvailableConnections() {
+ return org.apache.tomcat.jdbc.pool.DataSource.class.cast(ds).getSize();
+ }
+}
diff --git a/core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/pm/PollingWorker.java b/core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/pm/PollingWorker.java
new file mode 100644
index 000000000..f66250676
--- /dev/null
+++ b/core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/pm/PollingWorker.java
@@ -0,0 +1,259 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * onap
+ * ================================================================================
+ * Copyright (C) 2016 - 2017 ONAP
+ * ================================================================================
+ * Modifications Copyright (C) 2018 IBM.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.dblib.pm;
+
+import java.util.Iterator;
+import java.util.Properties;
+import java.util.Set;
+import java.util.Timer;
+import java.util.TimerTask;
+import java.util.TreeSet;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.atomic.AtomicLong;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @version $Revision: 1.15 $
+ * Change Log
+ * Author Date Comments
+ * ============== ======== ====================================================
+ * Rich Tabedzki
+ */
+public class PollingWorker implements Runnable {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(PollingWorker.class);
+
+ private static PollingWorker self = null;
+
+ private LinkedBlockingQueue tasks = new LinkedBlockingQueue(100);
+ private long interval = 1000L;
+ private Thread worker = null;
+ private AtomicLong[] counters = null;
+ private int[] bucketUnit = null;
+ private static boolean enabled = false;
+ private Timer timer = null;
+
+ private PollingWorker(Properties ctxprops) {
+ if (ctxprops == null || ctxprops.getProperty("org.onap.ccsdk.dblib.pm") == null) {
+ enabled = false;
+ } else {
+ if ("true".equalsIgnoreCase((String) ctxprops.getProperty("org.onap.ccsdk.dblib.pm"))) {
+ enabled = true;
+ } else {
+ enabled = false;
+ }
+ }
+
+ interval = Long.parseLong((ctxprops == null || ctxprops.getProperty("org.onap.ccsdk.dblib.pm.interval") == null)
+ ? "60" : (String) ctxprops.getProperty("org.onap.ccsdk.dblib.pm.interval"));
+ // '0' bucket is to count exceptions
+ String[] sampling = ((ctxprops == null || ctxprops.getProperty("org.onap.ccsdk.dblib.pm.sampling") == null)
+ ? "0,2,5,10,20,50,100" : (String) ctxprops.getProperty("org.onap.ccsdk.dblib.pm.sampling")).split(",");
+
+ if (enabled) {
+ bucketUnit = new int[sampling.length];
+ for (int i = 0, max = bucketUnit.length; i < max; i++) {
+ bucketUnit[i] = Integer.parseInt(sampling[i].trim());
+ }
+ counters = new AtomicLong[bucketUnit.length + 1];
+ for (int i = 0, max = counters.length; i < max; i++) {
+ counters[i] = new AtomicLong();
+ }
+ worker = new Thread(this);
+ worker.setDaemon(true);
+ worker.start();
+ timer = new Timer(true);
+ timer.schedule(new MyTimerTask(), interval * 1000L, interval * 1000L);
+ }
+ }
+
+ public static void post(long starttime) {
+ PollingWorker temp = self;
+ if (temp != null && enabled) {
+ temp.register(new TestSample(starttime));
+ }
+ }
+
+ public static void createInistance(Properties props) {
+ self = new PollingWorker(props);
+ }
+
+ private void register(TestSample object) {
+ try {
+ tasks.add(object);
+ } catch (Throwable exc) {
+ // if cannot add an object to the queue, do nothing
+ }
+ }
+
+ private void deRegister(TestSample object) {
+ tasks.remove(object);
+ }
+
+ @Override
+ public void run() {
+ for (;;) {
+ Set data = new TreeSet();
+ tasks.drainTo(data);
+ for (Iterator it = data.iterator(); it.hasNext();) {
+ Object next = it.next();
+ if (next instanceof TestSample) {
+ consume((TestSample) next);
+ } else {
+ System.out.println(next.getClass().getName());
+ LOGGER.error(next.getClass().getName());
+ }
+ }
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+
+ }
+ }
+
+ }
+
+ public void clearReqister() {
+ AtomicLong[] tmp = new AtomicLong[counters.length];
+ for (int i = 0, max = tmp.length; i < max; i++) {
+ tmp[i] = new AtomicLong();
+ }
+ AtomicLong[] tmp2 = counters;
+ synchronized (tmp2) {
+ counters = tmp;
+ }
+ StringBuffer sb = new StringBuffer("CPM: ");
+ for (int i = 0, max = tmp2.length; i < max; i++) {
+ if (i == 0 && bucketUnit[0] == 0) {
+ sb.append("[Exc]=");
+ } else {
+ sb.append("[");
+ if (i == bucketUnit.length) {
+ sb.append("Other]=");
+ } else {
+ sb.append(bucketUnit[i]).append(" ms]=");
+ }
+ }
+ sb.append(tmp2[i].get()).append("\t");
+ }
+ LOGGER.info(sb.toString());
+ }
+
+ class MyTimerTask extends TimerTask {
+
+ @Override
+ public void run() {
+
+ clearReqister();
+ }
+
+ }
+
+ private void consume(TestSample probe) {
+ AtomicLong[] tmp = counters;
+ synchronized (tmp) {
+ counters[getBucket(probe.getDuration())].incrementAndGet();
+ }
+ }
+
+ /*
+ * This method is used to find the offset of the bucket in counters.
+ * 'counters' array is 1 size longer than bucketUnit, hence by default it
+ * returns 'bucketUnit.length'
+ */
+ private int getBucket(long difftime) {
+ for (int i = 0; i < bucketUnit.length; i++) {
+ if (difftime < bucketUnit[i]) {
+ return i;
+ }
+ }
+ return bucketUnit.length;
+ }
+
+ private static boolean isEnabled() {
+ return enabled;
+ }
+
+ /**
+ * @author Rich Tabedzki
+ * A helper class to pass measured parameter to the counter.
+ */
+ static class TestSample implements Comparable {
+ private long starttime;
+ private long endtime;
+
+ public TestSample(long starttime) {
+ this.endtime = System.currentTimeMillis();
+ this.starttime = starttime;
+ }
+
+ public long getDuration() {
+ return endtime - starttime;
+ }
+
+ @Override
+ public int compareTo(Object o) {
+ if (o instanceof TestSample) {
+ TestSample x = (TestSample) o;
+ if (starttime < x.starttime)
+ return 1;
+ if (endtime < x.endtime)
+ return 1;
+ if (starttime > x.starttime)
+ return -1;
+ if (endtime > x.endtime)
+ return -1;
+ return 0;
+ }
+ return 1;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + (int) (endtime ^ (endtime >>> 32));
+ result = prime * result + (int) (starttime ^ (starttime >>> 32));
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ TestSample other = (TestSample) obj;
+ if (endtime != other.endtime)
+ return false;
+ if (starttime != other.starttime)
+ return false;
+ return true;
+ }
+ }
+}
diff --git a/core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/pm/SQLExecutionMonitor.java b/core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/pm/SQLExecutionMonitor.java
new file mode 100644
index 000000000..b6664f3c3
--- /dev/null
+++ b/core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/pm/SQLExecutionMonitor.java
@@ -0,0 +1,222 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * onap
+ * ================================================================================
+ * Copyright (C) 2016 - 2017 ONAP
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.dblib.pm;
+
+import java.io.Serializable;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Objects;
+import java.util.Observable;
+import java.util.Observer;
+import java.util.SortedSet;
+import java.util.Timer;
+import java.util.TimerTask;
+import java.util.TreeSet;
+import java.util.concurrent.atomic.AtomicLong;
+import org.onap.ccsdk.sli.core.dblib.DBResourceObserver;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class SQLExecutionMonitor extends Observable {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(SQLExecutionMonitor.class);
+
+ static final long MILISECOND = 1000000L;
+ static final long SECOND = 1000L * MILISECOND;
+
+ private final Timer timer;
+ // collection
+ private final SortedSet<TestObject> innerSet;
+ private SQLExecutionMonitorObserver parent = null;
+ private final AtomicLong completionCounter;
+ private boolean activeState = false;
+ private final long interval;
+ private final long initialDelay;
+ private final long EXPECTED_TIME_TO_COMPLETE;
+ private final long UNPROCESSED_FAILOVER_THRESHOLD;
+
+ private final class MonitoringTask extends TimerTask {
+
+ @Override
+ public void run() {
+ try {
+ TestObject testObj = new TestObject();
+ testObj.setStartTime(testObj.getStartTime() - EXPECTED_TIME_TO_COMPLETE);
+
+ // take a snapshot of the current task list
+ TestObject[] array = innerSet.toArray(new TestObject[0]);
+ SortedSet<TestObject> copyCurrent = new TreeSet<>(Arrays.asList(array));
+ // get the list of the tasks that are older than the specified
+ // interval.
+ SortedSet<TestObject> unprocessed = copyCurrent.headSet(testObj);
+
+ long successfulCount = completionCounter.get();
+ int unprocessedCount = unprocessed.size();
+
+ if (!unprocessed.isEmpty() && unprocessedCount > UNPROCESSED_FAILOVER_THRESHOLD
+ && successfulCount == 0) {
+ // switch the Connection Pool to passive
+ setChanged();
+ notifyObservers("Open JDBC requests=" + unprocessedCount + " in " + SQLExecutionMonitor.this.parent
+ .getDbConnectionName());
+ }
+ } catch (Exception exc) {
+ LOGGER.error("", exc);
+ } finally {
+ completionCounter.set(0L);
+ }
+ }
+ }
+
+ public static class TestObject implements Comparable<TestObject>, Serializable {
+
+ private static final long serialVersionUID = 1L;
+ private long startTime;
+ private long randId;
+
+ public TestObject() {
+ startTime = System.nanoTime();
+ }
+
+ public long getStartTime() {
+ return startTime;
+ }
+
+ public void setStartTime(long newTime) {
+ startTime = newTime;
+ }
+
+ @Override
+ public int compareTo(TestObject o) {
+ if (this == o) {
+ return 0;
+ }
+ if (this.startTime > o.getStartTime()) {
+ return 1;
+ }
+ if (this.startTime < o.getStartTime()) {
+ return -1;
+ }
+
+ if (this.hashCode() > o.hashCode()) {
+ return 1;
+ }
+ if (this.hashCode() < o.hashCode()) {
+ return -1;
+ }
+
+ return 0;
+ }
+
+ public String toString() {
+ return Long.toString(startTime) + "#" + this.hashCode();
+ }
+
+ public int hashCode() {
+ return Objects.hash(startTime, randId);
+ }
+
+ public boolean equals(Object obj) {
+ return this == obj || (obj instanceof TestObject && startTime == ((TestObject) obj).getStartTime()
+ && hashCode() == obj.hashCode());
+ }
+ }
+
+ public SQLExecutionMonitor(SQLExecutionMonitorObserver parent) {
+ this.parent = parent;
+ completionCounter = new AtomicLong(0L);
+ interval = parent.getInterval();
+ initialDelay = parent.getInitialDelay();
+ this.UNPROCESSED_FAILOVER_THRESHOLD = parent.getUnprocessedFailoverThreshold();
+ this.EXPECTED_TIME_TO_COMPLETE = parent.getExpectedCompletionTime() * MILISECOND;
+
+ innerSet = Collections.synchronizedSortedSet(new TreeSet<TestObject>());
+ timer = new Timer();
+ }
+
+ public void cleanup() {
+ timer.cancel();
+ }
+
+ // registerRequest
+ public TestObject registerRequest() {
+ if (activeState) {
+ TestObject test = new TestObject();
+ if (innerSet.add(test)) {
+ return test;
+ }
+ }
+ return null;
+ }
+
+ // deregisterSuccessfulRequest
+ public boolean deregisterRequest(TestObject test) {
+ if (test == null) {
+ return false;
+ }
+ // remove from the collection
+ if (innerSet.remove(test) && activeState) {
+ completionCounter.incrementAndGet();
+ return true;
+ }
+ return false;
+ }
+
+ public void terminate() {
+ timer.cancel();
+ }
+
+ /**
+ * @return the parent
+ */
+ public final Object getParent() {
+ return parent;
+ }
+
+ @Override
+ public void addObserver(Observer observer) {
+ if (observer instanceof DBResourceObserver) {
+ DBResourceObserver dbObserver = (DBResourceObserver) observer;
+ if (dbObserver.isMonitorDbResponse() && countObservers() == 0) {
+ TimerTask remindTask = new MonitoringTask();
+ timer.schedule(remindTask, initialDelay, interval);
+ activeState = true;
+ }
+ }
+ super.addObserver(observer);
+ }
+
+ @Override
+ public void deleteObserver(Observer observer) {
+ super.deleteObserver(observer);
+ if (observer instanceof DBResourceObserver) {
+ DBResourceObserver dbObserver = (DBResourceObserver) observer;
+ if (dbObserver.isMonitorDbResponse() && countObservers() == 0) {
+ timer.cancel();
+ activeState = false;
+ }
+ }
+ }
+
+ public final int getProcessedConnectionsCount() {
+ return innerSet.size();
+ }
+}
diff --git a/core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/pm/SQLExecutionMonitorObserver.java b/core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/pm/SQLExecutionMonitorObserver.java
new file mode 100644
index 000000000..2fdde1ee4
--- /dev/null
+++ b/core/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/pm/SQLExecutionMonitorObserver.java
@@ -0,0 +1,37 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * onap
+ * ================================================================================
+ * Copyright (C) 2016 - 2017 ONAP
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.dblib.pm;
+
+public interface SQLExecutionMonitorObserver {
+ String getDbConnectionName();
+
+ long getInterval();
+ void setInterval(long value);
+
+ long getInitialDelay();
+ void setInitialDelay(long value);
+
+ long getExpectedCompletionTime();
+ void setExpectedCompletionTime(long value);
+
+ long getUnprocessedFailoverThreshold();
+ void setUnprocessedFailoverThreshold(long value);
+}
diff --git a/core/dblib/provider/src/main/resources/OSGI-INF/blueprint/dblib-blueprint.xml b/core/dblib/provider/src/main/resources/OSGI-INF/blueprint/dblib-blueprint.xml
new file mode 100755
index 000000000..f1d5166db
--- /dev/null
+++ b/core/dblib/provider/src/main/resources/OSGI-INF/blueprint/dblib-blueprint.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+ xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0"
+ odl:use-default-for-reference-types="true">
+
+ <bean id="provider" class="org.onap.ccsdk.sli.core.dblib.DBLIBResourceProvider" />
+
+ <bean id="dbResourceManager" class="org.onap.ccsdk.sli.core.dblib.DBResourceManager">
+ <argument ref="provider" />
+ </bean>
+ <service ref="dbResourceManager">
+ <interfaces>
+ <value>javax.sql.DataSource</value>
+ <value>org.onap.ccsdk.sli.core.dblib.DbLibService</value>
+ </interfaces>
+ </service>
+
+</blueprint> \ No newline at end of file
diff --git a/core/dblib/provider/src/main/resources/dblib.properties b/core/dblib/provider/src/main/resources/dblib.properties
new file mode 100755
index 000000000..e0399cc31
--- /dev/null
+++ b/core/dblib/provider/src/main/resources/dblib.properties
@@ -0,0 +1,14 @@
+org.onap.ccsdk.sli.dbtype=jdbc
+org.onap.ccsdk.sli.jdbc.hosts=sdnctldb01,sdnctldb02
+org.onap.ccsdk.sli.jdbc.url=jdbc:derby:memory:sdnctl;create=true
+org.onap.ccsdk.sli.jdbc.driver=org.apache.derby.jdbc.EmbeddedDriver
+org.onap.ccsdk.sli.jdbc.database=sdnctl
+org.onap.ccsdk.sli.jdbc.user=test
+org.onap.ccsdk.sli.jdbc.password=test
+org.onap.ccsdk.sli.jdbc.connection.name=sdnctldb01
+
+org.onap.ccsdk.sli.jdbc.connection.timeout=50
+org.onap.ccsdk.sli.jdbc.request.timeout=100
+org.onap.ccsdk.sli.jdbc.limit.init=10
+org.onap.ccsdk.sli.jdbc.limit.min=10
+org.onap.ccsdk.sli.jdbc.limit.max=20
diff --git a/core/dblib/provider/src/main/resources/org/opendaylight/blueprint/dblib-blueprint.xml b/core/dblib/provider/src/main/resources/org/opendaylight/blueprint/dblib-blueprint.xml
new file mode 100755
index 000000000..d9bb99c07
--- /dev/null
+++ b/core/dblib/provider/src/main/resources/org/opendaylight/blueprint/dblib-blueprint.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+ xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0"
+ odl:use-default-for-reference-types="true">
+
+ <bean id="provider" class="org.onap.ccsdk.sli.core.dblib.DBLIBResourceProvider" />
+
+ <bean id="dbResourceManager" class="org.onap.ccsdk.sli.core.dblib.DBResourceManager">
+ <argument ref="provider" />
+ </bean>
+ <service ref="dbResourceManager">
+ <interfaces>
+ <value>javax.sql.DataSource</value>
+ <value>org.onap.ccsdk.sli.core.dblib.DbLibService</value>
+ </interfaces>
+ </service>
+
+ <command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.0.0">
+ <command name="dblib/encode">
+ <action class="org.onap.ccsdk.sli.core.dblib.EncShellCommand"/>
+ </command>
+ </command-bundle>
+
+</blueprint> \ No newline at end of file
diff --git a/core/dblib/provider/src/test/java/org/onap/ccsdk/sli/core/dblib/CachedDataSourceTest.java b/core/dblib/provider/src/test/java/org/onap/ccsdk/sli/core/dblib/CachedDataSourceTest.java
new file mode 100644
index 000000000..45268107e
--- /dev/null
+++ b/core/dblib/provider/src/test/java/org/onap/ccsdk/sli/core/dblib/CachedDataSourceTest.java
@@ -0,0 +1,121 @@
+package org.onap.ccsdk.sli.core.dblib;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.sql.SQLException;
+import java.sql.SQLFeatureNotSupportedException;
+import java.util.Properties;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.onap.ccsdk.sli.core.dblib.config.BaseDBConfiguration;
+import org.onap.ccsdk.sli.core.dblib.config.JDBCConfiguration;
+import org.onap.ccsdk.sli.core.dblib.jdbc.JdbcDBCachedDataSource;
+import org.slf4j.LoggerFactory;
+
+public class CachedDataSourceTest {
+
+ private static final Properties props = new Properties();
+ private static BaseDBConfiguration config;
+ private static CachedDataSource ds;
+
+ @BeforeClass
+ public static void setUpBeforeClass() throws Exception {
+ props.setProperty("org.onap.ccsdk.sli.dbtype", "jdbc");
+ props.setProperty("org.onap.ccsdk.sli.jdbc.hosts", "localhost");
+ props.setProperty("org.onap.ccsdk.sli.jdbc.url", "jdbc:mysql://dbhost:3306/test");
+ props.setProperty("org.onap.ccsdk.sli.jdbc.driver", "org.mariadb.jdbc.Driver");
+ props.setProperty("org.onap.ccsdk.sli.jdbc.database", "test");
+ props.setProperty("org.onap.ccsdk.sli.jdbc.user", "dbuser");
+ props.setProperty("org.onap.ccsdk.sli.jdbc.password", "passw0rd");
+ props.setProperty("org.onap.ccsdk.sli.jdbc.connection.name", "testdb01");
+ props.setProperty("org.onap.ccsdk.sli.jdbc.connection.timeout", "50");
+ props.setProperty("org.onap.ccsdk.sli.jdbc.request.timeout", "100");
+ props.setProperty("org.onap.ccsdk.sli.jdbc.limit.init", "10");
+ props.setProperty("org.onap.ccsdk.sli.jdbc.limit.min", "10");
+ props.setProperty("org.onap.ccsdk.sli.jdbc.limit.max", "20");
+ props.setProperty("org.onap.dblib.connection.recovery", "false");
+
+ config = new JDBCConfiguration(props);
+ ds = new JdbcDBCachedDataSource(config);
+ }
+
+ @Test
+ public void testCachedDataSource() {
+ assertNotNull(ds);
+ }
+
+ @Test
+ public void testConfigure() {
+
+ assertNotNull(ds.configure(config));
+ }
+
+ @Test
+ public void testSetInitialDelay() {
+ ds.setInitialDelay(1000L);
+ assertTrue(ds.getInitialDelay() == 1000L);
+ }
+
+ @Test
+ public void testSetInterval() {
+ ds.setInterval(1000L);
+ assertTrue(ds.getInterval() == 1000L);
+ }
+
+ @Test
+ public void testSetExpectedCompletionTime() {
+ ds.setExpectedCompletionTime(100L);
+ assertTrue(ds.getExpectedCompletionTime() == 100L);
+ }
+
+ @Test
+ public void testSetUnprocessedFailoverThreshold() {
+ ds.setUnprocessedFailoverThreshold(100L);
+ assertTrue(ds.getUnprocessedFailoverThreshold() == 100L);
+ }
+
+ @Test
+ public void testGetParentLogger() {
+ try {
+ assertNull(ds.getParentLogger());
+ } catch (SQLFeatureNotSupportedException e) {
+ LoggerFactory.getLogger(CachedDataSourceTest.class).warn("Test Failure", e);
+ }
+ }
+
+ @Test
+ public void testGettersForJdbcDBCachedDataSource() {
+
+ assertEquals("jdbc:mysql://dbhost:3306/test", ((JdbcDBCachedDataSource) ds).getDbUrl());
+ assertEquals("dbuser", ((JdbcDBCachedDataSource) ds).getDbUserId());
+ assertEquals("passw0rd", ((JdbcDBCachedDataSource) ds).getDbPasswd());
+ assertEquals("testdb01", ((JdbcDBCachedDataSource) ds).toString());
+ }
+
+ @Test
+ public void testIsInitialised() {
+ assertTrue(ds.isInitialized());
+ }
+
+ @Test
+ public void testIsWrapperFor() throws SQLException {
+ assertFalse(ds.isWrapperFor(CachedDataSource.class));
+ }
+
+ @Test
+ public void testGetSetNextErrorReportTime() throws SQLException {
+ ds.setNextErrorReportTime(1L);
+ assertEquals(1L, ds.getNextErrorReportTime());
+ }
+
+ @Test
+ public void testGetSetGlobalHostName() throws SQLException {
+ ds.setGlobalHostName("hostName");
+ assertEquals("hostName", ds.getGlobalHostName());
+ }
+} \ No newline at end of file
diff --git a/core/dblib/provider/src/test/java/org/onap/ccsdk/sli/core/dblib/DBConfigExceptionTest.java b/core/dblib/provider/src/test/java/org/onap/ccsdk/sli/core/dblib/DBConfigExceptionTest.java
new file mode 100644
index 000000000..2a5b65c7a
--- /dev/null
+++ b/core/dblib/provider/src/test/java/org/onap/ccsdk/sli/core/dblib/DBConfigExceptionTest.java
@@ -0,0 +1,19 @@
+package org.onap.ccsdk.sli.core.dblib;
+
+import static org.junit.Assert.assertNotNull;
+
+import org.junit.Test;
+
+public class DBConfigExceptionTest {
+
+ @Test
+ public void testDBConfigExceptionException() {
+ assertNotNull(new DBConfigException("JUnit Test"));
+ }
+
+ @Test
+ public void testDBConfigExceptionString() {
+ assertNotNull(new DBConfigException(new Exception("JUnit Test")));
+ }
+
+}
diff --git a/core/dblib/provider/src/test/java/org/onap/ccsdk/sli/core/dblib/DblibConfigurationExceptionTest.java b/core/dblib/provider/src/test/java/org/onap/ccsdk/sli/core/dblib/DblibConfigurationExceptionTest.java
new file mode 100644
index 000000000..7becd1ae4
--- /dev/null
+++ b/core/dblib/provider/src/test/java/org/onap/ccsdk/sli/core/dblib/DblibConfigurationExceptionTest.java
@@ -0,0 +1,24 @@
+package org.onap.ccsdk.sli.core.dblib;
+
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+
+public class DblibConfigurationExceptionTest {
+
+ @Test
+ public void testDblibConfigurationException() {
+ assertNotNull(new DblibConfigurationException());
+ }
+
+ @Test
+ public void testDblibConfigurationExceptionString() {
+ assertNotNull(new DblibConfigurationException("JUnit Test"));
+ }
+
+ @Test
+ public void testDblibConfigurationExceptionStringThrowable() {
+ assertNotNull(new DblibConfigurationException("JUnit Test", new Exception("JUnit Test")));
+ }
+
+}
diff --git a/core/dblib/provider/src/test/java/org/onap/ccsdk/sli/core/dblib/NoAvailableConnectionsExceptionTest.java b/core/dblib/provider/src/test/java/org/onap/ccsdk/sli/core/dblib/NoAvailableConnectionsExceptionTest.java
new file mode 100644
index 000000000..2fdacb922
--- /dev/null
+++ b/core/dblib/provider/src/test/java/org/onap/ccsdk/sli/core/dblib/NoAvailableConnectionsExceptionTest.java
@@ -0,0 +1,16 @@
+package org.onap.ccsdk.sli.core.dblib;
+
+import static org.junit.Assert.*;
+
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
+public class NoAvailableConnectionsExceptionTest {
+
+ @Test
+ public void testNoAvailableConnectionsException() {
+ assertNotNull(new NoAvailableConnectionsException(new Exception("test")));
+ }
+
+}
diff --git a/core/dblib/provider/src/test/java/org/onap/ccsdk/sli/core/dblib/TerminatingCachedDataSourceTest.java b/core/dblib/provider/src/test/java/org/onap/ccsdk/sli/core/dblib/TerminatingCachedDataSourceTest.java
new file mode 100644
index 000000000..160a3d4ae
--- /dev/null
+++ b/core/dblib/provider/src/test/java/org/onap/ccsdk/sli/core/dblib/TerminatingCachedDataSourceTest.java
@@ -0,0 +1,94 @@
+package org.onap.ccsdk.sli.core.dblib;
+
+import static org.junit.Assert.*;
+
+import java.sql.SQLFeatureNotSupportedException;
+import java.util.Properties;
+
+import org.junit.Test;
+import org.onap.ccsdk.sli.core.dblib.config.BaseDBConfiguration;
+import org.onap.ccsdk.sli.core.dblib.config.JDBCConfiguration;
+import org.slf4j.LoggerFactory;
+
+public class TerminatingCachedDataSourceTest {
+
+ @Test
+ public void testTerminatingCachedDataSource() {
+ Properties props = new Properties();
+ BaseDBConfiguration config = new JDBCConfiguration(props);
+ CachedDataSource ds = new TerminatingCachedDataSource(config);
+ assertNotNull(ds);
+ }
+
+ @Test
+ public void testConfigure() {
+ Properties props = new Properties();
+ props.setProperty("org.onap.ccsdk.sli.dbtype", "jdbc");
+ props.setProperty("org.onap.ccsdk.sli.jdbc.hosts", "localhost");
+ props.setProperty("org.onap.ccsdk.sli.jdbc.url", "jdbc:mysql://dbhost:3306/test");
+ props.setProperty("org.onap.ccsdk.sli.jdbc.driver", "org.mariadb.jdbc.Driver");
+ props.setProperty("org.onap.ccsdk.sli.jdbc.database", "test");
+ props.setProperty("org.onap.ccsdk.sli.jdbc.user", "dbuser");
+ props.setProperty("org.onap.ccsdk.sli.jdbc.password", "passw0rd");
+ props.setProperty("org.onap.ccsdk.sli.jdbc.connection.name", "testdb01");
+ props.setProperty("org.onap.ccsdk.sli.jdbc.connection.timeout", "50");
+ props.setProperty("org.onap.ccsdk.sli.jdbc.request.timeout", "100");
+ props.setProperty("org.onap.ccsdk.sli.jdbc.limit.init", "10");
+ props.setProperty("org.onap.ccsdk.sli.jdbc.limit.min", "10");
+ props.setProperty("org.onap.ccsdk.sli.jdbc.limit.max", "20");
+ props.setProperty("org.onap.dblib.connection.recovery", "false");
+ BaseDBConfiguration config = new JDBCConfiguration(props);
+
+ CachedDataSource ds = new TerminatingCachedDataSource(config);
+ assertNull(ds.configure(config));
+ }
+
+ @Test
+ public void testSetInitialDelay() {
+ Properties props = new Properties();
+ BaseDBConfiguration config = new JDBCConfiguration(props);
+ CachedDataSource ds = new TerminatingCachedDataSource(config);
+ ds.setInitialDelay(1000L);
+ assertTrue(ds.getInitialDelay() == 1000L);
+ }
+
+ @Test
+ public void testSetInterval() {
+ Properties props = new Properties();
+ BaseDBConfiguration config = new JDBCConfiguration(props);
+ CachedDataSource ds = new TerminatingCachedDataSource(config);
+ ds.setInterval(1000L);
+ assertTrue(ds.getInterval() == 1000L);
+ }
+
+ @Test
+ public void testSetExpectedCompletionTime() {
+ Properties props = new Properties();
+ BaseDBConfiguration config = new JDBCConfiguration(props);
+ CachedDataSource ds = new TerminatingCachedDataSource(config);
+ ds.setExpectedCompletionTime(100L);
+ assertTrue(ds.getExpectedCompletionTime() == 100L);
+ }
+
+ @Test
+ public void testSetUnprocessedFailoverThreshold() {
+ Properties props = new Properties();
+ BaseDBConfiguration config = new JDBCConfiguration(props);
+ CachedDataSource ds = new TerminatingCachedDataSource(config);
+ ds.setUnprocessedFailoverThreshold(100L);
+ assertTrue(ds.getUnprocessedFailoverThreshold() == 100L);
+ }
+
+ @Test
+ public void testGetParentLogger() {
+ Properties props = new Properties();
+ BaseDBConfiguration config = new JDBCConfiguration(props);
+ CachedDataSource ds = new TerminatingCachedDataSource(config);
+ ds.setInterval(100L);
+ try {
+ assertNull(ds.getParentLogger());
+ } catch (SQLFeatureNotSupportedException e) {
+ LoggerFactory.getLogger(TerminatingCachedDataSourceTest.class).warn("Test Failure", e);
+ }
+ }
+} \ No newline at end of file
diff --git a/core/dblib/provider/src/test/java/org/onap/ccsdk/sli/core/dblib/TestDBResourceManager.java b/core/dblib/provider/src/test/java/org/onap/ccsdk/sli/core/dblib/TestDBResourceManager.java
new file mode 100644
index 000000000..8d7d34324
--- /dev/null
+++ b/core/dblib/provider/src/test/java/org/onap/ccsdk/sli/core/dblib/TestDBResourceManager.java
@@ -0,0 +1,70 @@
+package org.onap.ccsdk.sli.core.dblib;
+
+import static org.junit.Assert.*;
+
+import java.io.InputStream;
+import java.net.URL;
+import java.sql.SQLException;
+import java.util.Properties;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import ch.vorburger.mariadb4j.DB;
+import ch.vorburger.mariadb4j.DBConfigurationBuilder;
+
+public class TestDBResourceManager {
+
+ DbLibService dblibSvc;
+ DBResourceManager dbm;
+
+ @Before
+ public void setUp() throws Exception {
+ URL propUrl = getClass().getResource("/dblib.properties");
+
+ InputStream propStr = getClass().getResourceAsStream("/dblib.properties");
+
+ Properties props = new Properties();
+
+ props.load(propStr);
+
+ // Start MariaDB4j database
+ DBConfigurationBuilder config = DBConfigurationBuilder.newBuilder();
+ config.setPort(0); // 0 => autom. detect free port
+ DB db = DB.newEmbeddedDB(config.build());
+ db.start();
+
+ // Override jdbc URL and database name
+ props.setProperty("org.onap.ccsdk.sli.jdbc.database", "test");
+ props.setProperty("org.onap.ccsdk.sli.jdbc.url", config.getURL("test"));
+
+ dblibSvc = new DBResourceManager(props);
+ dbm = new DBResourceManager(props);
+ dblibSvc.writeData("CREATE TABLE DBLIB_TEST (name varchar(20));", null, null);
+ dblibSvc.getData("SELECT * FROM DBLIB_TEST", null, null);
+
+ }
+
+ @Test
+ public void testForceRecovery() {
+ dbm.testForceRecovery();
+ }
+
+ @Test
+ public void testGetConnection() throws SQLException {
+ assertNotNull(dbm.getConnection());
+ assertNotNull(dbm.getConnection("testUser", "testPaswd"));
+ }
+
+ @Test
+ public void testCleanup() {
+ dbm.cleanUp();
+
+ }
+
+ @Test
+ public void testGetLogWriter() throws SQLException {
+ assertNull(dbm.getLogWriter());
+ }
+
+}
diff --git a/core/dblib/provider/src/test/java/org/onap/ccsdk/sli/core/dblib/TestDBResourceManager2.java b/core/dblib/provider/src/test/java/org/onap/ccsdk/sli/core/dblib/TestDBResourceManager2.java
new file mode 100644
index 000000000..a3cb8d914
--- /dev/null
+++ b/core/dblib/provider/src/test/java/org/onap/ccsdk/sli/core/dblib/TestDBResourceManager2.java
@@ -0,0 +1,95 @@
+/*-
+ 2 * ============LICENSE_START=======================================================
+ 3 * ONAP CCSDK
+ 4 * ================================================================================
+ 5 * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ 6 * reserved.
+ 7 * ================================================================================
+ 8 * Licensed under the Apache License, Version 2.0 (the "License");
+ 9 * you may not use this file except in compliance with the License.
+ 10 * You may obtain a copy of the License at
+ 11 *
+ 12 * http://www.apache.org/licenses/LICENSE-2.0
+ 13 *
+ 14 * Unless required by applicable law or agreed to in writing, software
+ 15 * distributed under the License is distributed on an "AS IS" BASIS,
+ 16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ 17 * See the License for the specific language governing permissions and
+ 18 * limitations under the License.
+ 19 * ============LICENSE_END============================================
+ 20 * ===================================================================
+ 21 *
+ 22 */
+package org.onap.ccsdk.sli.core.dblib;
+
+import static org.junit.Assert.*;
+
+import java.io.InputStream;
+import java.net.URL;
+import java.sql.SQLException;
+import java.util.Properties;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import ch.vorburger.mariadb4j.DB;
+import ch.vorburger.mariadb4j.DBConfigurationBuilder;
+
+public class TestDBResourceManager2 {
+
+ DbLibService dblibSvc;
+ DBResourceManager dbm;
+
+ @Before
+ public void setUp() throws Exception {
+ URL propUrl = getClass().getResource("/dblib.properties");
+
+ InputStream propStr = getClass().getResourceAsStream("/dblib.properties");
+
+ Properties props = new Properties();
+
+ props.load(propStr);
+
+ // Start MariaDB4j database
+ DBConfigurationBuilder config = DBConfigurationBuilder.newBuilder();
+ config.setPort(0); // 0 => autom. detect free port
+ DB db = DB.newEmbeddedDB(config.build());
+ db.start();
+
+ // Override jdbc URL, database name, and recovery
+ props.setProperty("org.onap.ccsdk.sli.jdbc.database", "test");
+ props.setProperty("org.onap.ccsdk.sli.jdbc.url", config.getURL("test"));
+ props.setProperty("org.onap.dblib.connection.recovery", "true");
+
+
+ dblibSvc = new DBResourceManager(props);
+ dbm = new DBResourceManager(props);
+ dblibSvc.writeData("CREATE TABLE DBLIB_TEST2 (name varchar(20));", null, null);
+ dblibSvc.getData("SELECT * FROM DBLIB_TEST2", null, null);
+
+
+ }
+
+ @Test
+ public void testForceRecovery() {
+ dbm.testForceRecovery();
+ }
+
+ @Test
+ public void testGetConnection() throws SQLException {
+ assertNotNull(dbm.getConnection());
+ assertNotNull(dbm.getConnection("testUser", "testPaswd"));
+ }
+
+ @Test
+ public void testCleanup() {
+ dbm.cleanUp();
+
+ }
+
+ @Test
+ public void testGetLogWriter() throws SQLException {
+ assertNull(dbm.getLogWriter());
+ }
+
+}
diff --git a/core/dblib/provider/src/test/resources/dblib.properties b/core/dblib/provider/src/test/resources/dblib.properties
new file mode 100644
index 000000000..9506ac8d1
--- /dev/null
+++ b/core/dblib/provider/src/test/resources/dblib.properties
@@ -0,0 +1,38 @@
+###
+# ============LICENSE_START=======================================================
+# openECOMP : SDN-C
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights
+# reserved.
+# ================================================================================
+# 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.
+# ============LICENSE_END=========================================================
+###
+
+# dblib.properrties
+org.onap.ccsdk.sli.dbtype=jdbc
+
+org.onap.ccsdk.sli.jdbc.hosts=sdnctldb01
+org.onap.ccsdk.sli.jdbc.url=jdbc:mysql://dbhost:3306/sdnctl
+org.onap.ccsdk.sli.jdbc.driver=org.mariadb.jdbc.Driver
+org.onap.ccsdk.sli.jdbc.database=sdnctl
+org.onap.ccsdk.sli.jdbc.user=sdnctl
+org.onap.ccsdk.sli.jdbc.password=gamma
+org.onap.ccsdk.sli.jdbc.connection.name=sdnctldb01
+org.onap.ccsdk.sli.jdbc.connection.timeout=50
+org.onap.ccsdk.sli.jdbc.request.timeout=100
+org.onap.ccsdk.sli.jdbc.limit.init=10
+org.onap.ccsdk.sli.jdbc.limit.min=10
+org.onap.ccsdk.sli.jdbc.limit.max=20
+org.onap.dblib.connection.recovery=false
+
diff --git a/core/features/ccsdk-dblib/pom.xml b/core/features/ccsdk-dblib/pom.xml
new file mode 100644
index 000000000..88a840a15
--- /dev/null
+++ b/core/features/ccsdk-dblib/pom.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>single-feature-parent</artifactId>
+ <version>2.1.0-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>ccsdk-dblib</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>feature</packaging>
+
+ <name>ccsdk-sli-core :: dblib :: ${project.artifactId}</name>
+
+ <dependencies>
+
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>dblib-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.mariadb.jdbc</groupId>
+ <artifactId>mariadb-java-client</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.tomcat</groupId>
+ <artifactId>tomcat-jdbc</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>utils-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.derby</groupId>
+ <artifactId>derby</artifactId>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.karaf.tooling</groupId>
+ <artifactId>karaf-maven-plugin</artifactId>
+ <extensions>true</extensions>
+ <configuration>
+ <excludedArtifactIds>
+ <excludedArtifactId>slf4j-api</excludedArtifactId>
+ <excludedArtifactId>tomcat-jdbc</excludedArtifactId>
+ <excludedArtifactId>tomcat-juli</excludedArtifactId>
+ </excludedArtifactIds>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/core/features/ccsdk-dblib/src/main/feature/feature.xml b/core/features/ccsdk-dblib/src/main/feature/feature.xml
new file mode 100644
index 000000000..771c37455
--- /dev/null
+++ b/core/features/ccsdk-dblib/src/main/feature/feature.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<features xmlns="http://karaf.apache.org/xmlns/features/v1.4.0" name="ccsdk-dblib">
+
+ <feature name="ccsdk-dblib" description="ccsdk-sli-core :: dblib :: ccsdk-dblib" version="${project.version}">
+ <details>Root POM to be used in place of odlparent for CCSDK based projects</details>
+ <feature prerequisite="true" dependency="false">wrap</feature>
+ <bundle>mvn:org.onap.ccsdk.sli.core/dblib-provider/${project.version}</bundle>
+ <bundle>mvn:org.mariadb.jdbc/mariadb-java-client/${mariadb.connector.version}</bundle>
+ <bundle>wrap:mvn:org.apache.tomcat/tomcat-jdbc/${tomcat-jdbc.version}/$DynamicImport-Package=org.mariadb.*,org.apache.derby.*&amp;overwrite=merge</bundle>
+ <bundle>wrap:mvn:org.apache.tomcat/tomcat-juli/${tomcat-jdbc.version}/$DynamicImport-Package=org.mariadb.*,org.apache.derby.*&amp;overwrite=merge</bundle>
+ <bundle>mvn:org.onap.ccsdk.sli.core/utils-provider/${project.version}</bundle>
+ </feature>
+</features>
diff --git a/core/features/ccsdk-filters/pom.xml b/core/features/ccsdk-filters/pom.xml
new file mode 100644
index 000000000..b096df322
--- /dev/null
+++ b/core/features/ccsdk-filters/pom.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>single-feature-parent</artifactId>
+ <version>2.1.0-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>ccsdk-filters</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>feature</packaging>
+
+ <name>ccsdk-sli-core :: filters :: ${project.artifactId}</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>filters-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.karaf.tooling</groupId>
+ <artifactId>karaf-maven-plugin</artifactId>
+ <extensions>true</extensions>
+ <configuration>
+ <excludedArtifactIds>
+ <!-- let opendaylight start these features/jars to avoid conflicts at runtime -->
+ <excludedArtifactId>slf4j-api</excludedArtifactId>
+ <excludedArtifactId>javax.annotation-api</excludedArtifactId>
+ <excludedArtifactId>javax.servlet-api</excludedArtifactId>
+ <excludedArtifactId>javax.ws.rs-api</excludedArtifactId>
+ </excludedArtifactIds>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/core/features/ccsdk-sli-core-all/pom.xml b/core/features/ccsdk-sli-core-all/pom.xml
new file mode 100644
index 000000000..270ed685f
--- /dev/null
+++ b/core/features/ccsdk-sli-core-all/pom.xml
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>single-feature-parent</artifactId>
+ <version>2.1.0-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>ccsdk-sli-core-all</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>feature</packaging>
+
+ <name>ccsdk-sli-core :: features :: ${project.artifactId}</name>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sli-common</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sli-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>dblib-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>ccsdk-slicore-utils</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>ccsdk-dblib</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>ccsdk-filters</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>ccsdk-sli</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>ccsdk-sliapi</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>ccsdk-sliPluginUtils</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/core/features/ccsdk-sli/pom.xml b/core/features/ccsdk-sli/pom.xml
new file mode 100644
index 000000000..f6e97ec20
--- /dev/null
+++ b/core/features/ccsdk-sli/pom.xml
@@ -0,0 +1,54 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>single-feature-parent</artifactId>
+ <version>2.1.0-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>ccsdk-sli</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>feature</packaging>
+
+ <name>ccsdk-sli-core :: sli :: ${project.artifactId}</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sli-common</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sli-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>dblib-provider</artifactId>
+ <version>${project.version}</version>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.mariadb.jdbc</groupId>
+ <artifactId>mariadb-java-client</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>ccsdk-dblib</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ </dependency>
+
+
+ </dependencies>
+</project>
diff --git a/core/features/ccsdk-sliPluginUtils/pom.xml b/core/features/ccsdk-sliPluginUtils/pom.xml
new file mode 100644
index 000000000..c050dcde5
--- /dev/null
+++ b/core/features/ccsdk-sliPluginUtils/pom.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>single-feature-parent</artifactId>
+ <version>2.1.0-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>ccsdk-sliPluginUtils</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>feature</packaging>
+
+ <name>ccsdk-sli-core :: sliPluginUtils :: ${project.artifactId}</name>
+
+ <dependencies>
+
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>ccsdk-sli</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ </dependency>
+
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>sliPluginUtils-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ </dependencies>
+</project>
diff --git a/core/features/ccsdk-sliapi/pom.xml b/core/features/ccsdk-sliapi/pom.xml
new file mode 100644
index 000000000..89e7eec3e
--- /dev/null
+++ b/core/features/ccsdk-sliapi/pom.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>single-feature-parent</artifactId>
+ <version>2.1.0-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>ccsdk-sliapi</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>feature</packaging>
+
+ <name>ccsdk-sli-core :: sliapi :: ${project.artifactId}</name>
+
+ <dependencies>
+
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>ccsdk-sli</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ </dependency>
+
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>sliapi-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ </dependencies>
+</project>
diff --git a/core/features/ccsdk-slicore-utils/pom.xml b/core/features/ccsdk-slicore-utils/pom.xml
new file mode 100644
index 000000000..ea8492b75
--- /dev/null
+++ b/core/features/ccsdk-slicore-utils/pom.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>single-feature-parent</artifactId>
+ <version>2.1.0-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>ccsdk-slicore-utils</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>feature</packaging>
+
+ <name>ccsdk-sli-core :: utils :: ${project.artifactId}</name>
+
+ <dependencies>
+
+
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>utils-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ </dependencies>
+</project>
diff --git a/core/features/features-sli-core/pom.xml b/core/features/features-sli-core/pom.xml
new file mode 100644
index 000000000..1459cef01
--- /dev/null
+++ b/core/features/features-sli-core/pom.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>feature-repo-parent</artifactId>
+ <version>2.1.0-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>features-sli-core</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>feature</packaging>
+
+ <name>ccsdk-sli-core :: features :: ${project.artifactId}</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>ccsdk-sli-core-all</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ </dependency>
+
+ </dependencies>
+</project>
diff --git a/core/features/installer/pom.xml b/core/features/installer/pom.xml
new file mode 100755
index 000000000..d02e5d8d3
--- /dev/null
+++ b/core/features/installer/pom.xml
@@ -0,0 +1,214 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>odlparent-lite</artifactId>
+ <version>2.1.0-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>slicore-features-installer</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>pom</packaging>
+
+ <name>ccsdk-sli-core :: features :: ${project.artifactId}</name>
+
+ <properties>
+ <application.name>ccsdk-sli-core-all</application.name>
+ <features.boot>${application.name}</features.boot>
+ <features.repositories>mvn:org.onap.ccsdk.sli.core/${features.boot}/${project.version}/xml/features</features.repositories>
+ <include.transitive.dependencies>false</include.transitive.dependencies>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>ccsdk-slicore-utils</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ <exclusions>
+ <exclusion>
+ <groupId>*</groupId>
+ <artifactId>*</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>ccsdk-dblib</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ <exclusions>
+ <exclusion>
+ <groupId>*</groupId>
+ <artifactId>*</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>ccsdk-filters</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ <exclusions>
+ <exclusion>
+ <groupId>*</groupId>
+ <artifactId>*</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>ccsdk-sli</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ <exclusions>
+ <exclusion>
+ <groupId>*</groupId>
+ <artifactId>*</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>ccsdk-sliapi</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ <exclusions>
+ <exclusion>
+ <groupId>*</groupId>
+ <artifactId>*</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>ccsdk-sliPluginUtils</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ <exclusions>
+ <exclusion>
+ <groupId>*</groupId>
+ <artifactId>*</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>${application.name}</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ <exclusions>
+ <exclusion>
+ <groupId>*</groupId>
+ <artifactId>*</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+
+
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>maven-repo-zip</id>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ <phase>package</phase>
+ <configuration>
+ <attach>true</attach>
+ <finalName>stage/${application.name}-${project.version}</finalName>
+ <descriptors>
+ <descriptor>src/assembly/assemble_mvnrepo_zip.xml</descriptor>
+ </descriptors>
+ <appendAssemblyId>true</appendAssemblyId>
+ </configuration>
+ </execution>
+ <execution>
+ <id>installer-zip</id>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ <phase>package</phase>
+ <configuration>
+ <attach>true</attach>
+ <finalName>${application.name}-${project.version}-installer</finalName>
+ <descriptors>
+ <descriptor>src/assembly/assemble_installer_zip.xml</descriptor>
+ </descriptors>
+ <appendAssemblyId>false</appendAssemblyId>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>copy-dependencies</id>
+ <goals>
+ <goal>copy-dependencies</goal>
+ </goals>
+ <phase>prepare-package</phase>
+ <configuration>
+ <transitive>false</transitive>
+ <outputDirectory>${project.build.directory}/assembly/system</outputDirectory>
+ <overWriteReleases>false</overWriteReleases>
+ <overWriteSnapshots>true</overWriteSnapshots>
+ <overWriteIfNewer>true</overWriteIfNewer>
+ <useRepositoryLayout>true</useRepositoryLayout>
+ <addParentPoms>false</addParentPoms>
+ <copyPom>false</copyPom>
+ <includeGroupIds>org.onap.ccsdk.sli.core,org.apache.tomcat,org.slf4j</includeGroupIds>
+ <excludeArtifactIds>utils-provider,slf4j-api</excludeArtifactIds>
+ <scope>provided</scope>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <artifactId>maven-resources-plugin</artifactId>
+ <version>2.6</version>
+ <executions>
+ <execution>
+ <id>copy-version</id>
+ <goals>
+ <goal>copy-resources</goal>
+ </goals><!-- here the phase you need -->
+ <phase>validate</phase>
+ <configuration>
+ <outputDirectory>${basedir}/target/stage</outputDirectory>
+ <resources>
+ <resource>
+ <directory>src/main/resources/scripts</directory>
+ <includes>
+ <include>install-feature.sh</include>
+ </includes>
+ <filtering>true</filtering>
+ </resource>
+ </resources>
+ </configuration>
+ </execution>
+
+ </executions>
+ </plugin>
+
+ </plugins>
+ </build>
+</project>
diff --git a/core/features/installer/src/assembly/assemble_installer_zip.xml b/core/features/installer/src/assembly/assemble_installer_zip.xml
new file mode 100755
index 000000000..a6a22a9ba
--- /dev/null
+++ b/core/features/installer/src/assembly/assemble_installer_zip.xml
@@ -0,0 +1,39 @@
+<!-- Defines how we build the .zip file which is our distribution. -->
+
+<assembly
+ xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
+ <id>bin</id>
+
+ <formats>
+ <format>zip</format>
+ </formats>
+
+ <!-- we want "system" and related files right at the root level
+ as this file is suppose to be unzip on top of a karaf
+ distro. -->
+ <includeBaseDirectory>false</includeBaseDirectory>
+
+ <fileSets>
+ <fileSet>
+ <directory>target/stage/</directory>
+ <outputDirectory>${application.name}</outputDirectory>
+ <fileMode>755</fileMode>
+ <includes>
+ <include>*.sh</include>
+ </includes>
+ </fileSet>
+ <fileSet>
+ <directory>target/stage/</directory>
+ <outputDirectory>${application.name}</outputDirectory>
+ <fileMode>644</fileMode>
+ <excludes>
+ <exclude>*.sh</exclude>
+ </excludes>
+ </fileSet>
+ </fileSets>
+
+
+
+</assembly>
diff --git a/core/features/installer/src/assembly/assemble_mvnrepo_zip.xml b/core/features/installer/src/assembly/assemble_mvnrepo_zip.xml
new file mode 100755
index 000000000..86b07f1f3
--- /dev/null
+++ b/core/features/installer/src/assembly/assemble_mvnrepo_zip.xml
@@ -0,0 +1,29 @@
+<!-- Defines how we build the .zip file which is our distribution. -->
+
+<assembly
+ xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
+ <id>repo</id>
+
+ <formats>
+ <format>zip</format>
+ </formats>
+
+ <!-- we want "system" and related files right at the root level
+ as this file is suppose to be unzip on top of a karaf
+ distro. -->
+ <includeBaseDirectory>false</includeBaseDirectory>
+
+ <fileSets>
+ <fileSet>
+ <directory>target/assembly/</directory>
+ <outputDirectory>.</outputDirectory>
+ <excludes>
+ </excludes>
+ </fileSet>
+ </fileSets>
+
+
+
+</assembly>
diff --git a/core/features/installer/src/main/resources/scripts/install-feature.sh b/core/features/installer/src/main/resources/scripts/install-feature.sh
new file mode 100644
index 000000000..e16e79a12
--- /dev/null
+++ b/core/features/installer/src/main/resources/scripts/install-feature.sh
@@ -0,0 +1,18 @@
+#!/bin/bash
+
+ODL_HOME=${ODL_HOME:-/opt/opendaylight/current}
+ODL_KARAF_CLIENT=${ODL_KARAF_CLIENT:-${ODL_HOME}/bin/client}
+INSTALLERDIR=$(dirname $0)
+
+REPOZIP=${INSTALLERDIR}/${features.boot}-${project.version}.zip
+
+if [ -f ${REPOZIP} ]
+then
+ unzip -d ${ODL_HOME} ${REPOZIP}
+else
+ echo "ERROR : repo zip ($REPOZIP) not found"
+ exit 1
+fi
+
+${ODL_KARAF_CLIENT} feature:repo-add ${features.repositories}
+${ODL_KARAF_CLIENT} feature:install ${features.boot}
diff --git a/core/features/pom.xml b/core/features/pom.xml
new file mode 100755
index 000000000..69355a4c7
--- /dev/null
+++ b/core/features/pom.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>odlparent-lite</artifactId>
+ <version>2.1.0-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>slicore-feature-aggregator</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>pom</packaging>
+
+ <name>ccsdk-sli-core :: features</name>
+
+ <modules>
+ <module>ccsdk-slicore-utils</module>
+ <module>ccsdk-dblib</module>
+ <module>ccsdk-filters</module>
+ <module>ccsdk-sli</module>
+ <module>ccsdk-sliapi</module>
+ <module>ccsdk-sliPluginUtils</module>
+ <module>ccsdk-sli-core-all</module>
+ <module>features-sli-core</module>
+ <module>installer</module>
+ </modules>
+</project>
diff --git a/core/filters/.gitignore b/core/filters/.gitignore
new file mode 100755
index 000000000..b73caf31e
--- /dev/null
+++ b/core/filters/.gitignore
@@ -0,0 +1,34 @@
+#####standard .git ignore entries#####
+
+## IDE Specific Files ##
+org.eclipse.core.resources.prefs
+.classpath
+.project
+.settings
+.idea
+.externalToolBuilders
+maven-eclipse.xml
+workspace
+
+## Compilation Files ##
+*.class
+**/target
+target
+target-ide
+MANIFEST.MF
+
+## Misc Ignores (OS specific etc) ##
+bin/
+dist
+*~
+*.ipr
+*.iml
+*.iws
+classes
+out/
+.DS_STORE
+.metadata
+
+## Folders which contain auto generated source code ##
+yang-gen-config
+yang-gen-sal
diff --git a/core/filters/.sonar/checkstyle.xml b/core/filters/.sonar/checkstyle.xml
new file mode 100755
index 000000000..3fa231535
--- /dev/null
+++ b/core/filters/.sonar/checkstyle.xml
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE module PUBLIC "-//Puppy Crawl//DTD Check Configuration 1.2//EN" "http://www.puppycrawl.com/dtds/configuration_1_2.dtd"><!-- Generated by Sonar --><module name="Checker"><module name="SuppressionCommentFilter"/><module name="TreeWalker"><module name="FileContentsHolder"/> <module name="ClassFanOutComplexity"><property name="severity" value="warning"/></module><module name="NestedForDepth"><property name="severity" value="warning"/><property name="max" value="1"/></module><module name="ClassDataAbstractionCoupling"><property name="severity" value="warning"/></module></module></module> \ No newline at end of file
diff --git a/core/filters/.sonar/pmd.xml b/core/filters/.sonar/pmd.xml
new file mode 100755
index 000000000..80343b3bd
--- /dev/null
+++ b/core/filters/.sonar/pmd.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ruleset>
+ <rule ref="rulesets/java/naming.xml/BooleanGetMethodName">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/j2ee.xml/StaticEJBFieldShouldBeFinal">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/coupling.xml/CouplingBetweenObjects">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/codesize.xml/TooManyMethods">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/naming.xml/AvoidFieldNameMatchingTypeName">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/basic.xml/DoubleCheckedLocking">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/naming.xml/AvoidFieldNameMatchingMethodName">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/coupling.xml/ExcessiveImports">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/basic.xml/OverrideBothEqualsAndHashcode">
+ <priority>2</priority>
+ </rule>
+ <rule ref="rulesets/java/naming.xml/ShortMethodName">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/basic.xml/BooleanInstantiation">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/codesize.xml/TooManyFields">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/controversial.xml/AvoidUsingNativeCode">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/optimizations.xml/UseStringBufferForStringAppends">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/coupling.xml/LooseCoupling">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/design.xml/NonThreadSafeSingleton">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/j2ee.xml/DoNotUseThreads">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/sunsecure.xml/ArrayIsStoredDirectly">
+ <priority>5</priority>
+ </rule>
+ <rule ref="rulesets/java/sunsecure.xml/MethodReturnsInternalArray">
+ <priority>2</priority>
+ </rule>
+ <rule ref="rulesets/java/design.xml/AssignmentToNonFinalStatic">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/strictexception.xml/AvoidCatchingGenericException">
+ <priority>3</priority>
+ </rule>
+</ruleset>
+
diff --git a/core/filters/README b/core/filters/README
new file mode 100755
index 000000000..5c1b3d627
--- /dev/null
+++ b/core/filters/README
@@ -0,0 +1,14 @@
+
+/restconf filters are enabled by specifying filter chain in
+ /opt/opendaylight/current/etc/org.opendaylight.aaa.filterchain.cfg
+and enabling bundle class loading
+ >bundle:dynamic-import org.onap.ccsdk.sli.core.filters-provider
+
+loggers:
+ org.onap.ccsdk.sli.core.filters.audit
+ org.onap.ccsdk.sli.core.filters.metric
+ org.onap.ccsdk.sli.core.filters.request.response
+
+
+
+
diff --git a/core/filters/installer/pom.xml b/core/filters/installer/pom.xml
new file mode 100755
index 000000000..fae31a12b
--- /dev/null
+++ b/core/filters/installer/pom.xml
@@ -0,0 +1,126 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>odlparent-lite</artifactId>
+ <version>2.1.0-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>filters-installer</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>pom</packaging>
+
+ <name>ccsdk-sli-core :: filters :: ${project.artifactId}</name>
+
+ <properties>
+ <application.name>ccsdk-filters</application.name>
+ <features.boot>${application.name}</features.boot>
+ <features.repositories>mvn:org.onap.ccsdk.sli.core/${features.boot}/${project.version}/xml/features</features.repositories>
+ <include.transitive.dependencies>false</include.transitive.dependencies>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>filters-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>maven-repo-zip</id>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ <phase>package</phase>
+ <configuration>
+ <attach>true</attach>
+ <finalName>stage/${application.name}-${project.version}</finalName>
+ <descriptors>
+ <descriptor>src/assembly/assemble_mvnrepo_zip.xml</descriptor>
+ </descriptors>
+ <appendAssemblyId>true</appendAssemblyId>
+ </configuration>
+ </execution>
+ <execution>
+ <id>installer-zip</id>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ <phase>package</phase>
+ <configuration>
+ <attach>true</attach>
+ <finalName>${application.name}-${project.version}-installer</finalName>
+ <descriptors>
+ <descriptor>src/assembly/assemble_installer_zip.xml</descriptor>
+ </descriptors>
+ <appendAssemblyId>false</appendAssemblyId>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>copy-dependencies</id>
+ <goals>
+ <goal>copy-dependencies</goal>
+ </goals>
+ <phase>prepare-package</phase>
+ <configuration>
+ <transitive>false</transitive>
+ <outputDirectory>${project.build.directory}/assembly/system</outputDirectory>
+ <overWriteReleases>false</overWriteReleases>
+ <overWriteSnapshots>true</overWriteSnapshots>
+ <overWriteIfNewer>true</overWriteIfNewer>
+ <useRepositoryLayout>true</useRepositoryLayout>
+ <addParentPoms>false</addParentPoms>
+ <copyPom>false</copyPom>
+ <includeGroupIds>org.onap.ccsdk.sli.core</includeGroupIds>
+ <excludeArtifactIds>sli-common,sli-provider,utils-provider,dblib-provider</excludeArtifactIds>
+ <scope>provided</scope>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <artifactId>maven-resources-plugin</artifactId>
+ <version>2.6</version>
+ <executions>
+ <execution>
+ <id>copy-version</id>
+ <goals>
+ <goal>copy-resources</goal>
+ </goals><!-- here the phase you need -->
+ <phase>validate</phase>
+ <configuration>
+ <outputDirectory>${basedir}/target/stage</outputDirectory>
+ <resources>
+ <resource>
+ <directory>src/main/resources/scripts</directory>
+ <includes>
+ <include>install-feature.sh</include>
+ </includes>
+ <filtering>true</filtering>
+ </resource>
+ </resources>
+ </configuration>
+ </execution>
+
+ </executions>
+ </plugin>
+
+ </plugins>
+ </build>
+</project>
diff --git a/core/filters/installer/src/assembly/assemble_installer_zip.xml b/core/filters/installer/src/assembly/assemble_installer_zip.xml
new file mode 100644
index 000000000..2ff550d2c
--- /dev/null
+++ b/core/filters/installer/src/assembly/assemble_installer_zip.xml
@@ -0,0 +1,61 @@
+<!--
+ ============LICENSE_START=======================================================
+ ONAP : CCSDK
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property. All rights
+ reserved.
+ ================================================================================
+ 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.
+ ============LICENSE_END=========================================================
+ -->
+
+<!-- Defines how we build the .zip file which is our distribution. -->
+
+<assembly
+ xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
+
+ <id>bin</id>
+
+ <formats>
+ <format>zip</format>
+ </formats>
+
+ <!-- we want "system" and related files right at the root level
+ as this file is suppose to be unzip on top of a karaf
+ distro. -->
+ <includeBaseDirectory>false</includeBaseDirectory>
+
+ <fileSets>
+ <fileSet>
+ <directory>target/stage/</directory>
+ <outputDirectory>${application.name}</outputDirectory>
+ <fileMode>755</fileMode>
+ <includes>
+ <include>*.sh</include>
+ </includes>
+ </fileSet>
+ <fileSet>
+ <directory>target/stage/</directory>
+ <outputDirectory>${application.name}</outputDirectory>
+ <fileMode>644</fileMode>
+ <excludes>
+ <exclude>*.sh</exclude>
+ </excludes>
+ </fileSet>
+ </fileSets>
+
+
+
+</assembly>
diff --git a/core/filters/installer/src/assembly/assemble_mvnrepo_zip.xml b/core/filters/installer/src/assembly/assemble_mvnrepo_zip.xml
new file mode 100644
index 000000000..69e9e2909
--- /dev/null
+++ b/core/filters/installer/src/assembly/assemble_mvnrepo_zip.xml
@@ -0,0 +1,49 @@
+<!--
+ ============LICENSE_START=======================================================
+ ONAP : CCSDK
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property. All rights
+ reserved.
+ ================================================================================
+ 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.
+ ============LICENSE_END=========================================================
+ -->
+
+<!-- Defines how we build the .zip file which is our distribution. -->
+
+<assembly
+ xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
+ <id>repo</id>
+ <formats>
+ <format>zip</format>
+ </formats>
+
+ <!-- we want "system" and related files right at the root level
+ as this file is suppose to be unzip on top of a karaf
+ distro. -->
+ <includeBaseDirectory>false</includeBaseDirectory>
+
+ <fileSets>
+ <fileSet>
+ <directory>target/assembly/</directory>
+ <outputDirectory>.</outputDirectory>
+ <excludes>
+ </excludes>
+ </fileSet>
+ </fileSets>
+
+
+
+</assembly>
diff --git a/core/filters/installer/src/main/resources/scripts/install-feature.sh b/core/filters/installer/src/main/resources/scripts/install-feature.sh
new file mode 100644
index 000000000..74b95b5c8
--- /dev/null
+++ b/core/filters/installer/src/main/resources/scripts/install-feature.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+
+###
+# ============LICENSE_START=======================================================
+# ONAP : CCSDK
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights
+# reserved.
+# ================================================================================
+# 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.
+# ============LICENSE_END=========================================================
+###
+
+ODL_HOME=${ODL_HOME:-/opt/opendaylight/current}
+ODL_KARAF_CLIENT=${ODL_KARAF_CLIENT:-${ODL_HOME}/bin/client}
+INSTALLERDIR=$(dirname $0)
+
+REPOZIP=${INSTALLERDIR}/${features.boot}-${project.version}.zip
+
+if [ -f ${REPOZIP} ]
+then
+ unzip -d ${ODL_HOME} ${REPOZIP}
+else
+ echo "ERROR : repo zip ($REPOZIP) not found"
+ exit 1
+fi
+
+${ODL_KARAF_CLIENT} feature:repo-add ${features.repositories}
+${ODL_KARAF_CLIENT} feature:install ${features.boot}
diff --git a/core/filters/pom.xml b/core/filters/pom.xml
new file mode 100644
index 000000000..8db5d810b
--- /dev/null
+++ b/core/filters/pom.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>odlparent-lite</artifactId>
+ <version>2.1.0-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>filters</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>pom</packaging>
+
+ <name>ccsdk-sli-core :: filters</name>
+ <description>Servlet filter to implement ONAP logging spec</description>
+ <organization>
+ <name>ONAP</name>
+ </organization>
+
+ <modules>
+ <module>provider</module>
+ <module>installer</module>
+ </modules>
+</project>
diff --git a/core/filters/provider/pom.xml b/core/filters/provider/pom.xml
new file mode 100755
index 000000000..ea7f9962e
--- /dev/null
+++ b/core/filters/provider/pom.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>binding-parent</artifactId>
+ <version>2.1.0-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>filters-provider</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>bundle</packaging>
+
+ <name>ccsdk-sli-core :: filters :: ${project.artifactId}</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.onap.logging-analytics</groupId>
+ <artifactId>logging-filter-base</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>javax.servlet-api</artifactId>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/core/filters/provider/src/main/java/org/onap/ccsdk/sli/core/filters/ControllerAuditLogFilter.java b/core/filters/provider/src/main/java/org/onap/ccsdk/sli/core/filters/ControllerAuditLogFilter.java
new file mode 100644
index 000000000..7805e365d
--- /dev/null
+++ b/core/filters/provider/src/main/java/org/onap/ccsdk/sli/core/filters/ControllerAuditLogFilter.java
@@ -0,0 +1,40 @@
+package org.onap.ccsdk.sli.core.filters;
+
+import javax.servlet.http.HttpServletRequest;
+import org.onap.logging.filter.base.AuditLogServletFilter;
+import org.onap.logging.ref.slf4j.ONAPLogConstants;
+import org.slf4j.MDC;
+
+public class ControllerAuditLogFilter extends AuditLogServletFilter {
+ private static final String MDC_HTTP_METHOD_KEY = "HttpMethod";
+
+ @Override
+ protected void additionalPreHandling(HttpServletRequest httpServletRequest) {
+ // Don't overwrite service instance id if it was set outside of this automated method
+ if (MDC.get(ONAPLogConstants.MDCs.SERVICE_INSTANCE_ID) == null) {
+ String serviceInstanceId = getServiceInstanceId(httpServletRequest.getPathInfo());
+ if (serviceInstanceId != null) {
+ MDC.put(ONAPLogConstants.MDCs.SERVICE_INSTANCE_ID, serviceInstanceId);
+ }
+ }
+ MDC.put(MDC_HTTP_METHOD_KEY, httpServletRequest.getMethod());
+ }
+
+ // restconf URLs follow a pattern, this method attempts to extract the service instance id according to that pattern
+ protected String getServiceInstanceId(String path) {
+ int idx = path.indexOf("service-list");
+ if (idx != -1) {
+ // chomp off service-list/
+ String str = path.substring(idx + 13);
+ idx = str.indexOf("/");
+ //if there is another forward slash with more information chomp it off
+ if (idx != -1) {
+ return str.substring(0, idx);
+ } else {
+ return str;
+ }
+ }
+ return null;
+ }
+
+}
diff --git a/core/filters/provider/src/main/java/org/onap/ccsdk/sli/core/filters/ControllerPayloadLoggingFilter.java b/core/filters/provider/src/main/java/org/onap/ccsdk/sli/core/filters/ControllerPayloadLoggingFilter.java
new file mode 100644
index 000000000..3f9f93fc5
--- /dev/null
+++ b/core/filters/provider/src/main/java/org/onap/ccsdk/sli/core/filters/ControllerPayloadLoggingFilter.java
@@ -0,0 +1,7 @@
+package org.onap.ccsdk.sli.core.filters;
+
+import org.onap.logging.filter.base.PayloadLoggingServletFilter;
+
+public class ControllerPayloadLoggingFilter extends PayloadLoggingServletFilter {
+
+}
diff --git a/core/filters/provider/src/test/java/org/onap/ccsdk/sli/core/filters/ControllerAuditLogFilterTest.java b/core/filters/provider/src/test/java/org/onap/ccsdk/sli/core/filters/ControllerAuditLogFilterTest.java
new file mode 100644
index 000000000..9d0357a96
--- /dev/null
+++ b/core/filters/provider/src/test/java/org/onap/ccsdk/sli/core/filters/ControllerAuditLogFilterTest.java
@@ -0,0 +1,23 @@
+package org.onap.ccsdk.sli.core.filters;
+
+import static org.junit.Assert.assertEquals;
+import org.junit.Test;
+
+public class ControllerAuditLogFilterTest {
+
+ @Test
+ public void getSimpleSiid() throws Exception {
+ ControllerAuditLogFilter filter = new ControllerAuditLogFilter();
+ String siid = filter.getServiceInstanceId("/restconf/config/Layer3API:services/service-list/100");
+ assertEquals("100", siid);
+ }
+
+ @Test
+ public void getSimpleComplexSiid() throws Exception {
+ ControllerAuditLogFilter filter = new ControllerAuditLogFilter();
+ String siid = filter.getServiceInstanceId(
+ "/restconf/config/Layer3API:services/service-list/1337/service-data/oper-status");
+ assertEquals("1337", siid);
+ }
+
+}
diff --git a/core/releases/0.5.0.yaml b/core/releases/0.5.0.yaml
new file mode 100644
index 000000000..dc9dae2c0
--- /dev/null
+++ b/core/releases/0.5.0.yaml
@@ -0,0 +1,5 @@
+---
+distribution_type: 'maven'
+version: '0.5.0'
+project: 'ccsdk-sli-core'
+log_dir: 'ccsdk-sli-core-maven-stage-master/157/'
diff --git a/core/releases/0.5.1.yaml b/core/releases/0.5.1.yaml
new file mode 100644
index 000000000..00785283f
--- /dev/null
+++ b/core/releases/0.5.1.yaml
@@ -0,0 +1,5 @@
+---
+distribution_type: 'maven'
+version: '0.5.1'
+project: 'ccsdk-sli-core'
+log_dir: 'ccsdk-sli-core-maven-stage-master/165/'
diff --git a/core/releases/0.5.2.yaml b/core/releases/0.5.2.yaml
new file mode 100644
index 000000000..25c0b4ada
--- /dev/null
+++ b/core/releases/0.5.2.yaml
@@ -0,0 +1,5 @@
+---
+distribution_type: 'maven'
+version: '0.5.2'
+project: 'ccsdk-sli-core'
+log_dir: 'ccsdk-sli-core-maven-stage-master/173/'
diff --git a/core/releases/0.6.0.yaml b/core/releases/0.6.0.yaml
new file mode 100644
index 000000000..0106367c1
--- /dev/null
+++ b/core/releases/0.6.0.yaml
@@ -0,0 +1,5 @@
+---
+distribution_type: 'maven'
+version: '0.6.0'
+project: 'ccsdk-sli-core'
+log_dir: 'ccsdk-sli-core-maven-stage-master/187/'
diff --git a/core/releases/0.6.1.yaml b/core/releases/0.6.1.yaml
new file mode 100644
index 000000000..8ccc981ed
--- /dev/null
+++ b/core/releases/0.6.1.yaml
@@ -0,0 +1,5 @@
+---
+distribution_type: 'maven'
+version: '0.6.1'
+project: 'ccsdk-sli-core'
+log_dir: 'ccsdk-sli-core-maven-stage-master/203/'
diff --git a/core/releases/0.7.0.yaml b/core/releases/0.7.0.yaml
new file mode 100644
index 000000000..50ec2b4d4
--- /dev/null
+++ b/core/releases/0.7.0.yaml
@@ -0,0 +1,5 @@
+---
+distribution_type: 'maven'
+version: '0.7.0'
+project: 'ccsdk-sli-core'
+log_dir: 'ccsdk-sli-core-maven-stage-master/300/'
diff --git a/core/releases/0.7.1.yaml b/core/releases/0.7.1.yaml
new file mode 100644
index 000000000..0cdbee453
--- /dev/null
+++ b/core/releases/0.7.1.yaml
@@ -0,0 +1,5 @@
+---
+distribution_type: 'maven'
+version: '0.7.1'
+project: 'ccsdk-sli-core'
+log_dir: 'ccsdk-sli-core-maven-stage-master/301/'
diff --git a/core/releases/1.0.0.yaml b/core/releases/1.0.0.yaml
new file mode 100644
index 000000000..7e7e577e3
--- /dev/null
+++ b/core/releases/1.0.0.yaml
@@ -0,0 +1,5 @@
+---
+distribution_type: 'maven'
+version: '1.0.0'
+project: 'ccsdk-sli-core'
+log_dir: 'ccsdk-sli-core-maven-stage-master/302/'
diff --git a/core/releases/1.0.1.yaml b/core/releases/1.0.1.yaml
new file mode 100644
index 000000000..f86a0ba6a
--- /dev/null
+++ b/core/releases/1.0.1.yaml
@@ -0,0 +1,5 @@
+---
+distribution_type: 'maven'
+version: '1.0.1'
+project: 'ccsdk-sli-core'
+log_dir: 'ccsdk-sli-core-maven-stage-master/303/'
diff --git a/core/releases/1.1.0.yaml b/core/releases/1.1.0.yaml
new file mode 100644
index 000000000..3c256dd0f
--- /dev/null
+++ b/core/releases/1.1.0.yaml
@@ -0,0 +1,5 @@
+---
+distribution_type: 'maven'
+version: '1.1.0'
+project: 'ccsdk-sli-core'
+log_dir: 'ccsdk-sli-core-maven-stage-master/304/'
diff --git a/core/sli/.gitignore b/core/sli/.gitignore
new file mode 100755
index 000000000..3632ac676
--- /dev/null
+++ b/core/sli/.gitignore
@@ -0,0 +1,38 @@
+#####standard .git ignore entries#####
+
+## IDE Specific Files ##
+org.eclipse.core.resources.prefs
+.classpath
+.project
+.settings
+.idea
+.externalToolBuilders
+maven-eclipse.xml
+workspace
+
+## Compilation Files ##
+*.class
+**/target
+target
+target-ide
+MANIFEST.MF
+
+## Misc Ignores (OS specific etc) ##
+bin/
+dist
+*~
+*.ipr
+*.iml
+*.iws
+classes
+out/
+.DS_STORE
+.metadata
+
+## antlr4 generated files ##
+ExprGrammarBaseListener.java
+ExprGrammarLexer.java
+ExprGrammarListener.java
+ExprGrammarParser.java
+ExprGrammar.tokens
+ExprGrammarLexer.tokens
diff --git a/core/sli/common/pom.xml b/core/sli/common/pom.xml
new file mode 100755
index 000000000..201c11bdd
--- /dev/null
+++ b/core/sli/common/pom.xml
@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>binding-parent</artifactId>
+ <version>2.1.0-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sli-common</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>bundle</packaging>
+
+ <name>ccsdk-sli-core :: sli :: ${project.artifactId}</name>
+ <description>The SLI Common package includes common classes used by the various SLI subcomponents, as well as classes used by clients to interface with the service logic interpreter</description>
+
+ <properties>
+ <!-- Ignore deprecated classes in coverage counts -->
+ <sonar.coverage.exclusions>**/MessageWriter.java</sonar.coverage.exclusions>
+
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.derby</groupId>
+ <artifactId>derby</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.antlr</groupId>
+ <artifactId>antlr4-runtime</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-lang3</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-text</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>dblib-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sli-model</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.logging-analytics</groupId>
+ <artifactId>logging-slf4j</artifactId>
+ </dependency>
+ <!-- log4j dependencies are needed to test MDC in junit tests -->
+ <dependency>
+ <groupId>org.apache.logging.log4j</groupId>
+ <artifactId>log4j-slf4j-impl</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.logging.log4j</groupId>
+ <artifactId>log4j-core</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.google.code.gson</groupId>
+ <artifactId>gson</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>javax.xml.bind</groupId>
+ <artifactId>jaxb-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.sun.xml.bind</groupId>
+ <artifactId>jaxb-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.sun.xml.bind</groupId>
+ <artifactId>jaxb-impl</artifactId>
+ </dependency>
+ <!-- Testing Dependencies -->
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.skyscreamer</groupId>
+ <artifactId>jsonassert</artifactId>
+ <version>1.5.0</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.antlr</groupId>
+ <artifactId>antlr4-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <configuration>
+ <sourceDirectory>${basedir}/src/main/antlr4</sourceDirectory>
+ <outputDirectory>${project.basedir}/src/main/java/</outputDirectory>
+ </configuration>
+ <id>antlr</id>
+ <goals>
+ <goal>antlr4</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/core/sli/common/src/main/antlr4/org/onap/ccsdk/sli/core/sli/ExprGrammar.g4 b/core/sli/common/src/main/antlr4/org/onap/ccsdk/sli/core/sli/ExprGrammar.g4
new file mode 100755
index 000000000..42563168c
--- /dev/null
+++ b/core/sli/common/src/main/antlr4/org/onap/ccsdk/sli/core/sli/ExprGrammar.g4
@@ -0,0 +1,67 @@
+
+grammar ExprGrammar;
+
+options {
+ language = Java;
+}
+
+
+COMPAREOP : '==' | '!=' | '>' | '<' | '>=' | '<=';
+
+RELOP : 'and' | 'or';
+
+ADDOP : '+' | '-';
+
+MULTOP : '/' | '*';
+
+NUMBER : ('0'..'9')+;
+
+STRING : '\'' ~[']* '\'';
+
+IDENTIFIER : ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_'|'-')*;
+
+// CONTEXT_VAR : '$' IDENTIFIER;
+
+WS: [ \n\t\r]+ -> skip;
+
+constant : NUMBER | STRING ;
+
+variableLead : ('$')? variableTerm ;
+
+variableTerm : IDENTIFIER ('[' expr ']')? ;
+
+variable : variableLead ('.' variableTerm)* ('.')?;
+
+// variable : CONTEXT_VAR ( '[' expr ']' )? ('.' IDENTIFIER )? ;
+
+atom : constant | variable;
+
+
+expr : atom
+ | parenExpr
+ | multExpr
+ | addExpr
+ | compareExpr
+ | relExpr
+ | funcExpr;
+
+parenExpr : '(' expr ')';
+
+term : atom | parenExpr | funcExpr;
+
+multExpr : term (MULTOP term)*;
+
+addExpr : multExpr (ADDOP multExpr)*;
+
+compareExpr : addExpr COMPAREOP addExpr;
+
+relExpr : compareExpr (RELOP expr)*;
+
+funcExpr : IDENTIFIER '(' expr (',' expr)* ')';
+
+
+
+
+
+
+
diff --git a/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/ActivationEntry.java b/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/ActivationEntry.java
new file mode 100644
index 000000000..a1c0eafe8
--- /dev/null
+++ b/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/ActivationEntry.java
@@ -0,0 +1,41 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.sli;
+
+public class ActivationEntry {
+ String module;
+ String rpc;
+ String version;
+ String mode;
+
+ public ActivationEntry(String module, String rpc, String version, String mode) {
+ this.module = module;
+ this.rpc = rpc;
+ this.version = version;
+ this.mode = mode;
+ }
+
+ @Override
+ public String toString() {
+ return "ActivationEntry [module=" + module + ", rpc=" + rpc + ", version=" + version + ", mode=" + mode + "]";
+ }
+}
diff --git a/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/BreakNodeException.java b/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/BreakNodeException.java
new file mode 100644
index 000000000..e1c0e3db5
--- /dev/null
+++ b/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/BreakNodeException.java
@@ -0,0 +1,46 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.sli;
+
+public class BreakNodeException extends SvcLogicException {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1L;
+
+ public BreakNodeException()
+ {
+ super();
+ }
+
+ public BreakNodeException(String message)
+ {
+ super(message);
+ }
+
+ public BreakNodeException(String message, Throwable t)
+ {
+ super(message, t);
+ }
+
+}
diff --git a/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/CheckSumHelper.java b/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/CheckSumHelper.java
new file mode 100644
index 000000000..9283cf650
--- /dev/null
+++ b/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/CheckSumHelper.java
@@ -0,0 +1,51 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.sli;
+
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+import org.onap.ccsdk.sli.core.utils.PathValidator;
+
+import javax.xml.bind.DatatypeConverter;
+
+public class CheckSumHelper {
+
+ public static String md5SumFromFile(String pathToFile) throws NoSuchAlgorithmException, IOException {
+ if (!PathValidator.isValidXmlPath(pathToFile)) {
+ throw new IOException("Invalid XML file name");
+ }
+ byte[] b = Files.readAllBytes(Paths.get(pathToFile));
+ return md5SumFromByteArray(b);
+ }
+
+ private static String md5SumFromByteArray(byte[] input) throws NoSuchAlgorithmException {
+ byte[] hash = MessageDigest.getInstance("MD5").digest(input);
+ String hexString = DatatypeConverter.printHexBinary(hash);
+ return hexString.toLowerCase();
+ }
+
+}
diff --git a/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/CommonConstants.java b/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/CommonConstants.java
new file mode 100644
index 000000000..b1a7320d7
--- /dev/null
+++ b/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/CommonConstants.java
@@ -0,0 +1,38 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.sli;
+
+public interface CommonConstants {
+
+ String SERVICE_LOGIC_STATUS = "SvcLogic.status";
+ String JDBC_CONN_ERR = "no jdbc connection";
+ String JDBC_STATEMENT_ERR = "could not prepare statement ";
+ String SVCLOGIC_TABLE = ".SVC_LOGIC";
+ String JDBC_SELECT_COUNT = "SELECT count(*) FROM ";
+ String RESULTSET_CLOSE_ERR = "ResultSet close error: ";
+ String JDBC_SELECT_GRAPGH = "SELECT graph FROM ";
+ String JDBC_INSERT = "INSERT INTO ";
+ String JDBC_DELETE = "DELETE FROM ";
+ String JDBC_UPDATE = "UPDATE ";
+ String JDBC_GRAPH_QUERY = " WHERE module = ? AND rpc = ? AND mode = ? AND version = ?";
+ String JDBC_ACTIVE_GRAPH_QUERY = " WHERE module = ? AND rpc = ? AND mode = ? AND active = 'Y'";
+}
diff --git a/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/ConfigurationException.java b/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/ConfigurationException.java
new file mode 100644
index 000000000..144b99a8a
--- /dev/null
+++ b/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/ConfigurationException.java
@@ -0,0 +1,45 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.sli;
+
+public class ConfigurationException extends SvcLogicException {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1L;
+
+ public ConfigurationException()
+ {
+ super();
+ }
+
+ public ConfigurationException(String msg)
+ {
+ super(msg);
+ }
+
+ public ConfigurationException(String msg, Throwable t)
+ {
+ super(msg, t);
+ }
+}
diff --git a/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/DuplicateValueException.java b/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/DuplicateValueException.java
new file mode 100644
index 000000000..43f4fe53e
--- /dev/null
+++ b/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/DuplicateValueException.java
@@ -0,0 +1,45 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.sli;
+
+public class DuplicateValueException extends SvcLogicException {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1L;
+
+ public DuplicateValueException()
+ {
+ super();
+ }
+
+ public DuplicateValueException(String message)
+ {
+ super(message);
+ }
+
+ public DuplicateValueException(String message, Throwable t)
+ {
+ super(message, t);
+ }
+}
diff --git a/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/ErrorLogger.java b/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/ErrorLogger.java
new file mode 100644
index 000000000..47f6526e9
--- /dev/null
+++ b/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/ErrorLogger.java
@@ -0,0 +1,100 @@
+package org.onap.ccsdk.sli.core.sli;
+
+import org.onap.logging.ref.slf4j.ONAPLogConstants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.slf4j.MDC;
+
+public class ErrorLogger {
+ public static final int ERROR_CODE_100 = 100;
+ public static final int ERROR_CODE_200 = 200;
+ public static final int ERROR_CODE_300 = 300;
+ public static final int ERROR_CODE_400 = 400;
+ public static final int ERROR_CODE_500 = 500;
+ public static final int ERROR_CODE_900 = 900;
+
+ private static final String DEFAULT_100_DESCRIPTION = "Permission Error";
+ private static final String DEFAULT_200_DESCRIPTION = "Availability Error or Timeout";
+ private static final String DEFAULT_300_DESCRIPTION = "Data Error";
+ private static final String DEFAULT_400_DESCRIPTION = "Schema Error";
+ private static final String DEFAULT_500_DESCRIPTION = "Business Process Error";
+ private static final String DEFAULT_900_DESCRIPTION = "Unknown Error";
+ private Logger log;
+
+ public ErrorLogger() {
+ this.log = LoggerFactory.getLogger(ErrorLogger.class);
+ }
+
+ public ErrorLogger(Logger log) {
+ this.log = log;
+ }
+
+ public void logError(String message, int errorCode) {
+ createLogEntry(message, errorCode, null, null);
+ }
+
+ public void logError(String message, int errorCode, Exception e) {
+ createLogEntry(message, errorCode, null, e);
+ }
+
+ public void logError(String message, int errorCode, String description) {
+ createLogEntry(message, errorCode, description, null);
+ }
+
+ public void logError(String message, int errorCode, String description, Exception e) {
+ createLogEntry(message, errorCode, description, e);
+ }
+
+ public void createLogEntry(String message, int errorCode, String description, Exception e) {
+ //If the error code isn't valid default it to unknown error code
+ if(!isValidCode(errorCode)) {
+ errorCode = 900;
+ }
+
+ MDC.put(ONAPLogConstants.MDCs.ERROR_CODE, String.valueOf(errorCode));
+
+ if (description == null || description.isEmpty()) {
+ description = getDefaultDescription(errorCode);
+ }
+
+ MDC.put(ONAPLogConstants.MDCs.ERROR_DESC, description);
+ if (e != null) {
+ log.error(message, e);
+ } else {
+ log.error(message);
+ }
+ clearKeys();
+ }
+
+ public boolean isValidCode(int errorCode) {
+ if (errorCode == ERROR_CODE_100 || errorCode == ERROR_CODE_200 || errorCode == ERROR_CODE_300 || errorCode == ERROR_CODE_400 || errorCode == ERROR_CODE_500
+ || errorCode == ERROR_CODE_900) {
+ return true;
+ }
+ return false;
+ }
+
+ public String getDefaultDescription(int errorCode) {
+ if (errorCode == ERROR_CODE_100) {
+ return DEFAULT_100_DESCRIPTION;
+ }
+ if (errorCode == ERROR_CODE_200) {
+ return DEFAULT_200_DESCRIPTION;
+ }
+ if (errorCode == ERROR_CODE_300) {
+ return DEFAULT_300_DESCRIPTION;
+ }
+ if (errorCode == ERROR_CODE_400) {
+ return DEFAULT_400_DESCRIPTION;
+ }
+ if (errorCode == ERROR_CODE_500) {
+ return DEFAULT_500_DESCRIPTION;
+ }
+ return DEFAULT_900_DESCRIPTION;
+ }
+
+ public void clearKeys() {
+ MDC.remove(ONAPLogConstants.MDCs.ERROR_CODE);
+ MDC.remove(ONAPLogConstants.MDCs.ERROR_DESC);
+ }
+}
diff --git a/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/ExitNodeException.java b/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/ExitNodeException.java
new file mode 100755
index 000000000..f119c1812
--- /dev/null
+++ b/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/ExitNodeException.java
@@ -0,0 +1,46 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.sli;
+
+public class ExitNodeException extends SvcLogicException {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1L;
+
+ public ExitNodeException()
+ {
+ super();
+ }
+
+ public ExitNodeException(String message)
+ {
+ super(message);
+ }
+
+ public ExitNodeException(String message, Throwable t)
+ {
+ super(message, t);
+ }
+
+}
diff --git a/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/MessageWriter.java b/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/MessageWriter.java
new file mode 100644
index 000000000..5ededb9eb
--- /dev/null
+++ b/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/MessageWriter.java
@@ -0,0 +1,281 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.sli;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.sql.SQLException;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.Properties;
+import javax.sql.rowset.CachedRowSet;
+import org.onap.ccsdk.sli.core.dblib.DbLibService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Deprecated
+public class MessageWriter {
+
+ private static final Logger LOG = LoggerFactory.getLogger(MessageWriter.class);
+
+ private static final String DBLIB_SERVICE = "org.onap.ccsdk.sli.core.dblib.DBResourceManager";
+ private static final String SVCLOGIC_PROP_VAR = "SDNC_SLI_PROPERTIES";
+ private static final String SDNC_CONFIG_DIR = "SDNC_CONFIG_DIR";
+
+ private static final String INCOMING_PROPERTY_NAME = "org.onap.ccsdk.sli.MessageWriter.writeIncomingRequests";
+ private static final String OUTGOING_PROPERTY_NAME = "org.onap.ccsdk.sli.MessageWriter.writeOutgoingRequests";
+
+ private static final SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
+
+ private static DbLibService dbLibService = null;
+
+ private static boolean incomingEnabled = false;
+ private static boolean outgoingEnabled = false;
+
+ private static boolean initialized = false;
+
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ private static void init() {
+ if (initialized)
+ return;
+
+ initialized = true;
+
+ // Read properties
+ Properties props = new Properties();
+ String propPath = System.getenv(SVCLOGIC_PROP_VAR);
+
+ if (propPath == null) {
+ String propDir = System.getenv(SDNC_CONFIG_DIR);
+ if (propDir == null) {
+ propDir = "/opt/sdnc/data/properties";
+ }
+ propPath = propDir + "/svclogic.properties";
+ LOG.warn("Environment variable " + SVCLOGIC_PROP_VAR + " unset - defaulting to " + propPath);
+ }
+
+ File propFile = new File(propPath);
+
+ if (!propFile.exists()) {
+ LOG.warn("Property file does not exist: " + propPath);
+ }
+
+ try {
+ props.load(new FileInputStream(propFile));
+ } catch (Exception e) {
+ LOG.warn("Error loading property file: " + propPath, e);
+ }
+
+ incomingEnabled = Boolean.valueOf(props.getProperty(INCOMING_PROPERTY_NAME, "false"));
+ outgoingEnabled = Boolean.valueOf(props.getProperty(OUTGOING_PROPERTY_NAME, "false"));
+
+ LOG.info(INCOMING_PROPERTY_NAME + ": " + incomingEnabled);
+ LOG.info(OUTGOING_PROPERTY_NAME + ": " + outgoingEnabled);
+ }
+
+ public static void saveOutgoingRequest(
+ String requestId,
+ String serviceInstanceId,
+ String targetUrl,
+ String request) {
+ try {
+ init();
+
+ if (!outgoingEnabled)
+ return;
+
+ if (serviceInstanceId == null || serviceInstanceId.trim().length() == 0)
+ serviceInstanceId = "NA";
+
+ int seqnum = getLastSequenceNumber("OUTGOING_MESSAGE", requestId) + 1;
+ String now = df.format(new Date());
+
+ String sql = "INSERT INTO OUTGOING_MESSAGE (\n" +
+ " request_id, sequence_number, service_instance_id, target_url, request, start_time)\n" +
+ "VALUES (?, ?, ?, ?, ?, ?)";
+
+ ArrayList<String> data = new ArrayList<>();
+ data.add(requestId);
+ data.add(String.valueOf(seqnum));
+ data.add(serviceInstanceId);
+ data.add(targetUrl);
+ data.add(request);
+ data.add(now);
+
+ dbLibService.writeData(sql, data, null);
+
+ } catch (Exception e) {
+ LOG.warn("Failed to save outgoing request for request-id: " + requestId, e);
+ }
+ }
+
+ public static void saveOutgoingResponse(String requestId, int httpResponseCode, String response) {
+ try {
+ init();
+
+ if (!outgoingEnabled)
+ return;
+
+ int seqnum = getLastSequenceNumber("OUTGOING_MESSAGE", requestId);
+ if (seqnum == 0) {
+ LOG.warn("Failed to save outgoing response for request-id: " + requestId +
+ ": Request record not found in OUTGOING_MESSAGE");
+ return;
+ }
+
+ String now = df.format(new Date());
+
+ String sql = "UPDATE OUTGOING_MESSAGE SET http_response_code = ?, response = ?,\n" +
+ " duration = timestampdiff(MICROSECOND, start_time, ?) / 1000\n" +
+ "WHERE request_id = ? AND sequence_number = ?";
+
+ ArrayList<String> data = new ArrayList<>();
+ data.add(String.valueOf(httpResponseCode));
+ data.add(response);
+ data.add(now);
+ data.add(requestId);
+ data.add(String.valueOf(seqnum));
+
+ dbLibService.writeData(sql, data, null);
+
+ } catch (Exception e) {
+ LOG.warn("Failed to save outgoing response for request-id: " + requestId, e);
+ }
+ }
+
+ public static void saveIncomingRequest(
+ String requestId,
+ String serviceInstanceId,
+ String requestHost,
+ String request) {
+ try {
+ init();
+
+ if (!incomingEnabled)
+ return;
+
+ if (serviceInstanceId == null || serviceInstanceId.trim().length() == 0)
+ serviceInstanceId = "NA";
+
+ int seqnum = getLastSequenceNumber("INCOMING_MESSAGE", requestId) + 1;
+ String now = df.format(new Date());
+
+ String sql = "INSERT INTO INCOMING_MESSAGE (\n" +
+ " request_id, sequence_number, service_instance_id, request_host, request, start_time)\n" +
+ "VALUES (?, ?, ?, ?, ?, ?)";
+
+ ArrayList<String> data = new ArrayList<>();
+ data.add(requestId);
+ data.add(String.valueOf(seqnum));
+ data.add(serviceInstanceId);
+ data.add(requestHost);
+ data.add(request);
+ data.add(now);
+
+ dbLibService.writeData(sql, data, null);
+
+ } catch (Exception e) {
+ LOG.warn("Failed to save incoming request for request-id: " + requestId, e);
+ }
+ }
+
+ public static void saveIncomingResponse(String requestId, int httpResponseCode, String response) {
+ try {
+ init();
+
+ if (!incomingEnabled)
+ return;
+
+ int seqnum = getLastSequenceNumber("INCOMING_MESSAGE", requestId);
+ if (seqnum == 0) {
+ LOG.warn("Failed to save response for request-id: " + requestId +
+ ": Request record not found in INCOMING_MESSAGE");
+ return;
+ }
+
+ String now = df.format(new Date());
+
+ String sql = "UPDATE INCOMING_MESSAGE SET http_response_code = ?, response = ?,\n" +
+ " duration = timestampdiff(MICROSECOND, start_time, ?) / 1000\n" +
+ "WHERE request_id = ? AND sequence_number = ?";
+
+ ArrayList<String> data = new ArrayList<>();
+ data.add(String.valueOf(httpResponseCode));
+ data.add(response);
+ data.add(now);
+ data.add(requestId);
+ data.add(String.valueOf(seqnum));
+
+ dbLibService.writeData(sql, data, null);
+
+ } catch (Exception e) {
+ LOG.warn("Failed to save response for request-id: " + requestId, e);
+ }
+ }
+
+ public static String getServiceInstanceId(String requestId) throws SQLException {
+ init();
+
+ String sql = "SELECT service_instance_id FROM OUTGOING_MESSAGE WHERE request_id = '" + requestId +
+ "' ORDER BY sequence_number DESC";
+
+ CachedRowSet rs = null;
+ try {
+ rs = dbLibService.getData(sql, null, null);
+ if (rs.next()) {
+ return rs.getString("service_instance_id");
+ }
+ } finally {
+ if (rs != null) {
+ try {
+ rs.close();
+ } catch (Exception e) {
+ LOG.warn("Failed to close CachedRowSet", e);
+ }
+ }
+ }
+ return null;
+ }
+
+ private static int getLastSequenceNumber(String tableName, String requestId) throws SQLException {
+ String sql = "SELECT sequence_number FROM " + tableName + " WHERE request_id = '" + requestId +
+ "' ORDER BY sequence_number DESC";
+
+ CachedRowSet rs = null;
+ try {
+ rs = dbLibService.getData(sql, null, null);
+ if (rs.next()) {
+ return rs.getInt("sequence_number");
+ }
+ } finally {
+ if (rs != null) {
+ try {
+ rs.close();
+ } catch (Exception e) {
+ LOG.warn("Failed to close CachedRowSet", e);
+ }
+ }
+ }
+ return 0;
+ }
+}
diff --git a/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/MetricLogger.java b/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/MetricLogger.java
new file mode 100755
index 000000000..577b73401
--- /dev/null
+++ b/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/MetricLogger.java
@@ -0,0 +1,165 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+/**
+ *
+ */
+package org.onap.ccsdk.sli.core.sli;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.time.ZoneOffset;
+import java.time.ZonedDateTime;
+import java.time.format.DateTimeFormatter;
+import java.time.temporal.ChronoUnit;
+import java.util.Date;
+import java.util.TimeZone;
+import java.util.UUID;
+
+import org.onap.logging.ref.slf4j.ONAPLogConstants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.slf4j.MDC;
+import org.slf4j.Marker;
+import org.slf4j.MarkerFactory;
+
+/**
+ * @author dt5972
+ *
+ */
+public class MetricLogger {
+
+ private static final Logger METRIC = LoggerFactory.getLogger("org.onap.ccsdk.sli.core.filters.metric");
+ private static final Marker INVOKE_RETURN = MarkerFactory.getMarker("INVOKE-RETURN");
+ private static final Marker INVOKE = MarkerFactory.getMarker("INVOKE");
+
+ private String lastMsg = null;
+
+ public String getRequestID() {
+ return MDC.get(ONAPLogConstants.MDCs.REQUEST_ID);
+ }
+
+ public MetricLogger() {
+
+ }
+
+ @Deprecated
+ public static String asIso8601(Date date) {
+ TimeZone tz = TimeZone.getTimeZone("UTC");
+ DateFormat df = new SimpleDateFormat("yyy-MM-dd'T'HH:mm:ss.SS'+00:00'");
+ df.setTimeZone(tz);
+ return df.format(date);
+ }
+
+ @Deprecated
+ public static String asIso8601(long tsInMillis) {
+ return MetricLogger.asIso8601(new Date(tsInMillis));
+ }
+
+ @Deprecated
+ public void logRequest(String svcInstanceId, String svcName, String partnerName, String targetEntity,
+ String targetServiceName, String targetElement, String msg) {
+ logRequest(svcInstanceId, targetEntity, targetServiceName, targetElement, msg);
+ }
+
+ public void logRequest(String svcInstanceId, String targetEntity, String targetServiceName, String targetElement,
+ String msg) {
+ String timeNow = ZonedDateTime.now(ZoneOffset.UTC).format(DateTimeFormatter.ISO_INSTANT);
+ MDC.put(ONAPLogConstants.MDCs.INVOKE_TIMESTAMP, timeNow);
+
+ // If transaction is initialized by an external client this will already be set by the audit servlet filter
+ // If the transaction is initialized by CCSDK this code will handle generating a new UUID
+ String requestId = MDC.get(ONAPLogConstants.MDCs.REQUEST_ID);
+ if (requestId == null || requestId.isEmpty()) {
+ MDC.put(ONAPLogConstants.MDCs.REQUEST_ID, UUID.randomUUID().toString());
+ }
+
+ String randomInvocationId = UUID.randomUUID().toString();
+ MDC.put(ONAPLogConstants.MDCs.INVOCATION_ID, randomInvocationId);
+ MDC.put(ONAPLogConstants.MDCs.CLIENT_INVOCATION_ID, randomInvocationId);
+
+ if (svcInstanceId != null) {
+ MDC.put(ONAPLogConstants.MDCs.SERVICE_INSTANCE_ID, svcInstanceId);
+ }
+ if (targetEntity != null) {
+ MDC.put(ONAPLogConstants.MDCs.TARGET_ENTITY, targetEntity);
+ }
+
+ if (targetServiceName != null) {
+ MDC.put(ONAPLogConstants.MDCs.TARGET_SERVICE_NAME, targetServiceName);
+ }
+
+ if (targetElement != null) {
+ MDC.put(ONAPLogConstants.MDCs.TARGET_ELEMENT, targetElement);
+ }
+ this.lastMsg = msg;
+ //During invoke status will always be INPROGRESS
+ MDC.put(ONAPLogConstants.MDCs.RESPONSE_STATUS_CODE, ONAPLogConstants.ResponseStatus.INPROGRESS.toString());
+ MDC.put(ONAPLogConstants.MDCs.ELAPSED_TIME, "0");
+ METRIC.info(INVOKE, "Invoke");
+ }
+
+ public void logResponse(String statusCode, String responseCode, String responseDescription) {
+ if (statusCode != null) {
+ MDC.put(ONAPLogConstants.MDCs.RESPONSE_STATUS_CODE, statusCode);
+ }
+ if (responseCode != null) {
+ MDC.put(ONAPLogConstants.MDCs.RESPONSE_CODE, responseCode);
+ }
+ if (responseDescription != null) {
+ MDC.put(ONAPLogConstants.MDCs.RESPONSE_DESCRIPTION, formatString(responseDescription));
+ }
+ ZonedDateTime endTime = ZonedDateTime.now(ZoneOffset.UTC);
+ MDC.put(ONAPLogConstants.MDCs.LOG_TIMESTAMP, endTime.format(DateTimeFormatter.ISO_INSTANT));
+ try {
+ DateTimeFormatter timeFormatter = DateTimeFormatter.ISO_ZONED_DATE_TIME;
+ ZonedDateTime entryTimestamp =
+ ZonedDateTime.parse(MDC.get(ONAPLogConstants.MDCs.INVOKE_TIMESTAMP), timeFormatter);
+ String elapedTime = Long.toString(ChronoUnit.MILLIS.between(entryTimestamp, endTime));
+ MDC.put(ONAPLogConstants.MDCs.ELAPSED_TIME,elapedTime);
+ } catch (Exception e) {
+ //pass
+ }
+ METRIC.info(INVOKE_RETURN, formatString(lastMsg));
+ resetContext();
+ }
+
+ protected String formatString(String str) {
+ if (str != null) {
+ str = str.replaceAll("\\R", ""); // this will strip all new line characters
+ str = str.replaceAll("\\|", "%7C"); // log records should not contain a pipe, encode the pipe character
+ str = str.replaceAll("\t", " "); // tabs are not allowed, replace with spaces
+ str = str.replace(",", "\\,"); // comma must be escaped
+ }
+ return str;
+ }
+
+ public static void resetContext() {
+ MDC.remove(ONAPLogConstants.MDCs.TARGET_ENTITY);
+ MDC.remove(ONAPLogConstants.MDCs.TARGET_SERVICE_NAME);
+ MDC.remove(ONAPLogConstants.MDCs.TARGET_ELEMENT);
+ MDC.remove(ONAPLogConstants.MDCs.RESPONSE_STATUS_CODE);
+ MDC.remove(ONAPLogConstants.MDCs.RESPONSE_CODE);
+ MDC.remove(ONAPLogConstants.MDCs.RESPONSE_DESCRIPTION);
+ MDC.remove(ONAPLogConstants.MDCs.ELAPSED_TIME);
+ }
+
+}
diff --git a/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SecurePrinter.java b/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SecurePrinter.java
new file mode 100644
index 000000000..e25aed9f8
--- /dev/null
+++ b/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SecurePrinter.java
@@ -0,0 +1,123 @@
+
+package org.onap.ccsdk.sli.core.sli;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.PrintStream;
+import java.util.HashMap;
+import java.util.Map.Entry;
+import java.util.Properties;
+import java.util.TreeMap;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class SecurePrinter {
+ private static final Logger LOG = LoggerFactory.getLogger(SecurePrinter.class);
+ private static final String DEFAULT_FILTER = "password,pass,pswd";
+ private static final String REDACTED = "***REDACTED***";
+ private static final String FILTER_PROPERTY = "NODE_STRING_FILTER";
+ private static final String SEPERATOR = " = ";
+ private static final String COMMON_ERROR_MESSAGE = "Failed to print properties";
+
+ private static String[] filterArray;
+
+ public SecurePrinter() {
+ String filterProperty = System.getProperty(FILTER_PROPERTY);
+ if (filterProperty != null && !filterProperty.isEmpty() && filterProperty.contains(",")) {
+ filterArray = filterProperty.split(",");
+ } else {
+ filterArray = DEFAULT_FILTER.split(",");
+ }
+ }
+
+ private String filterValue(String key, String value) {
+ String normalizedKey = key.toLowerCase();
+ for (String restrictedKey : filterArray) {
+ if (normalizedKey.contains(restrictedKey)) {
+ return REDACTED;
+ }
+ }
+ return value;
+ }
+
+ public void printAttributes(HashMap<String, String> attributes) {
+ if (LOG.isDebugEnabled()) {
+ for (Entry<String, String> attribute : attributes.entrySet()) {
+ String value = filterValue(attribute.getKey(), attribute.getValue());
+ LOG.debug(attribute.getKey() + SEPERATOR + value);
+ }
+ }
+ }
+
+ public void printAttributes(HashMap<String, String> attributes, String subpath) {
+ if (LOG.isDebugEnabled()) {
+ for (Entry<String, String> attribute : attributes.entrySet()) {
+ if (attribute.getKey().startsWith(subpath)) {
+ String value = filterValue(attribute.getKey(), attribute.getValue());
+ LOG.debug(attribute.getKey() + SEPERATOR + value);
+ }
+ }
+ }
+ }
+
+ public void printProperties(Properties props) {
+ if (LOG.isDebugEnabled()) {
+ try {
+ for (Entry<Object, Object> property : props.entrySet()) {
+ String keyString = (String) property.getKey();
+ String valueString = (String) property.getValue();
+ String value = filterValue(keyString, valueString);
+ LOG.debug(keyString + SEPERATOR + value);
+ }
+ } catch (Exception e) {
+ LOG.error(COMMON_ERROR_MESSAGE, e);
+ }
+ }
+ }
+
+ public void printProperties(Properties props, String subpath) {
+ if (LOG.isDebugEnabled()) {
+ try {
+ for (Entry<Object, Object> property : props.entrySet()) {
+ String keyString = (String) property.getKey();
+ if (keyString.startsWith(subpath)) {
+ String valueString = (String) property.getValue();
+ String value = filterValue(keyString, valueString);
+ LOG.debug(keyString + SEPERATOR + value);
+ }
+ }
+ } catch (Exception e) {
+ LOG.error(COMMON_ERROR_MESSAGE, e);
+ }
+ }
+ }
+
+ public void printPropertiesAlphabetically(Properties props) {
+ if (LOG.isDebugEnabled()) {
+ TreeMap<String, String> sortedMap = new TreeMap(props);
+ try {
+ for (Entry<String, String> entry : sortedMap.entrySet()) {
+ String value = filterValue(entry.getKey(), entry.getValue());
+ LOG.debug(entry.getKey() + SEPERATOR + value);
+ }
+ } catch (Exception e) {
+ LOG.error(COMMON_ERROR_MESSAGE, e);
+ }
+ }
+ }
+
+ public void printAttributesToFile(HashMap<String, String> attributes, String fileName) {
+ try (FileOutputStream fstr = new FileOutputStream(new File(fileName));
+ PrintStream pstr = new PrintStream(fstr, true);) {
+ pstr.println("#######################################");
+ for (Entry<String, String> entry : attributes.entrySet()) {
+ String value = filterValue(entry.getKey(), entry.getValue());
+ pstr.println(entry.getKey() + SEPERATOR + value);
+ }
+ } catch (Exception e) {
+ LOG.error("Cannot write context to file.", e);
+ }
+ }
+
+} \ No newline at end of file
diff --git a/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicAdaptor.java b/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicAdaptor.java
new file mode 100644
index 000000000..a76b123ca
--- /dev/null
+++ b/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicAdaptor.java
@@ -0,0 +1,42 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.sli;
+
+import java.util.Map;
+
+public interface SvcLogicAdaptor {
+
+ public enum ConfigStatus {
+ SUCCESS,
+ ALREADY_ACTIVE,
+ NOT_FOUND,
+ NOT_READY,
+ FAILURE
+ }
+
+ public ConfigStatus configure(String key, Map<String,String> parameters, SvcLogicContext ctx);
+
+ public ConfigStatus activate(String key, SvcLogicContext ctx);
+
+ public ConfigStatus deactivate(String key, SvcLogicContext ctx);
+
+}
diff --git a/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicAtom.java b/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicAtom.java
new file mode 100644
index 000000000..b9ad19e25
--- /dev/null
+++ b/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicAtom.java
@@ -0,0 +1,170 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.sli;
+
+public class SvcLogicAtom extends SvcLogicExpression {
+
+ public enum AtomType {
+ NUMBER,
+ STRING,
+ IDENTIFIER,
+ CONTEXT_VAR
+
+ }
+
+ private AtomType atomType;
+ private String atom;
+
+
+ public SvcLogicAtom(String atomType, String atom)
+ {
+ this.atomType = AtomType.valueOf(atomType);
+ this.atom = atom;
+
+ }
+
+ public SvcLogicAtom(String atom)
+ {
+
+ if (atom == null)
+ {
+ this.atomType = null;
+ this.atom = null;
+ }
+ else
+ {
+ if (atom.startsWith("$"))
+ {
+ this.atomType = AtomType.CONTEXT_VAR;
+ this.atom = atom.substring(1);
+ }
+ else
+ {
+ if (Character.isDigit(atom.charAt(0)))
+ {
+ this.atomType = AtomType.NUMBER;
+ this.atom = atom;
+ }
+ else if (atom.charAt(0) == '\'')
+ {
+ this.atomType = AtomType.STRING;
+ this.atom = atom.substring(1, atom.length()-1);
+ }
+ else
+ {
+ this.atomType = AtomType.IDENTIFIER;
+ this.atom = atom;
+
+ }
+
+ }
+ }
+ }
+
+ public AtomType getAtomType() {
+ return atomType;
+ }
+
+ public void setAtomType(String newType)
+ {
+ atomType = AtomType.valueOf(newType);
+ }
+
+ public String getAtom() {
+ return atom;
+ }
+
+
+
+ public void setAtomType(AtomType atomType) {
+ this.atomType = atomType;
+ }
+
+ public void setAtom(String atom) {
+ this.atom = atom;
+ }
+
+
+
+ public String toString()
+ {
+ StringBuffer sbuff = new StringBuffer();
+ switch(getAtomType())
+ {
+ case CONTEXT_VAR:
+ sbuff.append("$");
+ case IDENTIFIER:
+ boolean needDot = false;
+ for (SvcLogicExpression term: this.getOperands())
+ {
+ if (needDot)
+ {
+ sbuff.append(".");
+ }
+ sbuff.append(term.toString());
+ needDot = true;
+ }
+ return sbuff.toString();
+ case STRING:
+ case NUMBER:
+ default:
+ return atom;
+ }
+ }
+
+ public String asParsedExpr()
+ {
+ // simplify debugging output for NUMBER type
+ if (atomType == AtomType.NUMBER) {
+ return atom;
+ }
+
+ StringBuffer sbuff = new StringBuffer();
+
+ sbuff.append("(atom");
+ sbuff.append("<");
+ sbuff.append(atomType.toString());
+ sbuff.append(">");
+
+ switch(atomType)
+ {
+ case IDENTIFIER:
+ case CONTEXT_VAR:
+ for (SvcLogicExpression term : getOperands())
+ {
+ sbuff.append(" ");
+ sbuff.append(term.asParsedExpr());
+
+ }
+ break;
+ default:
+ sbuff.append(" ");
+ sbuff.append(atom);
+ }
+
+ sbuff.append(")");
+ return sbuff.toString();
+ }
+
+
+
+}
diff --git a/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicBinaryExpression.java b/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicBinaryExpression.java
new file mode 100644
index 000000000..a990dd950
--- /dev/null
+++ b/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicBinaryExpression.java
@@ -0,0 +1,151 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Modifications Copyright (C) 2018 IBM.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.sli;
+
+import java.util.LinkedList;
+import java.util.List;
+
+public class SvcLogicBinaryExpression extends SvcLogicExpression {
+
+
+ public enum OperatorType {
+ addOp("+"),
+ subOp("-"),
+ multOp("*"),
+ divOp("/"),
+ equalOp("=="),
+ ltOp("<"),
+ leOp("<="),
+ gtOp(">"),
+ geOp(">="),
+ neOp("!="),
+ andOp("and"),
+ orOp("or");
+
+ private String text;
+
+ private OperatorType(String text)
+ {
+ this.text = text;
+ }
+
+ public String getText()
+ {
+ return(text);
+ }
+
+ public static OperatorType fromString(String text)
+ {
+ if (text != null)
+ {
+ for (OperatorType t : OperatorType.values())
+ {
+ if (text.equalsIgnoreCase(t.getText())) {
+
+ return(t);
+ }
+ }
+ }
+ return(null);
+ }
+
+ public String toString()
+ {
+ return(text);
+ }
+ }
+ private List<OperatorType> operators;
+
+ public List<OperatorType> getOperators() {
+ return operators;
+ }
+
+ public SvcLogicBinaryExpression()
+ {
+ operators = new LinkedList<>();
+ }
+
+ public void addOperator(String operator)
+ {
+ operators.add(OperatorType.fromString(operator));
+ }
+
+
+ public String toString()
+ {
+
+ List<SvcLogicExpression>operands = getOperands();
+ StringBuffer sbuff = new StringBuffer();
+
+ sbuff.append(operands.get(0).toString());
+ for (int i = 0 ; i < operators.size(); i++)
+ {
+ sbuff.append(" ");
+ sbuff.append(operators.get(i));
+ sbuff.append(" ");
+ if (i + 1 < operands.size()) {
+ sbuff.append(operands.get(i + 1).toString());
+ } else {
+ // expression incomplete; operand not bound yet
+ sbuff.append("?");
+ }
+ }
+
+ return(sbuff.toString());
+
+ }
+
+ public String asParsedExpr() {
+
+ List<SvcLogicExpression> operands = getOperands();
+
+ if (operators.isEmpty()) {
+ return operands.get(0).asParsedExpr();
+ } else {
+ StringBuffer sbuff = new StringBuffer();
+ // operators in reverse order for left associativity
+ for (int i = operators.size() - 1; i >= 0; --i) {
+ sbuff.append("(");
+ sbuff.append(operators.get(i).getText());
+ sbuff.append(" ");
+ }
+ for (int i = 0; i < operators.size() + 1; ++i) {
+ if (i < operands.size()) {
+ sbuff.append(operands.get(i).asParsedExpr());
+ } else {
+ // expression incomplete; operand not bound yet
+ sbuff.append("?");
+ }
+ if (i != 0) {
+ sbuff.append(")");
+ }
+ if (i < operators.size()) {
+ sbuff.append(" ");
+ }
+ }
+ return sbuff.toString();
+ }
+ }
+
+}
diff --git a/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicConstants.java b/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicConstants.java
new file mode 100644
index 000000000..61bfe7c20
--- /dev/null
+++ b/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicConstants.java
@@ -0,0 +1,7 @@
+package org.onap.ccsdk.sli.core.sli;
+
+public class SvcLogicConstants {
+ public final static String SUCCESS = "success";
+ public final static String FAILURE = "failure";
+
+}
diff --git a/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicContext.java b/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicContext.java
new file mode 100644
index 000000000..98cf7e05e
--- /dev/null
+++ b/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicContext.java
@@ -0,0 +1,438 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.sli;
+
+import java.util.*;
+
+import com.google.gson.*;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Text;
+
+
+public class SvcLogicContext {
+
+ private static final Logger LOG = LoggerFactory.getLogger(SvcLogicContext.class);
+ private final SecurePrinter securePrinter = new SecurePrinter();
+ public static final String CTX_NULL_VALUE="";
+ private static final String LENGTH="_length";
+
+ private HashMap<String, String> attributes;
+
+ private String status = SvcLogicConstants.SUCCESS;
+
+ public SvcLogicContext() {
+ this.attributes = new HashMap<>();
+
+ }
+
+ public SvcLogicContext(Properties props) {
+ this.attributes = new HashMap<>();
+
+ if (props.containsKey(CommonConstants.SERVICE_LOGIC_STATUS)) {
+ this.status = props.getProperty(CommonConstants.SERVICE_LOGIC_STATUS);
+ }
+
+ for (Object nameObj : props.keySet()) {
+ String propName = (String) nameObj;
+ attributes.put(propName, props.getProperty(propName));
+ }
+ }
+
+ public String getAttribute(String name) {
+ if (attributes.containsKey(name)) {
+ return attributes.get(name);
+ } else {
+ return null;
+ }
+ }
+
+ public void setAttribute(String name, String value) {
+ if (value == null) {
+ if (attributes.containsKey(name)) {
+ attributes.remove(name);
+ }
+ } else {
+ attributes.put(name, value);
+ }
+ }
+
+ public Set<String> getAttributeKeySet() {
+ return attributes.keySet();
+ }
+
+ public Boolean isSuccess() {
+ return status.equals(SvcLogicConstants.SUCCESS);
+ }
+
+ @Deprecated
+ public String getStatus() {
+ return status;
+ }
+
+ @Deprecated
+ public void setStatus(String status) {
+ this.status = status;
+ }
+
+ public void markFailed() {
+ this.status = SvcLogicConstants.FAILURE;
+ }
+
+ public void markSuccess() {
+ this.status = SvcLogicConstants.SUCCESS;
+ }
+
+ public Properties toProperties() {
+ Properties props = new Properties();
+
+ if (status != null) {
+ props.setProperty(CommonConstants.SERVICE_LOGIC_STATUS, status);
+ }
+
+ String attrName;
+ String attrVal;
+ for (Map.Entry<String, String> entry : attributes.entrySet()) {
+ attrName = entry.getKey();
+ attrVal = entry.getValue();
+ if (attrVal == null) {
+ LOG.warn("attribute {} value is null - setting to empty string", attrName);
+ props.setProperty(attrName, "");
+ } else {
+ props.setProperty(attrName, attrVal);
+ }
+ }
+
+ return props;
+ }
+
+ public void mergeDocument(String pfx, Document doc) {
+ String prefix = "";
+
+ if (pfx != null) {
+ prefix = pfx;
+ }
+
+ Element root = doc.getDocumentElement();
+
+ mergeElement(prefix, root, null);
+ }
+
+ public void mergeElement(String pfx, Element element, Map<String, Integer> nodeMap) {
+
+ // In XML, cannot tell the difference between containers and lists.
+ // So, have to treat each element as both (ugly but necessary).
+ // We do this by passing a nodeMap to be used to count instance of each tag,
+ // which will be used to set _length and to set index
+
+ LOG.trace("mergeElement({},{},{})", pfx, element.getTagName(), nodeMap);
+
+ String curTagName = element.getTagName();
+ String prefix = curTagName;
+
+ if (pfx != null) {
+ prefix = pfx + "." + prefix;
+ }
+
+ int myIdx = 0;
+
+ if (nodeMap != null) {
+ if (nodeMap.containsKey(curTagName)) {
+ myIdx = nodeMap.get(curTagName);
+ }
+
+ nodeMap.put(curTagName, myIdx + 1);
+ this.setAttribute(prefix + "_length", Integer.toString(myIdx + 1));
+ }
+
+ NodeList children = element.getChildNodes();
+
+ int numChildren = children.getLength();
+
+ Map<String, Integer> childMap = new HashMap<>();
+ Map<String, Integer> idxChildMap = new HashMap<>();
+
+ for (int i = 0; i < numChildren; i++) {
+ Node curNode = children.item(i);
+
+ if (curNode instanceof Text) {
+ Text curText = (Text) curNode;
+ String curTextValue = curText.getTextContent();
+ LOG.trace("Setting ctx variable {} = {}", prefix, curTextValue);
+ this.setAttribute(prefix, curText.getTextContent());
+
+
+ } else if (curNode instanceof Element) {
+ mergeElement(prefix, (Element) curNode, childMap);
+ if (nodeMap != null) {
+
+ mergeElement(prefix + "[" + myIdx + "]", (Element) curNode, idxChildMap);
+
+ }
+ }
+ }
+
+ }
+
+ public void mergeJson(String pfx, String jsonString) {
+
+ JsonParser jp = new JsonParser();
+ JsonElement element = jp.parse(jsonString);
+ String root = "";
+ if ((pfx != null) && (pfx.length() > 0)) {
+ root = pfx + ".";
+ }
+ if (element.isJsonObject()) {
+ writeJsonObject(element.getAsJsonObject(), root);
+ } else if (element.isJsonArray()) {
+ handleJsonArray("", element.getAsJsonArray(), root);
+ }
+ }
+
+
+ protected void writeJsonObject(JsonObject obj, String root) {
+ for (Map.Entry<String, JsonElement> entry : obj.entrySet()) {
+ String key = entry.getKey();
+ if (entry.getValue().isJsonObject()) {
+ writeJsonObject(entry.getValue().getAsJsonObject(), root + key + ".");
+ } else if (entry.getValue().isJsonArray()) {
+ JsonArray array = entry.getValue().getAsJsonArray();
+ handleJsonArray(key, array, root);
+ } else {
+ //Handles when a JSON obj is nested within a JSON obj
+ if(!root.endsWith(".")){
+ root = root + ".";
+ }
+ if(entry.getValue().isJsonNull()) {
+ this.setAttribute(root + key, CTX_NULL_VALUE);
+ }else {
+ this.setAttribute(root + key, entry.getValue().getAsString());
+ }
+ }
+ }
+ }
+
+ protected void handleJsonArray(String key, JsonArray array, String root) {
+ this.setAttribute(root + key + LENGTH, String.valueOf(array.size()));
+ Integer arrayIdx = 0;
+ for (JsonElement element : array) {
+ String prefix = root + key + "[" + arrayIdx + "]";
+
+ if (element.isJsonArray()) {
+ handleJsonArray(key, element.getAsJsonArray(), prefix);
+ } else if (element.isJsonObject()) {
+ writeJsonObject(element.getAsJsonObject(), prefix + ".");
+ } else if (element.isJsonNull()) {
+ this.setAttribute(prefix, CTX_NULL_VALUE);
+ } else if (element.isJsonPrimitive()) {
+ this.setAttribute(prefix, element.getAsString());
+ }
+ arrayIdx++;
+ }
+ }
+
+
+ public String resolve(String ctxVarName) {
+
+ if (ctxVarName.indexOf('[') == -1) {
+ // Ctx variable contains no arrays
+ return getAttribute(ctxVarName);
+ }
+
+ // Resolve any array references
+ StringBuilder sbuff = new StringBuilder();
+ String[] ctxVarParts = ctxVarName.split("\\[");
+ sbuff.append(ctxVarParts[0]);
+ for (int i = 1; i < ctxVarParts.length; i++) {
+ if (ctxVarParts[i].startsWith("$")) {
+ int endBracketLoc = ctxVarParts[i].indexOf(']');
+ if (endBracketLoc == -1) {
+ // Missing end bracket ... give up parsing
+ LOG.warn("Variable reference {} seems to be missing a ']'", ctxVarName);
+ return getAttribute(ctxVarName);
+ }
+
+ String idxVarName = ctxVarParts[i].substring(1, endBracketLoc);
+ String remainder = ctxVarParts[i].substring(endBracketLoc);
+
+ sbuff.append("[");
+ sbuff.append(this.getAttribute(idxVarName));
+ sbuff.append(remainder);
+
+ } else {
+ // Index is not a variable reference
+ sbuff.append("[");
+ sbuff.append(ctxVarParts[i]);
+ }
+ }
+
+ return getAttribute(sbuff.toString());
+ }
+
+ public String toJsonString(String pfx) {
+ JsonParser jp = new JsonParser();
+
+ String jsonString = this.toJsonString();
+ JsonObject jsonRoot = (JsonObject) jp.parse(jsonString);
+ JsonObject targetJson = jsonRoot.getAsJsonObject(pfx);
+ if (targetJson == null) {
+ return("");
+ } else {
+ return(targetJson.toString());
+ }
+ }
+
+ public String toJsonString() {
+ JsonObject root = new JsonObject();
+ JsonElement lastJsonObject = root;
+ JsonElement currJsonLeaf = root;
+
+ String attrName = null;
+ String attrVal = null;
+
+ // Sort properties so that arrays will be reconstructed in proper order
+ TreeMap<String, String> sortedAttributes = new TreeMap<>();
+ sortedAttributes.putAll(attributes);
+
+ // Loop through properties, sorted by key
+ for (Map.Entry<String, String> entry : sortedAttributes.entrySet()) {
+ attrName = entry.getKey();
+ attrVal = entry.getValue();
+
+ currJsonLeaf = root;
+ String curFieldName = null;
+ JsonArray curArray = null;
+ lastJsonObject = null;
+ boolean addNeeded = false;
+
+ // Split property names by period and iterate through parts
+ for (String attrNamePart : attrName.split("\\.")) {
+
+ // Add last object found to JSON tree. Need to handle
+ // this way because last element found (leaf) needs to be
+ // assigned the property value.
+ if (lastJsonObject != null) {
+ if (addNeeded) {
+ if (currJsonLeaf.isJsonArray()) {
+ ((JsonArray) currJsonLeaf).add(lastJsonObject);
+ } else {
+ ((JsonObject) currJsonLeaf).add(curFieldName, lastJsonObject);
+ }
+ }
+ currJsonLeaf = (JsonObject) lastJsonObject;
+ }
+ addNeeded = false;
+ // See if current level should be a JsonArray or JsonObject based on
+ // whether name part contains square brackets.
+ if (!attrNamePart.contains("[")) {
+ // This level should be inserted as a JsonObject
+ curFieldName = attrNamePart;
+ lastJsonObject = ((JsonObject) currJsonLeaf).get(curFieldName);
+ if (lastJsonObject == null) {
+ lastJsonObject = new JsonObject();
+ addNeeded = true;
+ } else if (!lastJsonObject.isJsonObject()) {
+ LOG.error("Unexpected condition - expecting to find JsonObject, but found " + lastJsonObject.getClass().getName());
+ lastJsonObject = new JsonObject();
+ addNeeded = true;
+ }
+ } else {
+ // This level should be inserted as a JsonArray.
+
+ String[] curFieldNameParts = attrNamePart.split("[\\[\\]]");
+ curFieldName = curFieldNameParts[0];
+ int curIndex = Integer.parseInt(curFieldNameParts[1]);
+
+
+ curArray = ((JsonObject) currJsonLeaf).getAsJsonArray(curFieldName);
+
+ if (curArray == null) {
+ // This is the first time we see this array.
+ // Create a new JsonArray and add it to current
+ // leaf
+ curArray = new JsonArray();
+ ((JsonObject) currJsonLeaf).add(curFieldName, curArray);
+ }
+
+ // Current leaf should point to the JsonArray for this level.
+ // lastJsonObject should point to the array item entry to append
+ // the next level to - which is a new one if the index value
+ // isn't the end of the current array.
+ currJsonLeaf = curArray;
+ if (curArray.size() == curIndex + 1) {
+ lastJsonObject = curArray.get(curArray.size() - 1);
+ } else {
+ lastJsonObject = new JsonObject();
+ addNeeded = true;
+ }
+ }
+ }
+
+ // Done parsing property name. Add the value of this
+ // property to the current json leaf, either as a property
+ // or as a string (if the current leaf is a JsonArray)
+
+ if (!curFieldName.endsWith("_length")) {
+ if (currJsonLeaf.isJsonArray()) {
+ if ("true".equals(attrVal) || "false".equals(attrVal)) {
+ ((JsonArray) currJsonLeaf).add(Boolean.valueOf(attrVal));
+ } else if ("null".equals(attrVal)) {
+ ((JsonArray) currJsonLeaf).add(new JsonNull());
+ } else {
+ ((JsonArray) currJsonLeaf).add(attrVal);
+ }
+ } else {
+ if (("true".equals(attrVal) || "false".equals(attrVal))) {
+ ((JsonObject) currJsonLeaf).addProperty(curFieldName, Boolean.valueOf(attrVal));
+ } else if ("null".equals(attrVal)){
+
+ ((JsonObject) currJsonLeaf).add(curFieldName, new JsonNull());
+ } else {
+ ((JsonObject) currJsonLeaf).addProperty(curFieldName, attrVal);
+ }
+ }
+ }
+ }
+
+ return (root.toString());
+ }
+
+ public void printProperties(Properties props) {
+ securePrinter.printProperties(props);
+ }
+
+ public void printAttributes() {
+ securePrinter.printAttributes(attributes);
+ }
+
+ public void printProperties(Properties props, String subpath) {
+ securePrinter.printProperties(props, subpath);
+ }
+
+ public void printAttributes(String subpath) {
+ securePrinter.printAttributes(attributes, subpath);
+ }
+}
diff --git a/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicCrawler.java b/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicCrawler.java
new file mode 100644
index 000000000..c6fd8b6a2
--- /dev/null
+++ b/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicCrawler.java
@@ -0,0 +1,92 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Modifications Copyright (C) 2018 IBM.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.sli;
+
+import static java.nio.file.FileVisitResult.CONTINUE;
+
+import java.io.IOException;
+import java.nio.file.FileVisitResult;
+import java.nio.file.Path;
+import java.nio.file.SimpleFileVisitor;
+import java.nio.file.attribute.BasicFileAttributes;
+import java.util.ArrayList;
+import java.util.List;
+
+public class SvcLogicCrawler extends SimpleFileVisitor<Path> {
+
+ private List<Path> xmlGraphPathList;
+ private List<Path> activationFilePathList;
+
+ public SvcLogicCrawler() {
+ xmlGraphPathList = new ArrayList<>();
+ activationFilePathList = new ArrayList<>();
+ }
+
+ @Override
+ public FileVisitResult visitFile(Path file, BasicFileAttributes attr) {
+ if (attr.isRegularFile()) {
+ String fileName = file.getFileName().toString();
+ if (!file.toString().contains(".git") && !fileName.equals("pom.xml") && !fileName.equals("assemble_zip.xml") && !fileName.equals("assemble_zip_less_config.xml") && !fileName.equals("descriptor.xml")) {
+ if (fileName.endsWith(".xml")) {
+ xmlGraphPathList.add(file);
+ }
+ else if (fileName.endsWith(".versions")) {
+ activationFilePathList.add(file);
+ }
+ }
+ }
+ return CONTINUE;
+ }
+
+ @Override
+ public FileVisitResult postVisitDirectory(Path dir, IOException exc) {
+ return CONTINUE;
+ }
+
+ @Override
+ public FileVisitResult visitFileFailed(Path file, IOException exc) {
+ System.err.println("Couldn't visitFile");
+ System.err.println(exc.getMessage());
+ return CONTINUE;
+ }
+
+ @Override
+ public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
+ String[] skipDirectories = {".git"};
+ for (String str : skipDirectories) {
+ if (dir.endsWith(str)) {
+ return FileVisitResult.SKIP_SUBTREE;
+ }
+ }
+ return CONTINUE;
+ }
+
+ public List<Path> getGraphPaths() {
+ return this.xmlGraphPathList;
+ }
+
+ public List<Path> getActivationPaths() {
+ return this.activationFilePathList;
+ }
+}
diff --git a/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicDblibStore.java b/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicDblibStore.java
new file mode 100644
index 000000000..dc3a560eb
--- /dev/null
+++ b/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicDblibStore.java
@@ -0,0 +1,332 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.sli;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.sql.Blob;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Properties;
+import javax.sql.rowset.CachedRowSet;
+import org.onap.ccsdk.sli.core.dblib.DbLibService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class SvcLogicDblibStore implements SvcLogicStore {
+ private static final Logger LOG = LoggerFactory.getLogger(SvcLogicDblibStore.class);
+ private DbLibService dbSvc;
+
+ public SvcLogicDblibStore(DbLibService dbsvc) {
+ this.dbSvc = dbsvc;
+ }
+
+ public Connection getConnection() throws SQLException {
+ return(dbSvc.getConnection());
+ }
+
+ @Override
+ public void init(Properties props) throws ConfigurationException {
+ if(dbSvc == null) {
+ LOG.error("SvcLogic cannot acquire DBLIB_SERVICE");
+ return;
+ }
+ try {
+ dbSvc.getData("select 1 from DUAL", new ArrayList<String>(), null);
+ LOG.debug("SQL test was successful");
+ } catch (SQLException e) {
+ LOG.error("Failed SQL test", e);
+ }
+ }
+
+ @Override
+ public boolean hasGraph(String module, String rpc, String version,
+ String mode) throws SvcLogicException {
+ boolean retval = false;
+ CachedRowSet results = null;
+ String hasVersionGraphSql = "SELECT count(*) FROM SVC_LOGIC"
+ + " WHERE module = ? AND rpc = ? AND mode = ? AND version = ?";
+
+ String hasActiveGraphSql = "SELECT count(*) FROM SVC_LOGIC"
+ + " WHERE module = ? AND rpc = ? AND mode = ? AND active = 'Y'";
+
+ ArrayList<String> args = new ArrayList<>();
+ args.add(module);
+ args.add(rpc);
+ args.add(mode);
+
+ try {
+
+ if (version == null) {
+ results = dbSvc.getData(hasActiveGraphSql, args, null);
+ } else {
+ args.add(version);
+ results = dbSvc.getData(hasVersionGraphSql, args, null);
+ }
+
+ if (results.next()) {
+ int cnt = results.getInt(1);
+
+ if (cnt > 0) {
+ retval = true;
+ }
+ }
+ } catch (Exception e) {
+ throw new ConfigurationException("SQL query failed", e);
+ } finally {
+ if (results != null) {
+ try {
+ results.close();
+ } catch (SQLException x) {
+ LOG.error("Failed to close CachedRowSet", x);
+ }
+ }
+
+ }
+
+ return retval;
+ }
+
+ public SvcLogicGraph fetch(String module, String rpc, String version,
+ String mode) throws SvcLogicException {
+
+ PreparedStatement fetchGraphStmt = null;
+ Connection dbConn = null;
+ SvcLogicGraph retval = null;
+ ResultSet results = null;
+
+ String fetchVersionGraphSql = "SELECT graph FROM SVC_LOGIC"
+ + " WHERE module = ? AND rpc = ? AND mode = ? AND version = ?";
+
+ String fetchActiveGraphSql = "SELECT graph FROM SVC_LOGIC"
+ + " WHERE module = ? AND rpc = ? AND mode = ? AND active = 'Y'";
+
+
+ try {
+ dbConn = dbSvc.getConnection();
+
+ if (version == null) {
+ fetchGraphStmt = dbConn.prepareStatement(fetchActiveGraphSql);
+ } else {
+ fetchGraphStmt = dbConn.prepareStatement(fetchVersionGraphSql);
+ }
+
+ fetchGraphStmt.setString(1, module);
+ fetchGraphStmt.setString(2, rpc);
+ fetchGraphStmt.setString(3, mode);
+ if (version != null) {
+ fetchGraphStmt.setString(4,version);
+ }
+
+ results = fetchGraphStmt.executeQuery();
+
+ if (results.next()) {
+ Blob graphBlob = results.getBlob("graph");
+
+ ObjectInputStream gStream = new ObjectInputStream(graphBlob.getBinaryStream());
+
+ Object graphObj = gStream.readObject();
+ gStream.close();
+
+ if (graphObj instanceof SvcLogicGraph) {
+ retval = (SvcLogicGraph) graphObj;
+ } else {
+ throw new ConfigurationException("invalid type for graph ("
+ + graphObj.getClass().getName());
+
+ }
+
+ } else {
+ return null;
+ }
+ } catch (Exception e) {
+ LOG.error("Graph processing failed", e);
+ throw new ConfigurationException("Graph processing failed: " + e.getMessage());
+ } finally {
+ try {
+ if (fetchGraphStmt != null) {
+ fetchGraphStmt.close();
+ }
+ } catch (SQLException e) {
+ LOG.error("PreparedStatement close error", e);
+ }
+ if (results != null) {
+ try {
+ results.close();
+ } catch (SQLException x) {
+ LOG.error("ResultSet close error", x);
+ }
+ }
+ try {
+ if (dbConn != null && !dbConn.isClosed()) {
+ dbConn.close();
+ }
+ } catch (Exception exc) {
+ LOG.error("dbConn close error", exc);
+ } finally {
+ dbConn = null;
+ }
+
+ }
+
+ return retval;
+ }
+
+ public void store(SvcLogicGraph graph) throws SvcLogicException {
+
+
+
+ String storeGraphSql = "INSERT INTO SVC_LOGIC (module, rpc, version, mode, active, graph, md5sum)"
+ + " VALUES(?, ?, ?, ?, ?, ?, ?)";
+
+ if (graph == null) {
+ throw new SvcLogicException("graph cannot be null");
+ }
+
+ byte[] graphBytes = null;
+
+ try (ByteArrayOutputStream byteStr = new ByteArrayOutputStream();
+ ObjectOutputStream goutStr = new ObjectOutputStream(byteStr)) {
+
+ goutStr.writeObject(graph);
+
+ graphBytes = byteStr.toByteArray();
+
+ } catch (Exception e) {
+ throw new SvcLogicException("could not serialize graph", e);
+ }
+
+ // If object already stored in database, delete it
+ if (hasGraph(graph.getModule(), graph.getRpc(), graph.getVersion(),
+ graph.getMode())) {
+ delete(graph.getModule(), graph.getRpc(), graph.getVersion(),
+ graph.getMode());
+ }
+
+ Connection dbConn = null;
+ PreparedStatement storeGraphStmt = null;
+ try {
+ dbConn = dbSvc.getConnection();
+ boolean oldAutoCommit = dbConn.getAutoCommit();
+ dbConn.setAutoCommit(false);
+ storeGraphStmt = dbConn.prepareStatement(storeGraphSql);
+ storeGraphStmt.setString(1, graph.getModule());
+ storeGraphStmt.setString(2, graph.getRpc());
+ storeGraphStmt.setString(3, graph.getVersion());
+ storeGraphStmt.setString(4, graph.getMode());
+ storeGraphStmt.setString(5, "N");
+ storeGraphStmt.setBlob(6, new ByteArrayInputStream(graphBytes));
+ storeGraphStmt.setString(7, graph.getMd5sum());
+ storeGraphStmt.executeUpdate();
+ dbConn.commit();
+ dbConn.setAutoCommit(oldAutoCommit);
+ } catch (Exception e) {
+ throw new SvcLogicException("Could not write object to database", e);
+ } finally {
+ try {
+ if (storeGraphStmt != null) {
+ storeGraphStmt.close();
+ }
+ } catch (SQLException e) {
+ LOG.error("PreparedStatement close error", e);
+ }
+ try {
+ if (dbConn != null && !dbConn.isClosed()) {
+ dbConn.close();
+ }
+ } catch (Exception exc) {
+ LOG.error("dbConn close error", exc);
+ } finally {
+ dbConn = null;
+ }
+
+ }
+ }
+
+ public void delete(String module, String rpc, String version, String mode)
+ throws SvcLogicException {
+ String deleteGraphSql = "DELETE FROM SVC_LOGIC WHERE module = ? AND rpc = ? AND version = ? AND mode = ?";
+
+ ArrayList<String> args = new ArrayList<>();
+
+ args.add(module);
+ args.add(rpc);
+ args.add(version);
+ args.add(mode);
+
+ try {
+ dbSvc.writeData(deleteGraphSql, args, null);
+ } catch (Exception e) {
+ throw new SvcLogicException("Could not delete object from database", e);
+ }
+ }
+
+ public void activate(SvcLogicGraph graph) throws SvcLogicException {
+ String deactivateSql = "UPDATE SVC_LOGIC SET active = 'N' WHERE module = ? AND rpc = ? AND mode = ?";
+ String activateSql = "UPDATE SVC_LOGIC SET active = 'Y' WHERE module = ? AND rpc = ? AND mode = ? AND version = ?";
+
+ ArrayList<String> args = new ArrayList<>();
+
+ args.add(graph.getModule());
+ args.add(graph.getRpc());
+ args.add(graph.getMode());
+
+ try {
+ dbSvc.writeData(deactivateSql, args, null);
+ args.add(graph.getVersion());
+ dbSvc.writeData(activateSql, args, null);
+ } catch (Exception e) {
+ throw new SvcLogicException("Could not activate graph", e);
+ }
+ }
+
+ @Override
+ public void activate(String module, String rpc, String version, String mode) throws SvcLogicException {
+
+ String deactivateSql = "UPDATE SVC_LOGIC SET active = 'N' WHERE module = ? AND rpc = ? AND mode = ?";
+
+ String activateSql = "UPDATE SVC_LOGIC SET active = 'Y' WHERE module = ? AND rpc = ? AND mode = ? AND version = ?";
+
+ ArrayList<String> args = new ArrayList<>();
+
+ args.add(module);
+ args.add(rpc);
+ args.add(mode);
+
+ try {
+
+ dbSvc.writeData(deactivateSql, args, null);
+
+ args.add(version);
+ dbSvc.writeData(activateSql, args, null);
+
+ } catch (Exception e) {
+ throw new SvcLogicException("Could not activate graph", e);
+ }
+ }
+
+}
diff --git a/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicException.java b/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicException.java
new file mode 100644
index 000000000..c03ef9787
--- /dev/null
+++ b/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicException.java
@@ -0,0 +1,46 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.sli;
+
+public class SvcLogicException extends Exception {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1L;
+
+ public SvcLogicException()
+ {
+ super();
+ }
+
+ public SvcLogicException(String message)
+ {
+ super(message);
+ }
+
+ public SvcLogicException(String message, Throwable t)
+ {
+ super(message, t);
+ }
+
+}
diff --git a/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicExprListener.java b/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicExprListener.java
new file mode 100644
index 000000000..a1871951f
--- /dev/null
+++ b/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicExprListener.java
@@ -0,0 +1,271 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Modifications Copyright (C) 2018 IBM.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.sli;
+
+import java.util.LinkedList;
+import java.util.List;
+
+import org.antlr.v4.runtime.tree.TerminalNode;
+import org.onap.ccsdk.sli.core.sli.ExprGrammarParser.AddExprContext;
+import org.onap.ccsdk.sli.core.sli.ExprGrammarParser.AtomContext;
+import org.onap.ccsdk.sli.core.sli.ExprGrammarParser.CompareExprContext;
+import org.onap.ccsdk.sli.core.sli.ExprGrammarParser.ConstantContext;
+import org.onap.ccsdk.sli.core.sli.ExprGrammarParser.ExprContext;
+import org.onap.ccsdk.sli.core.sli.ExprGrammarParser.FuncExprContext;
+import org.onap.ccsdk.sli.core.sli.ExprGrammarParser.MultExprContext;
+import org.onap.ccsdk.sli.core.sli.ExprGrammarParser.ParenExprContext;
+import org.onap.ccsdk.sli.core.sli.ExprGrammarParser.RelExprContext;
+import org.onap.ccsdk.sli.core.sli.ExprGrammarParser.VariableContext;
+import org.onap.ccsdk.sli.core.sli.ExprGrammarParser.VariableLeadContext;
+import org.onap.ccsdk.sli.core.sli.ExprGrammarParser.VariableTermContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class SvcLogicExprListener extends ExprGrammarBaseListener
+{
+
+
+
+
+ private static final Logger LOG = LoggerFactory
+ .getLogger(SvcLogicExprListener.class);
+
+ private SvcLogicExpression curExpr;
+ //private SvcLogicExpression topExpr;
+ private LinkedList<SvcLogicExpression> exprStack;
+
+ public SvcLogicExprListener()
+ {
+ exprStack = new LinkedList<>();
+ }
+
+ public SvcLogicExpression getParsedExpr()
+ {
+ return(curExpr);
+ }
+
+ private void pushOperand(SvcLogicExpression operand)
+ {
+ if (curExpr == null)
+ {
+ curExpr = operand;
+ }
+ else
+ {
+ curExpr.addOperand(operand);
+ }
+ }
+
+ private void pushExpr(SvcLogicExpression expr)
+ {
+ if (curExpr != null)
+ {
+ exprStack.push(curExpr);
+ }
+ curExpr = expr;
+ }
+
+ private void popExpr()
+ {
+ if (exprStack.isEmpty())
+ {
+ //topExpr = curExpr;
+ }
+ else
+ {
+ SvcLogicExpression lastExpr = curExpr;
+ curExpr = exprStack.pop();
+ curExpr.addOperand(lastExpr);
+ }
+
+ }
+
+ @Override
+ public void enterAtom(AtomContext ctx) {
+ String atomText = ctx.getText();
+ SvcLogicAtom newAtom = new SvcLogicAtom(atomText);
+ pushExpr(newAtom);
+ }
+
+
+ @Override
+ public void enterMultExpr(MultExprContext ctx) {
+ SvcLogicBinaryExpression curBinExpr = new SvcLogicBinaryExpression();
+ pushExpr(curBinExpr);
+
+ List<TerminalNode> opList = ctx.MULTOP();
+
+ for (TerminalNode nd : opList)
+ {
+ curBinExpr.addOperator(nd.getText());
+ }
+
+ }
+
+ @Override
+ public void exitMultExpr(MultExprContext ctx) {
+ popExpr();
+ }
+
+ @Override
+ public void exitAtom(AtomContext ctx) {
+ popExpr();
+ }
+
+ @Override
+ public void enterAddExpr(AddExprContext ctx) {
+ List<TerminalNode> opList = ctx.ADDOP();
+
+
+ SvcLogicBinaryExpression curBinExpr = new SvcLogicBinaryExpression();
+ pushExpr(curBinExpr);
+
+
+ for (TerminalNode nd : opList)
+ {
+ curBinExpr.addOperator(nd.getText());
+ }
+
+ }
+
+ @Override
+ public void exitAddExpr(AddExprContext ctx) {
+ popExpr();
+ }
+
+ @Override
+ public void enterFuncExpr(FuncExprContext ctx) {
+ LOG.trace("enterFuncExpr: text = "+ctx.getText());
+ LOG.trace("enterFuncExpr - IDENTIFIER : "+ctx.IDENTIFIER().getText());
+
+ for (ExprContext expr: ctx.expr())
+ {
+ LOG.trace("enterFuncExpr - expr = "+expr.getText());
+ }
+
+
+ pushExpr(new SvcLogicFunctionCall(ctx.IDENTIFIER().getText()));
+ }
+
+ @Override
+ public void exitFuncExpr(FuncExprContext ctx) {
+ popExpr();
+ }
+
+ @Override
+ public void enterParenExpr(ParenExprContext ctx) {
+ LOG.trace("enterParenExpr: text = "+ctx.getText());
+ LOG.trace("enterParenExpr: expr = "+ctx.expr().getText());
+ }
+
+ @Override
+ public void exitParenExpr(ParenExprContext ctx) {
+ LOG.trace("exitParenExpr: text = "+ctx.getText());
+ }
+
+ @Override
+ public void enterRelExpr(RelExprContext ctx) {
+ List<TerminalNode> opList = ctx.RELOP();
+
+
+ SvcLogicBinaryExpression curBinExpr = new SvcLogicBinaryExpression();
+ pushExpr(curBinExpr);
+
+
+ for (TerminalNode nd : opList)
+ {
+ curBinExpr.addOperator(nd.getText());
+ }
+
+ }
+
+ @Override
+ public void exitRelExpr(RelExprContext ctx) {
+ popExpr();
+ }
+
+ @Override
+ public void enterCompareExpr(CompareExprContext ctx) {
+
+ TerminalNode nd = ctx.COMPAREOP();
+
+ SvcLogicBinaryExpression curBinExpr = new SvcLogicBinaryExpression();
+ pushExpr(curBinExpr);
+
+ curBinExpr.addOperator(nd.getText());
+
+ }
+
+ @Override
+ public void exitCompareExpr(CompareExprContext ctx) {
+
+ popExpr();
+ }
+
+
+
+ @Override
+ public void enterConstant(ConstantContext ctx) {
+ }
+
+ @Override
+ public void exitConstant(ConstantContext ctx) {
+ }
+
+
+ @Override
+ public void enterVariable(VariableContext ctx) {
+ }
+
+ @Override
+ public void exitVariable(VariableContext ctx) {
+ }
+
+
+ @Override
+ public void enterVariableLead(VariableLeadContext ctx) {
+ }
+
+ @Override
+ public void exitVariableLead(VariableLeadContext ctx) {
+ }
+
+ @Override
+ public void enterVariableTerm(VariableTermContext ctx) {
+ String name = ctx.getText();
+
+ int subscrStart = name.indexOf("[");
+ if (subscrStart > -1)
+ {
+ name = name.substring(0, subscrStart);
+ }
+ SvcLogicVariableTerm vterm = new SvcLogicVariableTerm(name);
+ pushExpr(vterm);
+ }
+
+ @Override
+ public void exitVariableTerm(VariableTermContext ctx) {
+ popExpr();
+ }
+}
diff --git a/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicExprParserErrorListener.java b/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicExprParserErrorListener.java
new file mode 100644
index 000000000..03f2a8b0b
--- /dev/null
+++ b/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicExprParserErrorListener.java
@@ -0,0 +1,44 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.sli;
+
+import org.antlr.v4.runtime.BaseErrorListener;
+import org.antlr.v4.runtime.RecognitionException;
+import org.antlr.v4.runtime.Recognizer;
+import org.antlr.v4.runtime.misc.ParseCancellationException;
+
+public class SvcLogicExprParserErrorListener extends BaseErrorListener {
+
+ private static final SvcLogicExprParserErrorListener instance = new SvcLogicExprParserErrorListener();
+
+ public static SvcLogicExprParserErrorListener getInstance() {
+ return(instance);
+ }
+
+ @Override
+ public void syntaxError(Recognizer<?, ?> recognizer, Object offendingSymbol, int line, int charPositionInLine,
+ String msg, RecognitionException e) throws ParseCancellationException {
+ throw new ParseCancellationException(msg);
+ }
+
+
+}
diff --git a/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicExpression.java b/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicExpression.java
new file mode 100644
index 000000000..81aeb6c37
--- /dev/null
+++ b/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicExpression.java
@@ -0,0 +1,52 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Modifications Copyright (C) 2018 IBM.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.sli;
+
+import java.io.Serializable;
+import java.util.LinkedList;
+import java.util.List;
+
+
+public abstract class SvcLogicExpression implements Serializable {
+
+ private List<SvcLogicExpression> operands = new LinkedList<>();
+
+
+ public void addOperand(SvcLogicExpression expr)
+ {
+ operands.add(expr);
+ }
+
+ public List<SvcLogicExpression> getOperands() {
+ return operands;
+ }
+
+ public int numOperands()
+ {
+ return(operands.size());
+ }
+
+ public abstract String asParsedExpr();
+
+}
diff --git a/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicExpressionFactory.java b/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicExpressionFactory.java
new file mode 100644
index 000000000..727c84b19
--- /dev/null
+++ b/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicExpressionFactory.java
@@ -0,0 +1,75 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.sli;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import org.antlr.v4.runtime.ANTLRInputStream;
+import org.antlr.v4.runtime.CharStream;
+import org.antlr.v4.runtime.CommonTokenStream;
+import org.antlr.v4.runtime.tree.ParseTreeWalker;
+import org.onap.ccsdk.sli.core.sli.ExprGrammarParser.ExprContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+public class SvcLogicExpressionFactory {
+
+ private static final Logger LOG = LoggerFactory
+ .getLogger(SvcLogicExpressionFactory.class);
+
+
+ public static SvcLogicExpression parse(String exprStr) throws IOException
+ {
+ InputStream exprStream = new ByteArrayInputStream(exprStr.getBytes());
+ CharStream input = new ANTLRInputStream(exprStream);
+ ExprGrammarLexer lexer = new ExprGrammarLexer(input);
+ CommonTokenStream tokens = new CommonTokenStream(lexer);
+ ExprGrammarParser parser = new ExprGrammarParser(tokens);
+
+ lexer.removeErrorListeners();
+ lexer.addErrorListener(SvcLogicExprParserErrorListener.getInstance());
+ parser.removeErrorListeners();
+ parser.addErrorListener(SvcLogicExprParserErrorListener.getInstance());
+
+ ExprContext expression = null;
+
+ try {
+ expression = parser.expr();
+ } catch (Exception e) {
+ String errorMsg = e.getMessage();
+
+ LOG.error(errorMsg);
+ throw new SvcLogicParserException(errorMsg);
+ }
+
+
+ ParseTreeWalker walker = new ParseTreeWalker();
+ SvcLogicExprListener listener = new SvcLogicExprListener();
+ walker.walk(listener, expression);
+
+
+ return(listener.getParsedExpr());
+ }
+
+}
diff --git a/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicFunctionCall.java b/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicFunctionCall.java
new file mode 100644
index 000000000..8289f16da
--- /dev/null
+++ b/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicFunctionCall.java
@@ -0,0 +1,80 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.sli;
+
+public class SvcLogicFunctionCall extends SvcLogicExpression {
+
+ private String functionName;
+
+ public SvcLogicFunctionCall(String functionName)
+ {
+ this.functionName = functionName;
+ }
+
+ public String getFunctionName() {
+ return functionName;
+ }
+
+ public void setFunctionName(String functionName) {
+ this.functionName = functionName;
+ }
+
+ public String toString()
+ {
+ StringBuffer sbuff = new StringBuffer();
+
+ sbuff.append(functionName);
+ sbuff.append("(");
+ boolean needComma = false;
+ for (SvcLogicExpression operand: getOperands())
+ {
+ if (needComma)
+ {
+ sbuff.append(",");
+ }
+ else
+ {
+ needComma = true;
+ }
+ sbuff.append(operand.toString());
+
+ }
+ sbuff.append(")");
+ return(sbuff.toString());
+ }
+
+ public String asParsedExpr()
+ {
+ StringBuffer sbuff = new StringBuffer();
+
+ sbuff.append("(");
+ sbuff.append(functionName);
+ for (SvcLogicExpression operand: getOperands())
+ {
+ sbuff.append(" ");
+ sbuff.append(operand.asParsedExpr());
+ }
+ sbuff.append(")");
+ return(sbuff.toString());
+ }
+
+}
diff --git a/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicGraph.java b/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicGraph.java
new file mode 100644
index 000000000..97f2bd7ab
--- /dev/null
+++ b/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicGraph.java
@@ -0,0 +1,199 @@
+/*-
+x * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Modifications copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.sli;
+
+import java.io.PrintStream;
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.Map;
+
+public class SvcLogicGraph implements Serializable {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1L;
+
+ private String module = null;
+ private String rpc = null;
+ private String mode = null;
+ private String version = null;
+
+ private String md5sum = null;
+
+ private Map<String, Serializable> attributes;
+ private Map<String, SvcLogicNode> namedNodes;
+ private SvcLogicNode rootNode;
+
+ public SvcLogicGraph()
+ {
+ attributes = new HashMap<>();
+ namedNodes = new HashMap<>();
+ rootNode = null;
+ }
+
+ public String getMd5sum() {
+ return md5sum;
+ }
+
+
+ public void setMd5sum(String md5sum) {
+ this.md5sum = md5sum;
+ }
+
+
+
+ public String getModule() {
+ return module;
+ }
+
+
+ public void setModule(String module) {
+ this.module = module;
+ }
+
+
+ public String getRpc() {
+ return rpc;
+ }
+
+
+ public void setRpc(String rpc) {
+ this.rpc = rpc;
+ }
+
+
+
+
+ public String getMode() {
+ return mode;
+ }
+
+
+ public void setMode(String mode) {
+ this.mode = mode;
+ }
+
+
+ public String getVersion() {
+ return version;
+ }
+
+
+ public void setVersion(String version) {
+ this.version = version;
+ }
+
+
+ public void setRootNode(SvcLogicNode rootNode)
+ {
+ this.rootNode = rootNode;
+ }
+
+ public SvcLogicNode getRootNode()
+ {
+ return(rootNode);
+ }
+
+ public Serializable getAttribute(String name)
+ {
+ if (attributes.containsKey(name))
+ {
+ return(attributes.get(name));
+ }
+ else
+ {
+ return(null);
+ }
+
+ }
+
+ public void setAttribute(String name, Serializable value) throws DuplicateValueException
+ {
+ if (attributes.containsKey(name))
+ {
+ throw new DuplicateValueException("Duplicate attribute "+name);
+ }
+
+ attributes.put(name, value);
+ }
+
+ public SvcLogicNode getNamedNode(String nodeName)
+ {
+ if (namedNodes.containsKey(nodeName))
+ {
+ return(namedNodes.get(nodeName));
+ }
+ else
+ {
+ return(null);
+ }
+ }
+
+ public void setNamedNode(String nodeName, SvcLogicNode node) throws DuplicateValueException
+ {
+ if (namedNodes.containsKey(nodeName))
+ {
+ throw new DuplicateValueException("Duplicate node name "+nodeName);
+ }
+
+ namedNodes.put(nodeName, node);
+ }
+
+
+
+ public void printAsGv(PrintStream pstr)
+ {
+ pstr.println("digraph g {");
+ pstr.println("START [label=\"START\\n"+module+":"+rpc+"\"];");
+
+ if (rootNode != null)
+ {
+ pstr.println("START -> node"+rootNode.getNodeId()+";");
+ rootNode.setVisited(false, true);
+ rootNode.printAsGv(pstr);
+ }
+ pstr.println("}");
+ }
+
+ public void printAsXml(PrintStream pstr)
+ {
+ pstr.println("<service-logic module='"+getModule()+"' version='"+getVersion()+"'>");
+ pstr.println(" <method rpc='"+getRpc()+"' mode='"+getMode()+"'>");
+ if (rootNode != null)
+ {
+ rootNode.setVisited(false, true);
+ rootNode.printAsXml(pstr, 2);
+ }
+ pstr.println(" </method>");
+ pstr.println("</service-logic>");
+ }
+
+ @Override
+ public String toString() {
+ return "SvcLogicGraph [module=" + module + ", rpc=" + rpc + ", mode=" + mode + ", version=" + version + ", md5sum=" + md5sum + "]";
+ }
+
+}
diff --git a/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicJavaPlugin.java b/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicJavaPlugin.java
new file mode 100644
index 000000000..23dff3e6e
--- /dev/null
+++ b/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicJavaPlugin.java
@@ -0,0 +1,30 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.sli;
+
+/**
+ * A marker interface, used to indicate that a class exposes methods that can be
+ * called from an <execute> node. Such methods must have the signature:
+ * void methodName(Map, SvcLogicContext)
+ */
+public interface SvcLogicJavaPlugin {
+}
diff --git a/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicJdbcStore.java b/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicJdbcStore.java
new file mode 100644
index 000000000..f23456fee
--- /dev/null
+++ b/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicJdbcStore.java
@@ -0,0 +1,574 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.sli;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.sql.Blob;
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.Driver;
+import java.sql.DriverManager;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.Properties;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class SvcLogicJdbcStore implements SvcLogicStore {
+ private static final Logger LOG = LoggerFactory.getLogger(SvcLogicJdbcStore.class);
+
+ private String dbUrl = null;
+ private String dbName = null;
+ private String dbUser = null;
+ private String dbPasswd = null;
+ private String dbDriver = null;
+
+ private Connection dbConn;
+ private PreparedStatement hasActiveGraphStmt = null;
+ private PreparedStatement hasVersionGraphStmt = null;
+ private PreparedStatement fetchActiveGraphStmt = null;
+ private PreparedStatement fetchVersionGraphStmt = null;
+ private PreparedStatement storeGraphStmt = null;
+ private PreparedStatement deleteGraphStmt = null;
+
+ private PreparedStatement deactivateStmt = null;
+ private PreparedStatement activateStmt = null;
+
+ private void getConnection() throws ConfigurationException {
+
+ Properties jdbcProps = new Properties();
+
+ jdbcProps.setProperty("user", dbUser);
+ jdbcProps.setProperty("password", dbPasswd);
+
+ try {
+ Driver dvr = new org.mariadb.jdbc.Driver();
+ if (dvr.acceptsURL(dbUrl)) {
+ LOG.debug("Driver com.mysql.jdbc.Driver accepts {}", dbUrl);
+ } else {
+ LOG.warn("Driver com.mysql.jdbc.Driver does not accept {}", dbUrl);
+ }
+ } catch (SQLException e1) {
+ LOG.error("Caught exception trying to load com.mysql.jdbc.Driver", e1);
+ }
+
+ try {
+ this.dbConn = DriverManager.getConnection(dbUrl, jdbcProps);
+ } catch (Exception e) {
+ throw new ConfigurationException("failed to get database connection [" + dbUrl + "]", e);
+ }
+
+ }
+
+ private void createTable() throws ConfigurationException {
+
+ DatabaseMetaData dbm;
+
+ try {
+ dbm = dbConn.getMetaData();
+ } catch (SQLException e) {
+
+ throw new ConfigurationException("could not get databse metadata", e);
+ }
+
+ // See if table SVC_LOGIC exists. If not, create it.
+ Statement stmt = null;
+ try {
+
+ ResultSet tables = dbm.getTables(null, null, "SVC_LOGIC", null);
+ if (tables.next()) {
+ LOG.debug("SVC_LOGIC table already exists");
+ } else {
+ String crTableCmd = "CREATE TABLE " + dbName + ".SVC_LOGIC (" + "module varchar(80) NOT NULL,"
+ + "rpc varchar(80) NOT NULL," + "version varchar(40) NOT NULL," + "mode varchar(5) NOT NULL,"
+ + "active varchar(1) NOT NULL,graph BLOB,"
+ + "modified_timestamp timestamp ,"
+ + "md5sum varchar(128) DEFAULT NULL,"
+ + "CONSTRAINT P_SVC_LOGIC PRIMARY KEY(module, rpc, version, mode))";
+
+ stmt = dbConn.createStatement();
+ stmt.executeUpdate(crTableCmd);
+ }
+ } catch (Exception e) {
+ throw new ConfigurationException("could not create SVC_LOGIC table", e);
+ } finally {
+ if (stmt != null) {
+ try {
+ stmt.close();
+ } catch (SQLException e) {
+ LOG.error("Statement close error ", e);
+ }
+ }
+ }
+
+ // See if NODE_TYPES table exists and, if not, create it
+ stmt = null;
+ try {
+
+ ResultSet tables = dbm.getTables(null, null, "NODE_TYPES", null);
+ if (tables.next()) {
+ LOG.debug("NODE_TYPES table already exists");
+ } else {
+ String crTableCmd = "CREATE TABLE " + dbName + ".NODE_TYPES (" + "nodetype varchar(80) NOT NULL,"
+ + "CONSTRAINT P_NODE_TYPES PRIMARY KEY(nodetype))";
+
+ stmt = dbConn.createStatement();
+
+ stmt.executeUpdate(crTableCmd);
+ }
+ } catch (Exception e) {
+ throw new ConfigurationException("could not create SVC_LOGIC table", e);
+ } finally {
+ if (stmt != null) {
+ try {
+ stmt.close();
+ } catch (SQLException e) {
+ LOG.error("Statement close error ", e);
+ }
+ }
+ }
+ }
+
+ private void prepStatements() throws ConfigurationException {
+
+ // Prepare statements
+ String hasVersionGraphSql = CommonConstants.JDBC_SELECT_COUNT + dbName + CommonConstants.SVCLOGIC_TABLE
+ + CommonConstants.JDBC_GRAPH_QUERY;
+
+ try {
+ hasVersionGraphStmt = dbConn.prepareStatement(hasVersionGraphSql);
+ } catch (Exception e) {
+ throw new ConfigurationException(CommonConstants.JDBC_STATEMENT_ERR + hasVersionGraphSql, e);
+
+ }
+
+ String hasActiveGraphSql = CommonConstants.JDBC_SELECT_COUNT + dbName + CommonConstants.SVCLOGIC_TABLE
+ + CommonConstants.JDBC_ACTIVE_GRAPH_QUERY;
+
+ try {
+ hasActiveGraphStmt = dbConn.prepareStatement(hasActiveGraphSql);
+ } catch (Exception e) {
+ throw new ConfigurationException(CommonConstants.JDBC_STATEMENT_ERR + hasVersionGraphSql, e);
+
+ }
+
+ String fetchVersionGraphSql = CommonConstants.JDBC_SELECT_GRAPGH + dbName + CommonConstants.SVCLOGIC_TABLE
+ + CommonConstants.JDBC_GRAPH_QUERY;
+
+ try {
+ fetchVersionGraphStmt = dbConn.prepareStatement(fetchVersionGraphSql);
+ } catch (Exception e) {
+ throw new ConfigurationException(CommonConstants.JDBC_STATEMENT_ERR + fetchVersionGraphSql, e);
+
+ }
+
+ String fetchActiveGraphSql = CommonConstants.JDBC_SELECT_GRAPGH + dbName + CommonConstants.SVCLOGIC_TABLE
+ + CommonConstants.JDBC_ACTIVE_GRAPH_QUERY;
+
+ try {
+ fetchActiveGraphStmt = dbConn.prepareStatement(fetchActiveGraphSql);
+ } catch (Exception e) {
+ throw new ConfigurationException(CommonConstants.JDBC_STATEMENT_ERR + fetchVersionGraphSql, e);
+
+ }
+
+ String storeGraphSql = CommonConstants.JDBC_INSERT + dbName
+ + ".SVC_LOGIC (module, rpc, version, mode, active, graph, md5sum) VALUES(?, ?, ?, ?, ?, ?, ?)";
+
+ try {
+ storeGraphStmt = dbConn.prepareStatement(storeGraphSql);
+ } catch (Exception e) {
+ throw new ConfigurationException(CommonConstants.JDBC_STATEMENT_ERR + storeGraphSql, e);
+ }
+
+ String deleteGraphSql = CommonConstants.JDBC_DELETE + dbName
+ + ".SVC_LOGIC WHERE module = ? AND rpc = ? AND version = ? AND mode = ?";
+
+ try {
+ deleteGraphStmt = dbConn.prepareStatement(deleteGraphSql);
+ } catch (Exception e) {
+ throw new ConfigurationException(CommonConstants.JDBC_STATEMENT_ERR + deleteGraphSql, e);
+ }
+
+ String deactivateSql = CommonConstants.JDBC_UPDATE + dbName
+ + ".SVC_LOGIC SET active = 'N' WHERE module = ? AND rpc = ? AND mode = ?";
+
+ try {
+ deactivateStmt = dbConn.prepareStatement(deactivateSql);
+ } catch (Exception e) {
+ throw new ConfigurationException(CommonConstants.JDBC_STATEMENT_ERR + deactivateSql, e);
+ }
+
+ String activateSql = CommonConstants.JDBC_UPDATE + dbName
+ + ".SVC_LOGIC SET active = 'Y' WHERE module = ? AND rpc = ? AND version = ? AND mode = ?";
+
+ try {
+ activateStmt = dbConn.prepareStatement(activateSql);
+ } catch (Exception e) {
+ throw new ConfigurationException(CommonConstants.JDBC_STATEMENT_ERR + activateSql, e);
+ }
+ }
+
+ private void initDbResources() throws ConfigurationException {
+ if ((dbDriver != null) && (dbDriver.length() > 0)) {
+
+ try {
+ Class.forName(dbDriver);
+ } catch (Exception e) {
+ throw new ConfigurationException("could not load driver class " + dbDriver, e);
+ }
+ }
+ getConnection();
+ createTable();
+ prepStatements();
+ }
+
+
+ @Override
+ public void init(Properties props) throws ConfigurationException {
+
+
+ dbUrl = props.getProperty("org.onap.ccsdk.sli.jdbc.url");
+ if ((dbUrl == null) || (dbUrl.length() == 0)) {
+ throw new ConfigurationException("property org.onap.ccsdk.sli.jdbc.url unset");
+ }
+
+ dbName = props.getProperty("org.onap.ccsdk.sli.jdbc.database");
+ if ((dbName == null) || (dbName.length() == 0)) {
+ throw new ConfigurationException("property org.onap.ccsdk.sli.jdbc.database unset");
+ }
+
+ dbUser = props.getProperty("org.onap.ccsdk.sli.jdbc.user");
+ if ((dbUser == null) || (dbUser.length() == 0)) {
+ throw new ConfigurationException("property org.onap.ccsdk.sli.jdbc.user unset");
+ }
+
+
+ dbPasswd = props.getProperty("org.onap.ccsdk.sli.jdbc.password");
+ if ((dbPasswd == null) || (dbPasswd.length() == 0)) {
+ throw new ConfigurationException("property org.onap.ccsdk.sli.jdbc.password unset");
+ }
+
+ dbDriver = props.getProperty("org.onap.ccsdk.sli.jdbc.driver");
+
+
+ initDbResources();
+
+ }
+
+ private boolean isDbConnValid() {
+
+ boolean isValid = false;
+
+ try {
+ if (dbConn != null) {
+ isValid = dbConn.isValid(1);
+ }
+ } catch (SQLException e) {
+ LOG.error("Not a valid db connection: ", e);
+ }
+
+ return isValid;
+ }
+
+ @Override
+ public boolean hasGraph(String module, String rpc, String version, String mode) throws SvcLogicException {
+
+ if (!isDbConnValid()) {
+
+ // Try reinitializing
+ initDbResources();
+
+ if (!isDbConnValid()) {
+ throw new ConfigurationException(CommonConstants.JDBC_CONN_ERR);
+ }
+ }
+
+ boolean retval = false;
+ ResultSet results = null;
+
+ PreparedStatement hasGraphStmt;
+ if (version == null) {
+ hasGraphStmt = hasActiveGraphStmt;
+ } else {
+ hasGraphStmt = hasVersionGraphStmt;
+ }
+
+ try {
+ hasGraphStmt.setString(1, module);
+ hasGraphStmt.setString(2, rpc);
+ hasGraphStmt.setString(3, mode);
+
+
+ if (version != null) {
+ hasGraphStmt.setString(4, version);
+ }
+ boolean oldAutoCommit = dbConn.getAutoCommit();
+ dbConn.setAutoCommit(false);
+ results = hasGraphStmt.executeQuery();
+ dbConn.commit();
+ dbConn.setAutoCommit(oldAutoCommit);
+
+ if (results.next()) {
+ int cnt = results.getInt(1);
+
+ if (cnt > 0) {
+ retval = true;
+ }
+
+ }
+ } catch (Exception e) {
+ throw new ConfigurationException("SQL query failed", e);
+ } finally {
+ if (results != null) {
+ try {
+ results.close();
+ } catch (SQLException x) {
+ LOG.error(CommonConstants.RESULTSET_CLOSE_ERR, x);
+ }
+ }
+
+ }
+
+ return retval;
+
+ }
+
+ @Override
+ public SvcLogicGraph fetch(String module, String rpc, String version, String mode) throws SvcLogicException {
+
+
+ if (!isDbConnValid()) {
+
+ // Try reinitializing
+ initDbResources();
+
+ if (!isDbConnValid()) {
+ throw new ConfigurationException(CommonConstants.JDBC_CONN_ERR);
+ }
+ }
+
+ SvcLogicGraph retval = null;
+ ResultSet results = null;
+
+ PreparedStatement fetchGraphStmt;
+ if (version == null) {
+ fetchGraphStmt = fetchActiveGraphStmt;
+ } else {
+ fetchGraphStmt = fetchVersionGraphStmt;
+ }
+ try {
+ fetchGraphStmt.setString(1, module);
+ fetchGraphStmt.setString(2, rpc);
+ fetchGraphStmt.setString(3, mode);
+
+
+ if (version != null) {
+ fetchGraphStmt.setString(4, version);
+ }
+ boolean oldAutoCommit = dbConn.getAutoCommit();
+ dbConn.setAutoCommit(false);
+ results = fetchGraphStmt.executeQuery();
+ dbConn.commit();
+ dbConn.setAutoCommit(oldAutoCommit);
+
+ if (results.next()) {
+ Blob graphBlob = results.getBlob("graph");
+
+ ObjectInputStream gStream = new ObjectInputStream(graphBlob.getBinaryStream());
+
+ Object graphObj = gStream.readObject();
+ gStream.close();
+
+ if (graphObj instanceof SvcLogicGraph) {
+ retval = (SvcLogicGraph) graphObj;
+ } else {
+ throw new ConfigurationException("invalid type for graph (" + graphObj.getClass().getName());
+
+ }
+ }
+
+ } catch (Exception e) {
+ throw new ConfigurationException("SQL query failed", e);
+ } finally {
+ if (results != null) {
+ try {
+ results.close();
+ } catch (SQLException x) {
+ LOG.error(CommonConstants.RESULTSET_CLOSE_ERR, x);
+ }
+ }
+
+ }
+
+ return retval;
+ }
+
+ public void store(SvcLogicGraph graph) throws SvcLogicException {
+
+
+ if (!isDbConnValid()) {
+
+ // Try reinitializing
+ initDbResources();
+
+ if (!isDbConnValid()) {
+ throw new ConfigurationException(CommonConstants.JDBC_CONN_ERR);
+ }
+ }
+
+ if (graph == null) {
+ throw new SvcLogicException("graph cannot be null");
+ }
+
+ byte[] graphBytes;
+
+ try (ByteArrayOutputStream byteStr = new ByteArrayOutputStream();
+ ObjectOutputStream goutStr = new ObjectOutputStream(byteStr)) {
+
+ goutStr.writeObject(graph);
+
+ graphBytes = byteStr.toByteArray();
+
+ } catch (Exception e) {
+ throw new SvcLogicException("could not serialize graph", e);
+ }
+
+ // If object already stored in database, delete it
+ if (hasGraph(graph.getModule(), graph.getRpc(), graph.getVersion(), graph.getMode())) {
+ delete(graph.getModule(), graph.getRpc(), graph.getVersion(), graph.getMode());
+ }
+
+ try {
+ boolean oldAutoCommit = dbConn.getAutoCommit();
+ dbConn.setAutoCommit(false);
+ storeGraphStmt.setString(1, graph.getModule());
+ storeGraphStmt.setString(2, graph.getRpc());
+ storeGraphStmt.setString(3, graph.getVersion());
+ storeGraphStmt.setString(4, graph.getMode());
+ storeGraphStmt.setString(5, "N");
+ storeGraphStmt.setBlob(6, new ByteArrayInputStream(graphBytes));
+ storeGraphStmt.setString(7, graph.getMd5sum());
+
+ storeGraphStmt.executeUpdate();
+ dbConn.commit();
+
+ dbConn.setAutoCommit(oldAutoCommit);
+ } catch (Exception e) {
+ throw new SvcLogicException("Could not write object to database", e);
+ }
+ }
+
+ @Override
+ public void delete(String module, String rpc, String version, String mode) throws SvcLogicException {
+ if (!isDbConnValid()) {
+
+ // Try reinitializing
+ initDbResources();
+
+ if (!isDbConnValid()) {
+ throw new ConfigurationException(CommonConstants.JDBC_CONN_ERR);
+ }
+ }
+
+ try {
+ boolean oldAutoCommit = dbConn.getAutoCommit();
+ dbConn.setAutoCommit(false);
+ deleteGraphStmt.setString(1, module);
+ deleteGraphStmt.setString(2, rpc);
+ deleteGraphStmt.setString(3, version);
+ deleteGraphStmt.setString(4, mode);
+
+
+ deleteGraphStmt.executeUpdate();
+ dbConn.commit();
+ dbConn.setAutoCommit(oldAutoCommit);
+ } catch (Exception e) {
+ throw new SvcLogicException("Could not delete object from database", e);
+ }
+ }
+
+ @Override
+ public void activate(SvcLogicGraph graph) throws SvcLogicException {
+ try {
+ boolean oldAutoCommit = dbConn.getAutoCommit();
+
+ dbConn.setAutoCommit(false);
+
+ // Deactivate any current active version
+ deactivateStmt.setString(1, graph.getModule());
+ deactivateStmt.setString(2, graph.getRpc());
+ deactivateStmt.setString(3, graph.getMode());
+ deactivateStmt.executeUpdate();
+
+ // Activate this version
+ activateStmt.setString(1, graph.getModule());
+ activateStmt.setString(2, graph.getRpc());
+ activateStmt.setString(3, graph.getVersion());
+ activateStmt.setString(4, graph.getMode());
+ activateStmt.executeUpdate();
+
+ dbConn.commit();
+
+ dbConn.setAutoCommit(oldAutoCommit);
+
+ } catch (Exception e) {
+ throw new SvcLogicException("Could not activate graph", e);
+ }
+ }
+
+ @Override
+ public void activate(String module, String rpc, String version, String mode) throws SvcLogicException {
+ try {
+ boolean oldAutoCommit = dbConn.getAutoCommit();
+
+ dbConn.setAutoCommit(false);
+
+ // Deactivate any current active version
+ deactivateStmt.setString(1, module);
+ deactivateStmt.setString(2, rpc);
+ deactivateStmt.setString(3, mode);
+ deactivateStmt.executeUpdate();
+
+ // Activate this version
+ activateStmt.setString(1, module);
+ activateStmt.setString(2, rpc);
+ activateStmt.setString(3, version);
+ activateStmt.setString(4, mode);
+ activateStmt.executeUpdate();
+
+ dbConn.commit();
+
+ dbConn.setAutoCommit(oldAutoCommit);
+
+ } catch (Exception e) {
+ throw new SvcLogicException("Could not activate graph", e);
+ }
+ }
+
+
+}
diff --git a/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicLoader.java b/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicLoader.java
new file mode 100644
index 000000000..433b723e7
--- /dev/null
+++ b/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicLoader.java
@@ -0,0 +1,178 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Modifications Copyright (C) 2018 IBM.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.sli;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class SvcLogicLoader {
+ private static final Logger LOGGER = LoggerFactory.getLogger(SvcLogicLoader.class);
+ protected SvcLogicStore store;
+ protected String directoryRoot;
+ protected SvcLogicParser parser;
+
+ public SvcLogicLoader(String directoryRoot, SvcLogicStore store) {
+ this.store = store;
+ this.directoryRoot = directoryRoot;
+ this.parser = new SvcLogicParser();
+ }
+
+ public SvcLogicLoader(String directoryRoot, String propFile) {
+ this.store = SvcLogicParser.getStore(propFile);
+ this.directoryRoot = directoryRoot;
+ this.parser = new SvcLogicParser();
+ }
+
+ public void loadAndActivate() throws IOException {
+ SvcLogicCrawler slc = new SvcLogicCrawler();
+ Files.walkFileTree(Paths.get(directoryRoot), slc);
+ loadGraphs(slc.getGraphPaths(), directoryRoot);
+ List<ActivationEntry> activationEntries = processActivationFiles(slc.getActivationPaths());
+ activateGraphs(activationEntries);
+ }
+
+ protected List<ActivationEntry> processActivationFiles(List<Path> activationPaths) {
+ List<ActivationEntry> activationEntries = new ArrayList<>();
+ for (Path activationFile : activationPaths) {
+ activationEntries.addAll(getActivationEntries(activationFile));
+ }
+ return activationEntries;
+ }
+
+ protected void activateGraphs(List<ActivationEntry> activationEntries) {
+ for (ActivationEntry entry : activationEntries) {
+ try {
+ if (store.hasGraph(entry.module, entry.rpc, entry.version, entry.mode)) {
+ LOGGER.info("Activating SvcLogicGraph [module=" + entry.module + ", rpc=" + entry.rpc + ", mode="
+ + entry.mode + ", version=" + entry.version + "]");
+ store.activate(entry.module, entry.rpc, entry.version, entry.mode);
+ } else {
+ LOGGER.error("hasGraph returned false for " + entry.toString());
+ }
+ } catch (SvcLogicException e) {
+ LOGGER.error("Failed to call hasGraph for " + entry.toString(), e);
+ }
+ }
+ }
+
+ protected List<ActivationEntry> getActivationEntries(Path activationFilePath) {
+ List<ActivationEntry> activationEntries = new ArrayList<>();
+ int lineNumber = 1;
+ try (BufferedReader br = Files.newBufferedReader(activationFilePath, StandardCharsets.US_ASCII)) {
+ String fileRead = br.readLine();
+ while (fileRead != null) {
+ String[] fields = fileRead.split("\\s");
+ if (fields.length == 4) {
+ activationEntries.add(parseActivationEntry(fields));
+ } else {
+ LOGGER.error("Activation entry [" + fileRead + "] is declared at line number " + lineNumber
+ + " in the file " + activationFilePath + " and is invalid.");
+ }
+ fileRead = br.readLine();
+ lineNumber++;
+ }
+ return activationEntries;
+ } catch (IOException ioe) {
+ LOGGER.error("Couldn't read the activation file at " + activationFilePath, ioe);
+ return new ArrayList<>();
+ }
+ }
+
+ protected void loadGraphs(List<Path> graphPaths, String directoryRoot) {
+ for (Path graphPath : graphPaths) {
+ try {
+ saveGraph(graphPath.toString());
+ } catch (Exception e) {
+ LOGGER.error("Couldn't load graph at " + graphPath, e);
+ }
+ }
+ }
+
+ protected void saveGraph(String xmlFile) throws SvcLogicException {
+ File f = new File(xmlFile);
+ if (!f.canRead()) {
+ throw new ConfigurationException("Cannot read xml file (" + xmlFile + ")");
+ }
+
+ LinkedList<SvcLogicGraph> graphs = null;
+
+ try {
+ graphs = parser.parse(xmlFile);
+ } catch (Exception e) {
+ throw new SvcLogicException(e.getMessage(), e);
+ }
+
+ if (graphs == null) {
+ throw new SvcLogicException("Could not parse " + xmlFile);
+ }
+
+ for (Iterator<SvcLogicGraph> iter = graphs.iterator(); iter.hasNext();) {
+ SvcLogicGraph graph = iter.next();
+ try {
+ LOGGER.info("Saving " + graph.toString() + " to database");
+ store.store(graph);
+ } catch (Exception e) {
+ throw new SvcLogicException(e.getMessage(), e);
+ }
+ }
+ }
+
+ protected ActivationEntry parseActivationEntry(String[] fileInput) {
+ return new ActivationEntry(fileInput[0], fileInput[1], fileInput[2], fileInput[3]);
+ }
+
+ protected String getValue(String raw, String attributeName) {
+ raw = raw.substring(attributeName.length() + 1);
+ if (raw.contains(">")) {
+ raw = raw.substring(0, raw.lastIndexOf('>'));
+ }
+ if (raw.endsWith("'")) {
+ raw = raw.substring(0, raw.lastIndexOf('\''));
+ }
+ if (raw.endsWith("\"")) {
+ raw = raw.substring(0, raw.lastIndexOf('"'));
+ }
+ return raw;
+ }
+
+ public void bulkActivate() {
+ Path activationFile = Paths.get(directoryRoot);
+ List<Path> pathList = new ArrayList<>(1);
+ pathList.add(activationFile);
+ List<ActivationEntry> activationEntries = processActivationFiles(pathList);
+ activateGraphs(activationEntries);
+ }
+
+}
diff --git a/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicNode.java b/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicNode.java
new file mode 100644
index 000000000..b0d4fc058
--- /dev/null
+++ b/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicNode.java
@@ -0,0 +1,457 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Modifications Copyright (C) 2018 IBM.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+/**
+ *
+ */
+package org.onap.ccsdk.sli.core.sli;
+
+import java.io.IOException;
+import java.io.PrintStream;
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import java.util.HashSet;
+import java.util.TreeMap;
+
+import org.apache.commons.text.StringEscapeUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class SvcLogicNode implements Serializable {
+
+ private static final Logger LOG = LoggerFactory
+ .getLogger(SvcLogicExprListener.class);
+
+ private static final long serialVersionUID = 2L;
+
+ private String nodeName;
+ private int nodeId;
+ private String nodeType;
+ private boolean visited;
+ private SvcLogicGraph graph;
+
+
+ private HashMap<String, SvcLogicExpression> attributes;
+ private HashMap<String, SvcLogicNode> outcomes;
+ private HashMap<String, SvcLogicExpression> parameters;
+
+ public SvcLogicNode(int nodeId, String nodeType, SvcLogicGraph graph)
+ {
+ this.nodeId = nodeId;
+ nodeName = "";
+ this.nodeType = nodeType;
+ this.graph = graph;
+ attributes = new HashMap<> ();
+ parameters = new HashMap<> ();
+ outcomes = null;
+
+ }
+
+ public SvcLogicNode(int nodeId, String nodeType, String nodeName, SvcLogicGraph graph) throws DuplicateValueException
+ {
+ this.nodeId = nodeId;
+ this.nodeName = nodeName;
+ this.nodeType = nodeType;
+ this.graph = graph;
+ attributes = new HashMap<> ();
+ parameters = new HashMap<> ();
+ outcomes = null;
+ graph.setNamedNode(nodeName, this);
+ }
+
+
+ public int getNodeId()
+ {
+ return nodeId;
+ }
+
+ public String getNodeName()
+ {
+ return nodeName;
+ }
+
+ public String getNodeType()
+ {
+ return nodeType;
+ }
+
+ public SvcLogicGraph getGraph()
+ {
+ return graph;
+ }
+
+ public int getNumOutcomes()
+ {
+ if (outcomes == null)
+ {
+ return 0;
+ }
+ else
+ {
+ return outcomes.size();
+ }
+ }
+
+ public SvcLogicExpression getAttribute(String name)
+ {
+ if (attributes.containsKey(name))
+ {
+ return attributes.get(name);
+ }
+ else
+ {
+ return null;
+ }
+
+ }
+
+ public void setAttribute(String name, String value) throws SvcLogicException
+ {
+ setAttribute(name, new SvcLogicAtom("STRING", value));
+ }
+
+ public void setAttribute(String name, SvcLogicExpression value) throws SvcLogicException
+ {
+ if (attributes.containsKey(name))
+ {
+ throw new DuplicateValueException("Duplicate attribute "+name);
+ }
+
+ attributes.put(name, value);
+ }
+
+
+ public void mapParameter(String name, String value) throws SvcLogicException
+ {
+
+ if (parameters.containsKey(name))
+ {
+ throw new DuplicateValueException("Duplicate parameter "+name);
+ }
+ try
+ {
+ SvcLogicExpression parmValue;
+ if (value == null || value.length() == 0)
+ {
+ parmValue = new SvcLogicAtom("STRING", "");
+ }
+ else if (value.trim().startsWith("`"))
+ {
+ int lastParen = value.lastIndexOf("`");
+ String evalExpr = value.trim().substring(1, lastParen);
+ parmValue = SvcLogicExpressionFactory.parse(evalExpr);
+
+ }
+ else
+ {
+ if (Character.isDigit(value.charAt(0)))
+ {
+ parmValue = new SvcLogicAtom("NUMBER", value);
+ }
+ else
+ {
+ parmValue = new SvcLogicAtom("STRING", value);
+ }
+ }
+ LOG.debug("Setting parameter "+name+" = "+value+" = "+parmValue.asParsedExpr());
+ parameters.put(name, parmValue);
+ }
+ catch (IOException e) {
+
+ LOG.error("Invalid parameter value expression ("+value+")");
+ throw new SvcLogicException(e.getMessage());
+ }
+ }
+
+ public SvcLogicExpression getParameter(String name)
+ {
+ if (parameters.containsKey(name))
+ {
+ return parameters.get(name);
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ public boolean isVisited() {
+ return visited;
+ }
+
+ public void setVisited(boolean visited, boolean recursive) {
+ this.visited = visited;
+
+ if (recursive)
+ {
+ Set<Map.Entry<String, SvcLogicNode>> outcomeSet = getOutcomeSet();
+
+ if (outcomeSet == null)
+ {
+ return;
+ }
+
+ for (Iterator<Map.Entry<String, SvcLogicNode>> iter = outcomeSet.iterator(); iter.hasNext();)
+ {
+ Map.Entry<String, SvcLogicNode> curOutcome = iter.next();
+ SvcLogicNode outNode = curOutcome.getValue();
+ outNode.setVisited(visited, recursive);
+ }
+ }
+ }
+
+ public void addOutcome(String outcomeValue, SvcLogicNode node) throws SvcLogicException
+ {
+ if (outcomes == null)
+ {
+ outcomes = new HashMap<>();
+ }
+
+ if (outcomeValue.length() == 0) {
+ outcomeValue = "\"\"";
+ }
+ if (outcomes.containsKey(outcomeValue))
+ {
+ throw new DuplicateValueException("Duplicate outcome value "+outcomeValue);
+ }
+
+ outcomes.put(outcomeValue, node);
+ }
+
+ public Set<Map.Entry<String, SvcLogicNode>> getOutcomeSet()
+ {
+ if (outcomes == null)
+ {
+ return new HashSet<>();
+ }
+
+ return outcomes.entrySet();
+
+ }
+
+ public Set<Map.Entry<String, SvcLogicExpression>> getParameterSet()
+ {
+ if (parameters == null)
+ {
+ return new HashSet<>();
+ }
+
+ return parameters.entrySet();
+
+ }
+
+ public void printAsGv(PrintStream pstr)
+ {
+
+ if (visited)
+ {
+ return;
+ }
+ else
+ {
+ visited = true;
+ }
+
+ StringBuffer sbuff = new StringBuffer();
+
+ sbuff.append("node");
+ sbuff.append(nodeId);
+ sbuff.append(" [ shape=none, margin=0, label=<<table border=\"0\" cellborder=\"1\" align=\"left\">");
+ sbuff.append("<tr><td colspan=\"2\"><b>");
+ sbuff.append(nodeId);
+ sbuff.append(" : ");
+ sbuff.append(nodeType);
+ sbuff.append("</b></td></tr><th><td><i>Attribute</i></td><td><i>Value</i></td></th>");
+
+ if (nodeName.length() > 0)
+ {
+ sbuff.append("<tr><td>name</td><td>");
+ sbuff.append(nodeName);
+ sbuff.append("</td></tr>");
+ }
+
+ Set<Map.Entry<String, SvcLogicExpression>> attrSet = attributes.entrySet();
+ for (Iterator<Map.Entry<String, SvcLogicExpression>> iter = attrSet.iterator() ; iter.hasNext();)
+ {
+ Map.Entry<String, SvcLogicExpression> curAttr = iter.next();
+ sbuff.append("<tr><td>");
+ sbuff.append(curAttr.getKey());
+ sbuff.append("</td><td>");
+ sbuff.append(StringEscapeUtils.escapeHtml3(curAttr.getValue().toString()));
+ sbuff.append("</td></tr>");
+ }
+ sbuff.append("</table>>];");
+
+ pstr.println(sbuff.toString());
+
+
+ if (outcomes != null)
+ {
+ TreeMap<String, SvcLogicNode> sortedOutcomes = new TreeMap<>(outcomes);
+ Set<Map.Entry<String, SvcLogicNode>> outcomeSet = sortedOutcomes.entrySet();
+
+ for (Iterator<Map.Entry<String, SvcLogicNode>> iter = outcomeSet.iterator(); iter.hasNext();)
+ {
+ Map.Entry<String, SvcLogicNode> curOutcome = iter.next();
+ String outValue = curOutcome.getKey();
+ SvcLogicNode outNode = curOutcome.getValue();
+ pstr.println("node"+nodeId+" -> node"+outNode.getNodeId()+" [label=\""+outValue+"\"];");
+ outNode.printAsGv(pstr);
+ }
+ }
+ }
+
+ public void printAsXml(PrintStream pstr, int indentLvl)
+ {
+ if (visited)
+ {
+ return;
+ }
+ // Print node tag
+ for (int i = 0 ; i < indentLvl ; i++)
+ {
+ pstr.print(" ");
+ }
+ pstr.print("<");
+ pstr.print(this.getNodeType());
+
+ Set<Map.Entry<String, SvcLogicExpression>> attrSet = attributes.entrySet();
+ for (Iterator<Map.Entry<String, SvcLogicExpression>> iter = attrSet.iterator() ; iter.hasNext();)
+ {
+ Map.Entry<String, SvcLogicExpression> curAttr = iter.next();
+ pstr.print(" ");
+ pstr.print(curAttr.getKey());
+ pstr.print("='`");
+ pstr.print(curAttr.getValue());
+ pstr.print("'`");
+ }
+
+ if ((parameters == null || parameters.isEmpty()) &&
+ (outcomes == null || outcomes.isEmpty()))
+ {
+ pstr.print("/>\n");
+ pstr.flush();
+ return;
+ }
+ else
+ {
+ pstr.print(">\n");
+ }
+
+ // Print parameters (if any)
+ if (parameters != null)
+ {
+ Set<Map.Entry<String, SvcLogicExpression>> paramSet = parameters.entrySet();
+ for (Iterator<Map.Entry<String, SvcLogicExpression>> iter = paramSet.iterator() ; iter.hasNext();)
+ {
+ for (int i = 0 ; i < indentLvl+1 ; i++)
+ {
+ pstr.print(" ");
+ }
+ pstr.print("<parameter");
+ Map.Entry<String, SvcLogicExpression> curAttr = iter.next();
+ pstr.print(" name='");
+ pstr.print(curAttr.getKey());
+ pstr.print("' value='`");
+ pstr.print(curAttr.getValue().toString());
+ pstr.print("`'/>\n");
+ }
+ }
+
+ // Print outcomes (if any)
+ if (outcomes != null)
+ {
+ Set<Map.Entry<String, SvcLogicNode>> outcomeSet = outcomes.entrySet();
+ for (Iterator<Map.Entry<String, SvcLogicNode>> iter = outcomeSet.iterator() ; iter.hasNext();)
+ {
+ for (int i = 0 ; i < indentLvl+1 ; i++)
+ {
+ pstr.print(" ");
+ }
+ pstr.print("<outcome");
+ Map.Entry<String, SvcLogicNode> curAttr = iter.next();
+ pstr.print(" value='");
+ pstr.print(curAttr.getKey());
+ pstr.print("'>\n");
+ SvcLogicNode outNode = curAttr.getValue();
+ outNode.printAsXml(pstr, indentLvl+2);
+ for (int i = 0 ; i < indentLvl+1 ; i++)
+ {
+ pstr.print(" ");
+ }
+ pstr.print("</outcome>\n");
+ }
+ }
+
+ // Print node end tag
+ for (int i = 0 ; i < indentLvl ; i++)
+ {
+ pstr.print(" ");
+ }
+ pstr.print("</");
+ pstr.print(this.getNodeType());
+ pstr.print(">\n");
+ pstr.flush();
+
+ }
+
+
+ public SvcLogicNode getOutcomeValue(String value)
+ {
+
+ if (value.length() == 0) {
+ value = "\"\"";
+ }
+ if (outcomes == null)
+ {
+ return null;
+ }
+
+ if (outcomes.containsKey(value))
+ {
+ return outcomes.get(value);
+ }
+ else
+ {
+ StringBuffer keyBuffer = new StringBuffer();
+ keyBuffer.append("{");
+ for (String key : outcomes.keySet()) {
+ keyBuffer.append(" ("+key+")");
+ }
+ keyBuffer.append("}");
+ LOG.info("Outcome (" + value + ") not found, keys are " + keyBuffer.toString());
+
+ if (outcomes.containsKey("Other"))
+ {
+ return outcomes.get("Other");
+ }
+ else
+ {
+ return null;
+ }
+ }
+ }
+}
diff --git a/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicParser.java b/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicParser.java
new file mode 100644
index 000000000..adec7b27d
--- /dev/null
+++ b/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicParser.java
@@ -0,0 +1,615 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.sli;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URL;
+import java.util.LinkedList;
+import javax.xml.XMLConstants;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+import javax.xml.validation.Schema;
+import javax.xml.validation.SchemaFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.xml.sax.*;
+import org.xml.sax.helpers.DefaultHandler;
+import org.onap.ccsdk.sli.core.utils.PathValidator;
+
+/**
+ * @author dt5972
+ *
+ */
+public class SvcLogicParser {
+
+ static final String JAXP_SCHEMA_LANGUAGE = "http://java.sun.com/xml/jaxp/properties/schemaLanguage";
+ static final String W3C_XML_SCHEMA = "http://www.w3.org/2001/XMLSchema";
+ static final String JAXP_SCHEMA_SOURCE = "http://java.sun.com/xml/jaxp/properties/schemaSource";
+ static final String JAXP_DYNAMIC_VALIDATION = "http://apache.org/xml/features/validation/dynamic";
+ static final String JAXP_SCHEMA_VALIDATION = "http://apache.org/xml/features/validation/schema";
+
+ private static final String LOAD_MESSAGE = "Getting SvcLogicGraph from database - {}";
+ private static final String LOAD_ERROR_MESSAGE = "SvcLogicGraph not found - {}";
+ private static final String ACTIVATION_ERROR_MESSAGE = "Could not activate SvcLogicGraph - {}";
+ private static final String PRINT_ERROR_MESSAGE = "Could not print SvcLogicGraph - {}";
+ private static final String SVC_LOGIC_STORE_ERROR = "Could not get service logic store";
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(SvcLogicParser.class);
+ private static final String SLI_VALIDATING_PARSER = "org.onap.ccsdk.sli.parser.validate";
+ private static final String SVCLOGIC_XSD = "/svclogic.xsd";
+ private SAXParser saxParser;
+
+ private class SvcLogicHandler extends DefaultHandler {
+ private Locator locator = null;
+ private String module = null;
+ private String version = null;
+ private LinkedList<SvcLogicGraph> graphs = null;
+ private SvcLogicGraph curGraph = null;
+ private SvcLogicNode curNode = null;
+ private LinkedList<SvcLogicNode> nodeStack = null;
+ private int curNodeId = 0;
+ private String outcomeValue = null;
+ private LinkedList<String> outcomeStack = null;
+
+ public SvcLogicHandler(LinkedList<SvcLogicGraph> graphs) {
+ this.graphs = graphs;
+ this.curNode = null;
+ this.nodeStack = new LinkedList<>();
+ this.outcomeStack = new LinkedList<>();
+ this.curNodeId = 1;
+ this.outcomeValue = null;
+ }
+
+ @Override
+ public void setDocumentLocator(Locator locator) {
+ this.locator = locator;
+ }
+
+ @Override
+ public void startElement(String uri, String localName, String qName, Attributes attributes)
+ throws SAXException {
+
+ // Handle service-logic (graph) tag
+ if ("service-logic".equalsIgnoreCase(qName)) {
+
+ module = attributes.getValue("module");
+ if (module == null || module.length() == 0) {
+ throw new SAXException("line " + locator.getLineNumber() + ":" + locator.getColumnNumber() + " "
+ + "Missing 'module' attribute from service-logic tag");
+ }
+
+ version = attributes.getValue("version");
+ if (version == null || version.length() == 0) {
+ throw new SAXException("line " + locator.getLineNumber() + ":" + locator.getColumnNumber() + " "
+ + "Missing 'version' attribute from service-logic tag");
+ }
+
+ return;
+ }
+
+ if ("method".equalsIgnoreCase(qName)) {
+
+ if (curGraph != null) {
+ throw new SAXException("line " + locator.getLineNumber() + ":" + locator.getColumnNumber() + " "
+ + "Cannot nest module tags");
+ }
+
+ curGraph = new SvcLogicGraph();
+ curGraph.setModule(module);
+ curGraph.setVersion(version);
+ this.curNodeId = 1;
+
+ String attrValue = attributes.getValue("rpc");
+ if (attrValue == null || attrValue.length() == 0) {
+ throw new SAXException("line " + locator.getLineNumber() + ":" + locator.getColumnNumber() + " "
+ + "Missing 'rpc' attribute for method tag");
+ }
+ curGraph.setRpc(attrValue);
+
+ attrValue = attributes.getValue("mode");
+ if (attrValue == null || attrValue.length() == 0) {
+ throw new SAXException("line " + locator.getLineNumber() + ":" + locator.getColumnNumber() + " "
+ + "Missing 'mode' attribute for method tag");
+ }
+ curGraph.setMode(attrValue);
+
+ return;
+ }
+
+ // Handle outcome (edge) tag
+ if ("outcome".equalsIgnoreCase(qName)) {
+ String refValue = attributes.getValue("ref");
+
+ if (refValue != null) {
+ SvcLogicNode refNode = curGraph.getNamedNode(refValue);
+
+ if (refNode != null) {
+ try {
+ curNode.addOutcome(attributes.getValue("value"), refNode);
+ } catch (SvcLogicException e) {
+ throw new SAXException("line " + locator.getLineNumber() + ":" + locator.getColumnNumber()
+ + " " + "Cannot add outcome", e);
+ }
+ } else {
+ throw new SAXException("line " + locator.getLineNumber() + ":" + locator.getColumnNumber() + " "
+ + "ref to unknown node " + refValue);
+ }
+ return;
+ }
+
+ if (outcomeValue != null) {
+ outcomeStack.push(outcomeValue);
+ }
+ outcomeValue = attributes.getValue("value");
+
+ return;
+ }
+
+ // Handle parameter tag
+ if ("parameter".equalsIgnoreCase(qName)) {
+ String parmName = attributes.getValue("name");
+ String parmValue = attributes.getValue("value");
+
+ if (parmName != null && parmName.length() > 0 && parmValue != null) {
+ try {
+
+ curNode.mapParameter(parmName, parmValue);
+ } catch (Exception e) {
+ throw new SAXException("line " + locator.getLineNumber() + ":" + locator.getColumnNumber() + " "
+ + " cannot set parameter " + parmName + " to " + parmValue + " [" + e.getMessage()
+ + "]");
+ }
+ }
+
+ return;
+ }
+
+ // Handle node tags
+ String nodeName = attributes.getValue("name");
+ SvcLogicNode thisNode;
+
+
+ try {
+ if (nodeName != null && nodeName.length() > 0) {
+ thisNode = new SvcLogicNode(curNodeId++, qName, nodeName, curGraph);
+ } else {
+ thisNode = new SvcLogicNode(curNodeId++, qName, curGraph);
+ }
+
+ if (curGraph.getRootNode() == null) {
+ curGraph.setRootNode(thisNode);
+ }
+ } catch (SvcLogicException e) {
+ throw new SAXException(
+ "line " + locator.getLineNumber() + ":" + locator.getColumnNumber() + " " + e.getMessage());
+
+ }
+
+ int numAttributes = attributes.getLength();
+
+ for (int i = 0; i < numAttributes; i++) {
+ String attrName = attributes.getQName(i);
+ if (!"name".equalsIgnoreCase(attrName)) {
+ try {
+
+ String attrValueStr = attributes.getValue(i);
+ SvcLogicExpression attrValue;
+ if (attrValueStr.trim().startsWith("`")) {
+ int lastParen = attrValueStr.lastIndexOf('`');
+ String evalExpr = attrValueStr.trim().substring(1, lastParen);
+ attrValue = SvcLogicExpressionFactory.parse(evalExpr);
+
+ } else {
+ if (Character.isDigit(attrValueStr.charAt(0))) {
+ attrValue = new SvcLogicAtom("NUMBER", attrValueStr);
+ } else {
+ attrValue = new SvcLogicAtom("STRING", attrValueStr);
+ }
+ }
+ thisNode.setAttribute(attrName, attrValue);
+ } catch (Exception e) {
+ throw new SAXException("line " + locator.getLineNumber() + ":" + locator.getColumnNumber() + " "
+ + "Cannot set attribute " + attrName, e);
+ }
+ }
+ }
+
+ if (curNode != null) {
+ try {
+ if ("block".equalsIgnoreCase(curNode.getNodeType()) || "for".equalsIgnoreCase(curNode.getNodeType())
+ || "while".equalsIgnoreCase(curNode.getNodeType())) {
+ curNode.addOutcome(Integer.toString(curNode.getNumOutcomes() + 1), thisNode);
+ } else {
+ if (outcomeValue == null) {
+ throw new SAXException("line " + locator.getLineNumber() + ":" + locator.getColumnNumber()
+ + " " + curNode.getNodeType() + " node expects outcome, instead found "
+ + thisNode.getNodeType());
+ }
+ curNode.addOutcome(outcomeValue, thisNode);
+ }
+ } catch (SvcLogicException e) {
+ throw new SAXException(
+ "line " + locator.getLineNumber() + ":" + locator.getColumnNumber() + " " + e.getMessage());
+ }
+ nodeStack.push(curNode);
+ }
+ curNode = thisNode;
+
+ }
+
+ @Override
+ public void endElement(String uri, String localName, String qName) throws SAXException {
+
+ // Handle close of service-logic tag
+ if ("service-logic".equalsIgnoreCase(qName)) {
+ // Nothing more to do
+ return;
+ }
+
+ // Handle close of method tag
+ if ("method".equalsIgnoreCase(qName)) {
+ graphs.add(curGraph);
+ curGraph = null;
+ return;
+ }
+
+ // Handle close of outcome tag
+ if ("outcome".equalsIgnoreCase(qName)) {
+ // Finished this outcome - pop the outcome stack
+ if (outcomeStack.isEmpty()) {
+ outcomeValue = null;
+ } else {
+ outcomeValue = outcomeStack.pop();
+ }
+ return;
+ }
+
+ // Handle close of parameter tag - do nothing
+ if ("parameter".equalsIgnoreCase(qName)) {
+ return;
+ }
+
+ // Handle close of a node tag
+ if (nodeStack.isEmpty()) {
+ curNode = null;
+ } else {
+ curNode = nodeStack.pop();
+ }
+ }
+
+ @Override
+ public void error(SAXParseException arg0) throws SAXException {
+ throw new SAXException(
+ "line " + locator.getLineNumber() + ":" + locator.getColumnNumber() + " " + arg0.getMessage());
+ }
+
+ }
+
+ public LinkedList<SvcLogicGraph> parse(String fileName) throws SvcLogicException {
+ LinkedList<SvcLogicGraph> graphs;
+
+ try {
+ if (saxParser == null) {
+ saxParser = initParser();
+ }
+
+ graphs = new LinkedList<>();
+ saxParser.parse(fileName, new SvcLogicHandler(graphs));
+
+ try {
+ for (SvcLogicGraph graph : graphs) {
+ graph.setMd5sum(CheckSumHelper.md5SumFromFile(fileName));
+ }
+ } catch (Exception exc) {
+ LOGGER.error("Couldn't set md5sum on graphs", exc);
+ }
+ } catch (Exception e) {
+ LOGGER.error("Parsing failed ", e);
+ String msg = e.getMessage();
+ if (msg != null) {
+ throw new SvcLogicException("Compiler error: " + fileName + " @ " + msg);
+ } else {
+ throw new SvcLogicException("Compiler error: " + fileName, e);
+ }
+ }
+ return graphs;
+ }
+
+ public static void main(String argv[]) {
+
+ if (argv.length == 0) {
+ SvcLogicParser.usage();
+ }
+
+ if ("load".equalsIgnoreCase(argv[0])) {
+ if (argv.length == 3) {
+ String xmlfile = argv[1];
+ String propfile = argv[2];
+
+ SvcLogicStore store = SvcLogicParser.getStore(propfile);
+ try {
+ SvcLogicParser.load(xmlfile, store);
+ } catch (Exception e) {
+ LOGGER.error("Load failed ", e);
+ }
+ } else {
+ SvcLogicParser.usage();
+ }
+ } else if ("print".equalsIgnoreCase(argv[0])) {
+ String version = null;
+ String propfile = null;
+
+ switch (argv.length) {
+ case 6:
+ version = argv[4];
+ propfile = argv[5];
+ case 5:
+ if (propfile == null) {
+ propfile = argv[4];
+ }
+ SvcLogicStore store = SvcLogicParser.getStore(propfile);
+ SvcLogicParser.print(argv[1], argv[2], argv[3], version, store);
+ break;
+ default:
+ SvcLogicParser.usage();
+ }
+ } else if ("get-source".equalsIgnoreCase(argv[0])) {
+
+ if (argv.length == 6) {
+ SvcLogicStore store = SvcLogicParser.getStore(argv[5]);
+ SvcLogicParser.getSource(argv[1], argv[2], argv[3], argv[4], store);
+ } else {
+ SvcLogicParser.usage();
+ }
+ } else if ("activate".equalsIgnoreCase(argv[0])) {
+ if (argv.length == 6) {
+ SvcLogicStore store = SvcLogicParser.getStore(argv[5]);
+ SvcLogicParser.activate(argv[1], argv[2], argv[3], argv[4], store);
+ } else {
+ SvcLogicParser.usage();
+ }
+ } else if ("validate".equalsIgnoreCase(argv[0])) {
+ if (argv.length == 3) {
+ String xmlfile = argv[1];
+ String propfile = argv[2];
+
+ System.setProperty(SLI_VALIDATING_PARSER, "true");
+ SvcLogicStore store = SvcLogicParser.getStore(propfile);
+ try {
+ SvcLogicParser.validate(xmlfile, store);
+ } catch (Exception e) {
+ LOGGER.error("Validate failed", e);
+ }
+ } else {
+ SvcLogicParser.usage();
+ }
+ } else if ("install".equalsIgnoreCase(argv[0])) {
+ if (argv.length == 3) {
+ SvcLogicLoader loader = new SvcLogicLoader(argv[1], argv[2]);
+ try {
+ loader.loadAndActivate();
+ } catch (IOException e) {
+ LOGGER.error(e.getMessage(), e);
+ }
+ } else {
+ SvcLogicParser.usage();
+ }
+ } else if ("bulkActivate".equalsIgnoreCase(argv[0])) {
+ if (argv.length == 3) {
+ SvcLogicLoader loader = new SvcLogicLoader(argv[1], argv[2]);
+ try {
+ loader.bulkActivate();
+ } catch (Exception e) {
+ LOGGER.error(e.getMessage(), e);
+ }
+ } else {
+ SvcLogicParser.usage();
+ }
+ }
+
+ System.exit(0);
+ }
+
+ protected static SvcLogicStore getStore(String propfile) {
+
+ SvcLogicStore store = null;
+
+ try {
+ store = SvcLogicStoreFactory.getSvcLogicStore(propfile);
+ } catch (Exception e) {
+ LOGGER.error(SVC_LOGIC_STORE_ERROR, e);
+ System.exit(1);
+ }
+
+ return store;
+
+ }
+
+
+ public static void load(String xmlfile, SvcLogicStore store) throws SvcLogicException {
+ if (!PathValidator.isValidXmlPath(xmlfile)) {
+ throw new ConfigurationException("Invalid xml file name ("+ xmlfile + ")");
+ }
+ File xmlFile = new File(xmlfile);
+ if (!xmlFile.canRead()) {
+ throw new ConfigurationException("Cannot read xml file (" + xmlfile + ")");
+ }
+
+ SvcLogicParser parser = new SvcLogicParser();
+ LinkedList<SvcLogicGraph> graphs;
+ try {
+ LOGGER.info("Loading {}", xmlfile);
+ graphs = parser.parse(xmlfile);
+ } catch (Exception e) {
+ throw new SvcLogicException(e.getMessage(), e);
+ }
+
+ if (graphs == null) {
+ throw new SvcLogicException("Could not parse " + xmlfile);
+ }
+
+ for (SvcLogicGraph graph : graphs) {
+
+ try {
+ LOGGER.info("Saving " + graph.toString() + " to database.");
+ store.store(graph);
+ } catch (Exception e) {
+ throw new SvcLogicException(e.getMessage(), e);
+ }
+
+ }
+
+ }
+
+ public static void validate(String xmlfile, SvcLogicStore store) throws SvcLogicException {
+ if (!PathValidator.isValidXmlPath(xmlfile)) {
+ throw new ConfigurationException("Invalid xml file name ("+ xmlfile + ")");
+ }
+ File xmlFile = new File(xmlfile);
+ if (!xmlFile.canRead()) {
+ throw new ConfigurationException("Cannot read xml file (" + xmlfile + ")");
+ }
+
+ SvcLogicParser parser = new SvcLogicParser();
+ LinkedList<SvcLogicGraph> graphs;
+ try {
+ LOGGER.info("Validating {}", xmlfile);
+ graphs = parser.parse(xmlfile);
+ } catch (Exception e) {
+ throw new SvcLogicException(e.getMessage(), e);
+ }
+
+ if (graphs == null) {
+ throw new SvcLogicException("Could not parse " + xmlfile);
+ } else {
+ LOGGER.info("Compilation successful for {}", xmlfile);
+ }
+
+ }
+
+ private static void print(String module, String rpc, String mode, String version, SvcLogicStore store) {
+ String details = "(module:" + module + ", rpc:" + rpc + ", version:" + version + ", mode:" + mode + ")";
+
+ try {
+ LOGGER.info(LOAD_MESSAGE, details);
+
+ SvcLogicGraph graph = store.fetch(module, rpc, version, mode);
+ if (graph == null) {
+ LOGGER.error(LOAD_ERROR_MESSAGE, details);
+ System.exit(1);
+ }
+ graph.printAsGv(System.out);
+ } catch (Exception e) {
+ LOGGER.error(PRINT_ERROR_MESSAGE, details, e);
+ System.exit(1);
+ }
+
+ }
+
+ private static void getSource(String module, String rpc, String mode, String version, SvcLogicStore store) {
+ String details = "(module:" + module + ", rpc:" + rpc + ", version:" + version + ", mode:" + mode + ")";
+
+ try {
+ LOGGER.info(LOAD_MESSAGE, details);
+
+ SvcLogicGraph graph = store.fetch(module, rpc, version, mode);
+ if (graph == null) {
+ LOGGER.error(LOAD_ERROR_MESSAGE, details);
+ System.exit(1);
+ }
+ graph.printAsXml(System.out);
+ } catch (Exception e) {
+ LOGGER.error(PRINT_ERROR_MESSAGE, details, e);
+ System.exit(1);
+ }
+
+ }
+
+ public static void activate(String module, String rpc, String version, String mode, SvcLogicStore store) {
+ String details = "(module:" + module + ", rpc:" + rpc + ", version:" + version + ", mode:" + mode + ")";
+
+ try {
+ LOGGER.info(LOAD_MESSAGE, details);
+
+ SvcLogicGraph graph = store.fetch(module, rpc, version, mode);
+ if (graph == null) {
+ LOGGER.error(LOAD_ERROR_MESSAGE, details);
+ System.exit(1);
+ }
+ store.activate(graph);
+ } catch (Exception e) {
+ LOGGER.error(ACTIVATION_ERROR_MESSAGE, details, e);
+ System.exit(1);
+ }
+
+ }
+
+ private static void usage() {
+ System.err.println("Usage: SvcLogicParser load <xml-file> <prop-file>");
+ System.err.println(" OR SvcLogicParser print <module> <rpc> <mode> [<version>] <prop-file>");
+ System.err.println(" OR SvcLogicParser get-source <module> <rpc> <mode> <version> <prop-file>");
+ System.err.println(" OR SvcLogicParser activate <module> <rpc> <version> <mode>");
+ System.err.println(" OR SvcLogicParser validate <file path to graph> <prop-file>");
+ System.err.println(" OR SvcLogicParser install <service-logic directory path> <prop-file>");
+ System.err.println(" OR SvcLogicParser bulkActivate <path to activation file> <prop-file>");
+ System.exit(1);
+ }
+
+ protected SAXParser initParser() throws ParserConfigurationException, SAXException {
+ URL xsdUrl = null;
+ Schema schema = null;
+ String validateSchema = System.getProperty(SLI_VALIDATING_PARSER, "true");
+
+ if ("true".equalsIgnoreCase(validateSchema)) {
+ xsdUrl = getClass().getResource(SVCLOGIC_XSD);
+ }
+
+ if (xsdUrl != null) {
+ try {
+ SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
+ schema = schemaFactory.newSchema(xsdUrl);
+ LOGGER.info("Schema path {}", xsdUrl.getPath());
+ } catch (Exception e) {
+ LOGGER.warn("Could not validate using schema {}", xsdUrl.getPath(), e);
+ }
+ } else {
+ LOGGER.warn("Could not find resource {}", SVCLOGIC_XSD);
+ }
+
+ SAXParserFactory factory = SAXParserFactory.newInstance();
+
+ if (schema != null) {
+ factory.setNamespaceAware(true);
+ factory.setSchema(schema);
+ }
+
+ SAXParser saxParser = factory.newSAXParser();
+ if (saxParser.isValidating()) {
+ LOGGER.info("Parser configured to validate XML {}", (xsdUrl != null ? xsdUrl.getPath() : null));
+ }
+ return saxParser;
+ }
+
+
+}
diff --git a/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicParserException.java b/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicParserException.java
new file mode 100644
index 000000000..61f80f7e2
--- /dev/null
+++ b/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicParserException.java
@@ -0,0 +1,43 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.sli;
+
+import java.io.IOException;
+
+public class SvcLogicParserException extends IOException {
+
+ public SvcLogicParserException() {
+ super();
+ }
+
+ public SvcLogicParserException(String msg) {
+ super(msg);
+ }
+
+ public SvcLogicParserException(Throwable t) {
+ super(t);
+ }
+
+ public SvcLogicParserException(String msg, Throwable t) {
+ super(msg, t);
+ }
+}
diff --git a/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicRecorder.java b/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicRecorder.java
new file mode 100644
index 000000000..ca13536bb
--- /dev/null
+++ b/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicRecorder.java
@@ -0,0 +1,30 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.sli;
+
+import java.util.Map;
+
+public interface SvcLogicRecorder {
+
+ void record(Map<String, String> parmMap) throws SvcLogicException;
+
+}
diff --git a/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicResource.java b/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicResource.java
new file mode 100644
index 000000000..0e2c42574
--- /dev/null
+++ b/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicResource.java
@@ -0,0 +1,52 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.sli;
+
+import java.util.Map;
+
+public interface SvcLogicResource {
+
+ public enum QueryStatus {
+ SUCCESS,
+ NOT_FOUND,
+ FAILURE
+ }
+
+ public QueryStatus isAvailable(String resource, String key, String prefix, SvcLogicContext ctx) throws SvcLogicException;
+
+ public QueryStatus exists(String resource, String key, String prefix, SvcLogicContext ctx) throws SvcLogicException;
+
+ public QueryStatus query(String resource, boolean localOnly, String select, String key, String prefix, String orderBy, SvcLogicContext ctx) throws SvcLogicException;
+
+ public QueryStatus reserve(String resource, String select, String key, String prefix, SvcLogicContext ctx) throws SvcLogicException;
+
+ public QueryStatus save(String resource, boolean force, boolean localOnly, String key, Map<String, String> parms, String prefix, SvcLogicContext ctx) throws SvcLogicException;
+
+ public QueryStatus release(String resource, String key, SvcLogicContext ctx) throws SvcLogicException;
+
+ public QueryStatus delete(String resource, String key, SvcLogicContext ctx) throws SvcLogicException;
+
+ public QueryStatus notify(String resource, String action, String key, SvcLogicContext ctx) throws SvcLogicException;
+
+ public QueryStatus update(String resource, String key, Map<String, String> parms, String prefix, SvcLogicContext ctx) throws SvcLogicException;
+
+}
diff --git a/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicStore.java b/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicStore.java
new file mode 100644
index 000000000..2eda67f11
--- /dev/null
+++ b/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicStore.java
@@ -0,0 +1,36 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.sli;
+
+import java.util.Properties;
+
+public interface SvcLogicStore {
+
+ public void init(Properties props) throws SvcLogicException;
+ public boolean hasGraph(String module, String rpc, String version, String mode) throws SvcLogicException;
+ public SvcLogicGraph fetch(String module, String rpc, String version, String mode) throws SvcLogicException;
+ public void store(SvcLogicGraph graph) throws SvcLogicException;
+ public void delete(String module, String rpc, String version, String mode) throws SvcLogicException;
+ public void activate(SvcLogicGraph graph) throws SvcLogicException;
+ public void activate(String module, String rpc, String version, String mode) throws SvcLogicException;
+
+}
diff --git a/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicStoreFactory.java b/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicStoreFactory.java
new file mode 100644
index 000000000..e0eb57304
--- /dev/null
+++ b/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicStoreFactory.java
@@ -0,0 +1,100 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.sli;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.util.Properties;
+import org.onap.ccsdk.sli.core.dblib.DBResourceManager;
+import org.onap.ccsdk.sli.core.utils.PathValidator;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class SvcLogicStoreFactory {
+
+ private static final Logger LOG = LoggerFactory.getLogger(SvcLogicStoreFactory.class);
+
+ public static SvcLogicStore getSvcLogicStore(String propfile)
+ throws SvcLogicException {
+ if (!PathValidator.isValidPropertiesPath(propfile)) {
+ throw new ConfigurationException("Invalid property file name ("+propfile+")");
+ }
+ File propFile = new File(propfile);
+ if (!propFile.canRead()) {
+ throw new ConfigurationException("Cannot read property file "
+ + propfile);
+
+ }
+
+ try {
+ return getSvcLogicStore(new FileInputStream(propFile));
+ } catch (Exception e) {
+ throw new ConfigurationException(
+ "Could load service store from properties file " + propfile,
+ e);
+ }
+
+ }
+
+ public static SvcLogicStore getSvcLogicStore(InputStream inStr) throws SvcLogicException
+ {
+ Properties props = new Properties();
+
+ try {
+ props.load(inStr);
+ } catch (Exception e) {
+ throw new ConfigurationException("Could not get load properties from input stream", e);
+ }
+
+ return getSvcLogicStore(props);
+ }
+
+ public static SvcLogicStore getSvcLogicStore(Properties props)
+ throws SvcLogicException {
+ String storeType = props.getProperty("org.onap.ccsdk.sli.dbtype");
+ if ((storeType == null) || (storeType.length() == 0)) {
+ throw new ConfigurationException(
+ "property org.onap.ccsdk.sli.dbtype unset");
+
+ }
+
+ SvcLogicStore retval;
+ LOG.debug("Using org.onap.ccsdk.sli.dbtype={}", storeType);
+
+ if ("jdbc".equalsIgnoreCase(storeType)) {
+ retval = new SvcLogicJdbcStore();
+
+ } else if ("dblib".equalsIgnoreCase(storeType)) {
+ retval = new SvcLogicDblibStore(new DBResourceManager(props));
+ } else {
+ throw new ConfigurationException("unsupported dbtype (" + storeType
+ + ")");
+
+ }
+
+
+ retval.init(props);
+ return retval;
+ }
+
+}
diff --git a/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicVariableTerm.java b/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicVariableTerm.java
new file mode 100644
index 000000000..4edf3ecbe
--- /dev/null
+++ b/core/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicVariableTerm.java
@@ -0,0 +1,77 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.sli;
+
+public class SvcLogicVariableTerm extends SvcLogicExpression {
+
+ private String name = null;
+
+ public String getName() {
+ return name;
+ }
+
+
+ public SvcLogicVariableTerm(String identifier)
+ {
+ this.name = identifier;
+ }
+
+ public SvcLogicExpression getSubscript()
+ {
+ if (numOperands() > 0)
+ {
+ return(getOperands().get(0));
+ }
+ else
+ {
+ return(null);
+ }
+ }
+
+ @Override
+ public String toString()
+ {
+ String retval;
+
+ if (numOperands() > 0)
+ {
+ retval = name + "[" + getSubscript().toString() + "]";
+ }
+ else
+ {
+ retval = name;
+ }
+ return(retval);
+ }
+
+ @Override
+ public String asParsedExpr() {
+ if (numOperands() == 0) {
+ return("(variable-term "+name+")");
+ }
+ else
+ {
+ return("(variable-term "+name+" "+getSubscript().asParsedExpr()+")");
+ }
+ }
+
+}
diff --git a/core/sli/common/src/main/resources/svclogic.xsd b/core/sli/common/src/main/resources/svclogic.xsd
new file mode 100755
index 000000000..c9beae83e
--- /dev/null
+++ b/core/sli/common/src/main/resources/svclogic.xsd
@@ -0,0 +1,339 @@
+<?xml version = "1.0" encoding = "UTF-8"?>
+<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.onap.org/sdnc/svclogic" xmlns="http://www.onap.org/sdnc/svclogic">
+
+ <xsd:simpleType name="modeType">
+ <xsd:restriction base="xsd:string">
+ <xsd:enumeration value="sync" />
+ <xsd:enumeration value="async" />
+ </xsd:restriction>
+ </xsd:simpleType>
+
+ <xsd:group name="node">
+ <xsd:choice>
+ <xsd:element ref="block" />
+ <xsd:element ref="is-available" />
+ <xsd:element ref="exists" />
+ <xsd:element ref="reserve" />
+ <xsd:element ref="release" />
+ <xsd:element ref="allocate" />
+ <xsd:element ref="get-resource" />
+ <xsd:element ref="configure" />
+ <xsd:element ref="return" />
+ <xsd:element ref="switch" />
+ <xsd:element ref="record" />
+ <xsd:element ref="save" />
+ <xsd:element ref="for" />
+ <xsd:element ref="set" />
+ <xsd:element ref="execute" />
+ <xsd:element ref="delete" />
+ <xsd:element ref="update" />
+ <xsd:element ref="call" />
+ <xsd:element ref="notify" />
+ <xsd:element ref="break" />
+ <xsd:element ref="while" />
+ <xsd:element ref="exit" />
+ </xsd:choice>
+ </xsd:group>
+
+ <xsd:element name="service-logic">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="method" minOccurs="0" maxOccurs="100" />
+ </xsd:sequence>
+ <xsd:attribute name="module" use="required" type="xsd:string" />
+ <xsd:attribute name="version" use="required" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="method">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:group ref="node" minOccurs="0" maxOccurs="100" />
+ </xsd:sequence>
+ <xsd:attribute name="rpc" use="required" type="xsd:string" />
+ <xsd:attribute name="mode" use="optional" type="modeType" />
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="block">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:group ref="node" minOccurs="0" maxOccurs="100" />
+ </xsd:sequence>
+ <xsd:attribute name="atomic" use="optional" type="xsd:boolean" />
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="is-available">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="outcome" minOccurs="0" maxOccurs="100" />
+ </xsd:sequence>
+ <xsd:attribute name="pfx" use="optional" type="xsd:string" />
+ <xsd:attribute name="plugin" use="required" type="xsd:string" />
+ <xsd:attribute name="resource" use="required" type="xsd:string" />
+ <xsd:attribute name="key" use="optional" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="exists">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="outcome" minOccurs="0" maxOccurs="100" />
+ </xsd:sequence>
+ <xsd:attribute name="pfx" use="optional" type="xsd:string" />
+ <xsd:attribute name="plugin" use="required" type="xsd:string" />
+ <xsd:attribute name="resource" use="required" type="xsd:string" />
+ <xsd:attribute name="key" use="required" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="outcome">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:group ref="node" minOccurs="0" maxOccurs="100" />
+ </xsd:sequence>
+ <xsd:attribute name="ref" use="optional" type="xsd:string" />
+ <xsd:attribute name="value" use="required" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="reserve">
+ <xsd:complexType>
+ <xsd:sequence>
+ <!-- This node does not actually read from parameters -->
+ <xsd:element ref="parameter" minOccurs="0" maxOccurs="100" />
+ <xsd:element ref="outcome" minOccurs="0" maxOccurs="100" />
+ </xsd:sequence>
+ <xsd:attribute name="plugin" use="required" type="xsd:string" />
+ <xsd:attribute name="resource" use="required" type="xsd:string" />
+ <xsd:attribute name="key" use="optional" type="xsd:string" />
+ <xsd:attribute name="select" use="optional" type="xsd:string" />
+ <xsd:attribute name="pfx" use="optional" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="release">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="outcome" minOccurs="0" maxOccurs="100" />
+ </xsd:sequence>
+ <xsd:attribute name="plugin" use="required" type="xsd:string" />
+ <xsd:attribute name="resource" use="required" type="xsd:string" />
+ <xsd:attribute name="key" use="optional" type="xsd:string" />
+ <xsd:attribute name="pfx" use="optional" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="record">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="parameter" minOccurs="0" maxOccurs="100" />
+ <xsd:element ref="outcome" minOccurs="0" maxOccurs="100" />
+ </xsd:sequence>
+ <xsd:attribute name="plugin" use="required" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="allocate">
+ <xsd:complexType>
+ <xsd:sequence>
+ <!-- This node does not actually read from parameters -->
+ <xsd:element ref="parameter" minOccurs="0" maxOccurs="100" />
+ <xsd:element ref="outcome" minOccurs="0" maxOccurs="100" />
+ </xsd:sequence>
+ <xsd:attribute name="plugin" use="required" type="xsd:string" />
+ <xsd:attribute name="resource" use="required" type="xsd:string" />
+ <xsd:attribute name="key" use="required" type="xsd:string" />
+ <xsd:attribute name="pfx" use="required" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="get-resource">
+ <xsd:complexType>
+ <xsd:sequence>
+ <!-- This node does not actually read from parameters -->
+ <xsd:element ref="parameter" minOccurs="0" maxOccurs="100" />
+ <xsd:element ref="outcome" minOccurs="0" maxOccurs="100" />
+ </xsd:sequence>
+ <xsd:attribute name="plugin" use="required" type="xsd:string" />
+ <xsd:attribute name="resource" use="required" type="xsd:string" />
+ <xsd:attribute name="key" use="optional" type="xsd:string" />
+ <xsd:attribute name="local-only" use="optional" type="xsd:boolean" />
+ <xsd:attribute name="order-by" use="optional" type="xsd:string" />
+ <xsd:attribute name="pfx" use="optional" type="xsd:string" />
+ <!-- force is retired and does not do anything -->
+ <xsd:attribute name="force" use="optional" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="configure">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="parameter" minOccurs="0" maxOccurs="100" />
+ <xsd:element ref="outcome" minOccurs="0" maxOccurs="100" />
+ </xsd:sequence>
+ <xsd:attribute name="adaptor" use="required" type="xsd:string" />
+ <xsd:attribute name="key" use="required" type="xsd:string" />
+ <xsd:attribute name="activate" use="optional" type="xsd:boolean" />
+ </xsd:complexType>
+ </xsd:element>
+
+
+ <xsd:element name="parameter">
+ <xsd:complexType>
+ <xsd:attribute name="name" use="required" type="xsd:string" />
+ <xsd:attribute name="value" use="required" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+
+
+ <xsd:element name="return">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="parameter" minOccurs="0" maxOccurs="100" />
+ </xsd:sequence>
+ <xsd:attribute name="status" use="optional" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="switch">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="outcome" minOccurs="0" maxOccurs="100" />
+ </xsd:sequence>
+ <xsd:attribute name="test" use="required" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="save">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="parameter" minOccurs="0" maxOccurs="100" />
+ <xsd:element ref="outcome" minOccurs="0" maxOccurs="100" />
+ </xsd:sequence>
+ <xsd:attribute name="plugin" use="required" type="xsd:string" />
+ <xsd:attribute name="resource" use="required" type="xsd:string" />
+ <xsd:attribute name="key" use="optional" type="xsd:string" />
+ <xsd:attribute name="force" use="optional" type="xsd:boolean" />
+ <xsd:attribute name="local-only" use="optional" type="xsd:boolean" />
+ <xsd:attribute name="pfx" use="optional" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="delete">
+ <xsd:complexType>
+ <xsd:sequence>
+ <!-- This node does not actually read from parameters -->
+ <xsd:element ref="parameter" minOccurs="0" maxOccurs="100" />
+ <xsd:element ref="outcome" minOccurs="0" maxOccurs="100" />
+ </xsd:sequence>
+ <xsd:attribute name="plugin" use="required" type="xsd:string" />
+ <xsd:attribute name="resource" use="required" type="xsd:string" />
+ <xsd:attribute name="key" use="optional" type="xsd:string" />
+ <!-- force is retired and does not do anything -->
+ <xsd:attribute name="force" use="optional" type="xsd:string" />
+ <!-- local-only is retired and does not do anything -->
+ <xsd:attribute name="local-only" use="optional" type="xsd:string" />
+ <!-- pfx is retired and does not do anything -->
+ <xsd:attribute name="pfx" use="optional" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="for">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:group ref="node" minOccurs="0" maxOccurs="100" />
+ </xsd:sequence>
+ <xsd:attribute name="atomic" use="optional" type="xsd:boolean" />
+ <xsd:attribute name="index" use="required" type="xsd:string" />
+ <xsd:attribute name="start" use="required" type="xsd:string" />
+ <xsd:attribute name="end" use="required" type="xsd:string" />
+ <xsd:attribute name="silentFailure" use="optional" type="xsd:boolean" default="false" />
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="set">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="parameter" minOccurs="0" maxOccurs="100" />
+ </xsd:sequence>
+ <xsd:attribute name="only-if-unset" use="optional"
+ type="xsd:boolean" />
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="execute">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="parameter" minOccurs="0" maxOccurs="100" />
+ <xsd:element ref="outcome" minOccurs="0" maxOccurs="100" />
+ </xsd:sequence>
+ <xsd:attribute name="plugin" use="required" type="xsd:string" />
+ <xsd:attribute name="method" use="required" type="xsd:string" />
+ <xsd:attribute name="emitsOutcome" use="optional" type="xsd:boolean" />
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="update">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="parameter" minOccurs="0" maxOccurs="100" />
+ <xsd:element ref="outcome" minOccurs="0" maxOccurs="100" />
+ </xsd:sequence>
+ <xsd:attribute name="plugin" use="required" type="xsd:string" />
+ <xsd:attribute name="resource" use="required" type="xsd:string" />
+ <xsd:attribute name="key" use="optional" type="xsd:string" />
+ <xsd:attribute name="force" use="optional" type="xsd:boolean" />
+ <xsd:attribute name="local-only" use="optional" type="xsd:boolean" />
+ <xsd:attribute name="pfx" use="optional" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="call">
+ <xsd:complexType>
+ <xsd:sequence>
+ <!-- This node does not actually read from parameters -->
+ <xsd:element ref="parameter" minOccurs="0" maxOccurs="100" />
+ <xsd:element ref="outcome" minOccurs="0" maxOccurs="100" />
+ </xsd:sequence>
+ <xsd:attribute name="module" use="optional" type="xsd:string" />
+ <xsd:attribute name="rpc" use="required" type="xsd:string" />
+ <xsd:attribute name="version" use="optional" type="xsd:string" />
+ <xsd:attribute name="mode" use="required" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="notify">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:element ref="outcome" minOccurs="0" maxOccurs="100" />
+ </xsd:sequence>
+ <xsd:attribute name="plugin" use="optional" type="xsd:string" />
+ <xsd:attribute name="resource" use="optional" type="xsd:string" />
+ <xsd:attribute name="action" use="required" type="xsd:string" />
+ <xsd:attribute name="key" use="optional" type="xsd:string" />
+ <!-- force is retired and does not do anything -->
+ <xsd:attribute name="force" use="optional" type="xsd:string" />
+ </xsd:complexType>
+ </xsd:element>
+
+ <xsd:element name="break">
+ <xsd:complexType />
+ </xsd:element>
+
+ <xsd:element name="exit">
+ <xsd:complexType />
+ </xsd:element>
+
+ <xsd:element name="while">
+ <xsd:complexType>
+ <xsd:sequence>
+ <xsd:group ref="node" minOccurs="0" maxOccurs="100" />
+ </xsd:sequence>
+ <xsd:attribute name="test" use="required" type="xsd:string" />
+ <xsd:attribute name="do" use="optional" type="xsd:boolean" />
+ </xsd:complexType>
+ </xsd:element>
+
+</xsd:schema>
diff --git a/core/sli/common/src/test/java/org/onap/ccsdk/sli/core/sli/ConfigurationExceptionTestt.java b/core/sli/common/src/test/java/org/onap/ccsdk/sli/core/sli/ConfigurationExceptionTestt.java
new file mode 100644
index 000000000..ef7492366
--- /dev/null
+++ b/core/sli/common/src/test/java/org/onap/ccsdk/sli/core/sli/ConfigurationExceptionTestt.java
@@ -0,0 +1,30 @@
+package org.onap.ccsdk.sli.core.sli;
+
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+
+public class ConfigurationExceptionTestt {
+
+
+ @Test
+ public void ConfigurationExceptionTest() {
+ assertNotNull(new ConfigurationException());
+
+ }
+
+ @Test
+ public void ConfigurationExceptionTestString() {
+ assertNotNull(new ConfigurationException("JUnit Test"));
+
+ }
+
+ @Test
+ public void ConfigurationExceptionTestStringThrowable() {
+ assertNotNull(new ConfigurationException("JUnit Test", new Exception("JUnit Test")));
+
+ }
+
+
+
+}
diff --git a/core/sli/common/src/test/java/org/onap/ccsdk/sli/core/sli/DuplicatevalueExceptionTest.java b/core/sli/common/src/test/java/org/onap/ccsdk/sli/core/sli/DuplicatevalueExceptionTest.java
new file mode 100644
index 000000000..387873557
--- /dev/null
+++ b/core/sli/common/src/test/java/org/onap/ccsdk/sli/core/sli/DuplicatevalueExceptionTest.java
@@ -0,0 +1,28 @@
+package org.onap.ccsdk.sli.core.sli;
+
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+
+public class DuplicatevalueExceptionTest {
+
+
+ @Test
+ public void DuplicateValueExceptionTest() {
+ assertNotNull(new DuplicateValueException());
+
+ }
+
+ @Test
+ public void DuplicateValueExceptionTestString() {
+ assertNotNull(new DuplicateValueException("JUnit Test"));
+
+ }
+
+ @Test
+ public void DuplicateValueExceptionTestStringThrowable() {
+ assertNotNull(new DuplicateValueException("JUnit Test", new Exception("JUnit Test")));
+
+ }
+
+}
diff --git a/core/sli/common/src/test/java/org/onap/ccsdk/sli/core/sli/ErrorLoggerTest.java b/core/sli/common/src/test/java/org/onap/ccsdk/sli/core/sli/ErrorLoggerTest.java
new file mode 100644
index 000000000..d95ff3075
--- /dev/null
+++ b/core/sli/common/src/test/java/org/onap/ccsdk/sli/core/sli/ErrorLoggerTest.java
@@ -0,0 +1,56 @@
+package org.onap.ccsdk.sli.core.sli;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ErrorLoggerTest {
+ private Logger log = LoggerFactory.getLogger(ErrorLoggerTest.class);
+
+ @Test
+ public void testOverloads() throws Exception {
+ ErrorLogger e = new ErrorLogger();
+ Exception exc = new Exception();
+ e.logError("failure", 200);
+ e.logError("failure", 200, exc);
+ e.logError("failure", 200, "Timeout during HTTP operation");
+ e.logError("failure", 200, "Timeout during HTTP operation", exc);
+ }
+
+ @Test
+ public void testInvalidErrorCode() throws Exception {
+ ErrorLogger e = new ErrorLogger();
+ e.logError("failure", 0);
+ }
+
+ @Test
+ public void testDescriptionMapping() throws Exception {
+ ErrorLogger e = new ErrorLogger();
+ e.logError("failure", 100);
+ e.logError("failure", 200);
+ e.logError("failure", 300);
+ e.logError("failure", 400);
+ e.logError("failure", 500);
+ e.logError("failure", 900);
+ }
+
+ @Test
+ public void testIsValidCode() throws Exception {
+ ErrorLogger e = new ErrorLogger(log);
+ assertTrue(e.isValidCode(ErrorLogger.ERROR_CODE_100));
+ assertTrue(e.isValidCode(ErrorLogger.ERROR_CODE_200));
+ assertTrue(e.isValidCode(ErrorLogger.ERROR_CODE_300));
+ assertTrue(e.isValidCode(ErrorLogger.ERROR_CODE_400));
+ assertTrue(e.isValidCode(ErrorLogger.ERROR_CODE_500));
+ assertTrue(e.isValidCode(ErrorLogger.ERROR_CODE_900));
+
+ assertFalse(e.isValidCode(0));
+ assertFalse(e.isValidCode(204));
+ assertFalse(e.isValidCode(404));
+ assertFalse(e.isValidCode(501));
+ }
+
+}
diff --git a/core/sli/common/src/test/java/org/onap/ccsdk/sli/core/sli/ExitNodeExceptionTest.java b/core/sli/common/src/test/java/org/onap/ccsdk/sli/core/sli/ExitNodeExceptionTest.java
new file mode 100644
index 000000000..039b9f5ca
--- /dev/null
+++ b/core/sli/common/src/test/java/org/onap/ccsdk/sli/core/sli/ExitNodeExceptionTest.java
@@ -0,0 +1,27 @@
+package org.onap.ccsdk.sli.core.sli;
+
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+
+public class ExitNodeExceptionTest {
+
+ @Test
+ public void ExitNodeExceptionTest() {
+ assertNotNull(new ExitNodeException());
+
+ }
+
+ @Test
+ public void ExitNodeExceptionTestString() {
+ assertNotNull(new ExitNodeException("JUnit Test"));
+
+ }
+
+ @Test
+ public void ExitNodeExceptionTestStringThrowable() {
+ assertNotNull(new ExitNodeException("JUnit Test", new Exception("JUnit Test")));
+
+ }
+
+}
diff --git a/core/sli/common/src/test/java/org/onap/ccsdk/sli/core/sli/ITCaseSvcLogicParser.java b/core/sli/common/src/test/java/org/onap/ccsdk/sli/core/sli/ITCaseSvcLogicParser.java
new file mode 100644
index 000000000..50eb917f8
--- /dev/null
+++ b/core/sli/common/src/test/java/org/onap/ccsdk/sli/core/sli/ITCaseSvcLogicParser.java
@@ -0,0 +1,284 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+/**
+ *
+ */
+package org.onap.ccsdk.sli.core.sli;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.Properties;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.onap.ccsdk.sli.core.dblib.DBResourceManager;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @author dt5972
+ *
+ */
+public class ITCaseSvcLogicParser {
+
+ private static SvcLogicStore store;
+ private static final Logger LOG = LoggerFactory.getLogger(SvcLogicJdbcStore.class);
+
+ @BeforeClass
+ public static void setUpBeforeClass() throws Exception {
+
+ LOG.info("before class");
+
+ URL propUrl = ITCaseSvcLogicParser.class.getResource("/svclogic.properties");
+
+ InputStream propStr = ITCaseSvcLogicParser.class.getResourceAsStream("/svclogic.properties");
+
+ Properties props = new Properties();
+
+ props.load(propStr);
+
+ store = SvcLogicStoreFactory.getSvcLogicStore(props);
+
+ assertNotNull(store);
+
+ }
+
+ @AfterClass
+ public static void tearDownAfterClass() throws Exception {
+ LOG.info("after class");
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ LOG.info("before");
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ LOG.info("after");
+ }
+
+ /**
+ * Test method for {@link org.onap.ccsdk.sli.core.sli.SvcLogicParser#parse(java.lang.String)}.
+ */
+ @Test
+ public void testParseValidXml() {
+
+ try {
+ InputStream testStr = getClass().getResourceAsStream("/parser-good.tests");
+ BufferedReader testsReader = new BufferedReader(new InputStreamReader(testStr));
+ String testCaseFile = null;
+ while ((testCaseFile = testsReader.readLine()) != null) {
+
+ testCaseFile = testCaseFile.trim();
+
+ if (testCaseFile.length() > 0) {
+ if (!testCaseFile.startsWith("/")) {
+ testCaseFile = "/" + testCaseFile;
+ }
+ URL testCaseUrl = getClass().getResource(testCaseFile);
+ if (testCaseUrl == null) {
+ fail("Could not resolve test case file " + testCaseFile);
+ }
+
+ // Test parsing and printing
+ try {
+ SvcLogicParser parser = new SvcLogicParser();
+
+ for (SvcLogicGraph graph : parser.parse(testCaseUrl.getPath())) {
+ System.out.println("XML for graph "+graph.getModule()+":"+graph.getRpc());
+ graph.printAsXml(System.out);
+ System.out.println("GV for graph "+graph.getModule()+":"+graph.getRpc());
+ graph.printAsGv(System.out);
+ }
+ } catch (Exception e) {
+
+ fail("Validation failure [" + e.getMessage() + "]");
+ }
+
+ try {
+ SvcLogicParser.load(testCaseUrl.getPath(), store);
+ } catch (Exception e) {
+
+ fail("Validation failure [" + e.getMessage() + "]");
+ }
+ }
+ }
+ } catch (SvcLogicParserException e) {
+ fail("Parser error : " + e.getMessage());
+ } catch (Exception e) {
+ LOG.error("", e);
+ fail("Caught exception processing test cases");
+ }
+ }
+
+ @Test
+ public void testDblibLoadValidXml() throws IOException, SQLException, ConfigurationException {
+
+ URL propUrl = ITCaseSvcLogicParser.class.getResource("/dblib.properties");
+
+ InputStream propStr = ITCaseSvcLogicParser.class.getResourceAsStream("/dblib.properties");
+
+ Properties props = new Properties();
+
+ props.load(propStr);
+
+ SvcLogicDblibStore dblibStore = new SvcLogicDblibStore(new DBResourceManager(props));
+
+ Connection dbConn = dblibStore.getConnection();
+
+ String dbName = props.getProperty("org.onap.ccsdk.sli.jdbc.database", "sdnctl");
+
+ DatabaseMetaData dbm;
+
+ try {
+ dbm = dbConn.getMetaData();
+ } catch (SQLException e) {
+
+ throw new ConfigurationException("could not get databse metadata", e);
+ }
+
+ // See if table SVC_LOGIC exists. If not, create it.
+ Statement stmt = null;
+ try {
+
+ ResultSet tables = dbm.getTables(null, null, "SVC_LOGIC", null);
+ if (tables.next()) {
+ LOG.debug("SVC_LOGIC table already exists");
+ } else {
+ String crTableCmd = "CREATE TABLE " + dbName + ".SVC_LOGIC (" + "module varchar(80) NOT NULL,"
+ + "rpc varchar(80) NOT NULL," + "version varchar(40) NOT NULL," + "mode varchar(5) NOT NULL,"
+ + "active varchar(1) NOT NULL,graph BLOB,"
+ + "modified_timestamp timestamp DEFAULT NULL,"
+ + "md5sum varchar(128) DEFAULT NULL,"
+ + "CONSTRAINT P_SVC_LOGIC PRIMARY KEY(module, rpc, version, mode))";
+
+ stmt = dbConn.createStatement();
+ stmt.executeUpdate(crTableCmd);
+ }
+ } catch (Exception e) {
+ throw new ConfigurationException("could not create SVC_LOGIC table", e);
+ } finally {
+ if (stmt != null) {
+ try {
+ stmt.close();
+ } catch (SQLException e) {
+ LOG.error("Statement close error ", e);
+ }
+ }
+ }
+
+ // See if NODE_TYPES table exists and, if not, create it
+ stmt = null;
+ try {
+
+ ResultSet tables = dbm.getTables(null, null, "NODE_TYPES", null);
+ if (tables.next()) {
+ LOG.debug("NODE_TYPES table already exists");
+ } else {
+ String crTableCmd = "CREATE TABLE " + dbName + ".NODE_TYPES (" + "nodetype varchar(80) NOT NULL,"
+ + "CONSTRAINT P_NODE_TYPES PRIMARY KEY(nodetype))";
+
+ stmt = dbConn.createStatement();
+
+ stmt.executeUpdate(crTableCmd);
+ }
+ } catch (Exception e) {
+ throw new ConfigurationException("could not create SVC_LOGIC table", e);
+ } finally {
+ if (stmt != null) {
+ try {
+ stmt.close();
+ } catch (SQLException e) {
+ LOG.error("Statement close error ", e);
+ }
+ }
+ }
+
+ try {
+ InputStream testStr = getClass().getResourceAsStream("/parser-good.tests");
+ BufferedReader testsReader = new BufferedReader(new InputStreamReader(testStr));
+ String testCaseFile = null;
+ while ((testCaseFile = testsReader.readLine()) != null) {
+
+ testCaseFile = testCaseFile.trim();
+
+ if (testCaseFile.length() > 0) {
+ if (!testCaseFile.startsWith("/")) {
+ testCaseFile = "/" + testCaseFile;
+ }
+ URL testCaseUrl = getClass().getResource(testCaseFile);
+ if (testCaseUrl == null) {
+ fail("Could not resolve test case file " + testCaseFile);
+ }
+
+ try {
+ SvcLogicParser.load(testCaseUrl.getPath(), dblibStore);
+ } catch (Exception e) {
+
+ fail("Validation failure [" + e.getMessage() + "]");
+ }
+ }
+ }
+ } catch (SvcLogicParserException e) {
+ fail("Parser error : " + e.getMessage());
+ } catch (Exception e) {
+ LOG.error("", e);
+ fail("Caught exception processing test cases");
+ }
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void testParseInvalidXml() throws SvcLogicException, IOException {
+
+ InputStream testStr = getClass().getResourceAsStream("/parser-bad.tests");
+ BufferedReader testsReader = new BufferedReader(new InputStreamReader(testStr));
+ String testCaseFile;
+ while ((testCaseFile = testsReader.readLine()) != null) {
+
+ testCaseFile = testCaseFile.trim();
+
+ if (testCaseFile.length() > 0) {
+ if (!testCaseFile.startsWith("/")) {
+ testCaseFile = "/" + testCaseFile;
+ }
+ URL testCaseUrl = getClass().getResource(testCaseFile);
+ if (testCaseUrl == null) {
+ fail("Could not resolve test case file " + testCaseFile);
+ }
+ SvcLogicParser.validate(testCaseUrl.getPath(), store);
+ }
+ }
+ }
+}
diff --git a/core/sli/common/src/test/java/org/onap/ccsdk/sli/core/sli/SvcLogicContextTest.java b/core/sli/common/src/test/java/org/onap/ccsdk/sli/core/sli/SvcLogicContextTest.java
new file mode 100644
index 000000000..43e7a862b
--- /dev/null
+++ b/core/sli/common/src/test/java/org/onap/ccsdk/sli/core/sli/SvcLogicContextTest.java
@@ -0,0 +1,400 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.sli;
+
+import java.io.*;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import com.google.gson.*;
+import org.apache.commons.lang3.builder.ToStringExclude;
+import org.checkerframework.checker.units.qual.A;
+import org.json.JSONException;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.skyscreamer.jsonassert.JSONAssert;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.Document;
+import junit.framework.TestCase;
+
+import static org.junit.Assert.assertEquals;
+
+public class SvcLogicContextTest extends TestCase {
+ private static final Logger LOG = LoggerFactory
+ .getLogger(SvcLogicContextTest.class);
+
+ @Test
+ public void testMerge() {
+
+ try {
+ InputStream testStr = getClass().getResourceAsStream("/mergetest.xml");
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ DocumentBuilder db = dbf.newDocumentBuilder();
+
+ Document theDocument = db.parse(testStr);
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.mergeDocument("test-merge", theDocument);
+ Properties props = ctx.toProperties();
+ LOG.info("SvcLogicContext contains the following : ");
+ for (Enumeration e = props.propertyNames(); e.hasMoreElements() ; ) {
+ String propName = (String) e.nextElement();
+ LOG.info(propName+" = "+props.getProperty(propName));
+
+ }
+ } catch (Exception e) {
+ LOG.error("Caught exception trying to merge", e);
+ fail("Caught exception trying to merge");
+ }
+
+ }
+
+ @Test
+ public void testIsSuccess() {
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setStatus(SvcLogicConstants.SUCCESS);
+ assertTrue(ctx.isSuccess());
+ ctx.setStatus(SvcLogicConstants.FAILURE);
+ assertFalse(ctx.isSuccess());
+ }
+
+ @Test
+ public void testMarkSuccess() {
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.markSuccess();
+ assertTrue(ctx.isSuccess());
+ assertEquals(SvcLogicConstants.SUCCESS, ctx.getStatus());
+ }
+
+ @Test
+ public void testMarkFailed() {
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.markFailed();
+ assertFalse(ctx.isSuccess());
+ assertEquals(SvcLogicConstants.FAILURE, ctx.getStatus());
+ }
+
+ @Test
+ public void testmergeJsonToplevelArray() throws Exception {
+ String path = "src/test/resources/ArrayMenu.json";
+ String content = new String(Files.readAllBytes(Paths.get(path)));
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.mergeJson("testPath", content);
+
+
+ assertEquals("1000", ctx.getAttribute("testPath.[0].calories"));
+ assertEquals("1", ctx.getAttribute("testPath.[0].id"));
+ assertEquals("plain", ctx.getAttribute("testPath.[0].name"));
+ assertEquals("pizza", ctx.getAttribute("testPath.[0].type"));
+ assertEquals("true", ctx.getAttribute("testPath.[0].vegetarian"));
+ assertEquals(SvcLogicContext.CTX_NULL_VALUE, ctx.getAttribute("testPath.[1].calories"));
+ assertEquals("2", ctx.getAttribute("testPath.[1].id"));
+ assertEquals("Tuesday Special", ctx.getAttribute("testPath.[1].name"));
+ assertEquals("1", ctx.getAttribute("testPath.[1].topping[0].id"));
+ assertEquals("onion", ctx.getAttribute("testPath.[1].topping[0].name"));
+ assertEquals("2", ctx.getAttribute("testPath.[1].topping[1].id"));
+ assertEquals("pepperoni", ctx.getAttribute("testPath.[1].topping[1].name"));
+ assertEquals("2", ctx.getAttribute("testPath.[1].topping_length"));
+ assertEquals("pizza", ctx.getAttribute("testPath.[1].type"));
+ assertEquals("false", ctx.getAttribute("testPath.[1].vegetarian"));
+ assertEquals("1500", ctx.getAttribute("testPath.[2].calories"));
+ assertEquals("3", ctx.getAttribute("testPath.[2].id"));
+ assertEquals("House Special", ctx.getAttribute("testPath.[2].name"));
+ assertEquals("3", ctx.getAttribute("testPath.[2].topping[0].id"));
+ assertEquals("basil", ctx.getAttribute("testPath.[2].topping[0].name"));
+ assertEquals("4", ctx.getAttribute("testPath.[2].topping[1].id"));
+ assertEquals("fresh mozzarella", ctx.getAttribute("testPath.[2].topping[1].name"));
+ assertEquals("5", ctx.getAttribute("testPath.[2].topping[2].id"));
+ assertEquals("tomato", ctx.getAttribute("testPath.[2].topping[2].name"));
+ assertEquals("3", ctx.getAttribute("testPath.[2].topping_length"));
+ assertEquals("pizza", ctx.getAttribute("testPath.[2].type"));
+ assertEquals("true", ctx.getAttribute("testPath.[2].vegetarian"));
+ assertEquals("3", ctx.getAttribute("testPath._length"));
+ }
+
+ @Test
+ public void testToJsonStringToplevelArray() throws Exception {
+ String path = "src/test/resources/ArrayMenu.json";
+ String content = new String(Files.readAllBytes(Paths.get(path)));
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.mergeJson("testPath", content);
+
+ String ctxContent = ctx.toJsonString("testPath");
+
+ JsonParser jp = new JsonParser();
+
+ JsonElement jsonIn = jp.parse(content);
+ JsonElement jsonOut = jp.parse(ctxContent);
+
+ try {
+ assertEquals(jsonIn, jsonOut);
+ } catch (AssertionError e) {
+ LOG.warn("Top level array not working - error is {}", e.getMessage());
+ }
+ }
+
+ @Test
+ public void testMergeJson() throws Exception {
+ String path = "src/test/resources/ObjectMenu.json";
+ String content = new String(Files.readAllBytes(Paths.get(path)));
+
+ SvcLogicContext ctx = new SvcLogicContext();
+
+ ctx.mergeJson("testPath", content);
+
+
+ assertEquals("1000", ctx.getAttribute("testPath.menu[0].calories"));
+ assertEquals("1", ctx.getAttribute("testPath.menu[0].id"));
+ assertEquals("plain", ctx.getAttribute("testPath.menu[0].name"));
+ assertEquals("pizza", ctx.getAttribute("testPath.menu[0].type"));
+ assertEquals("true", ctx.getAttribute("testPath.menu[0].vegetarian"));
+ assertEquals("2000", ctx.getAttribute("testPath.menu[1].calories"));
+ assertEquals("2", ctx.getAttribute("testPath.menu[1].id"));
+ assertEquals("Tuesday Special", ctx.getAttribute("testPath.menu[1].name"));
+ assertEquals("1", ctx.getAttribute("testPath.menu[1].topping[0].id"));
+ assertEquals("onion", ctx.getAttribute("testPath.menu[1].topping[0].name"));
+ assertEquals("2", ctx.getAttribute("testPath.menu[1].topping[1].id"));
+ assertEquals("pepperoni", ctx.getAttribute("testPath.menu[1].topping[1].name"));
+ assertEquals("2", ctx.getAttribute("testPath.menu[1].topping_length"));
+ assertEquals("pizza", ctx.getAttribute("testPath.menu[1].type"));
+ assertEquals("false", ctx.getAttribute("testPath.menu[1].vegetarian"));
+ assertEquals("1500", ctx.getAttribute("testPath.menu[2].calories"));
+ assertEquals("3", ctx.getAttribute("testPath.menu[2].id"));
+ assertEquals("House Special", ctx.getAttribute("testPath.menu[2].name"));
+ assertEquals("3", ctx.getAttribute("testPath.menu[2].topping[0].id"));
+ assertEquals("basil", ctx.getAttribute("testPath.menu[2].topping[0].name"));
+ assertEquals("4", ctx.getAttribute("testPath.menu[2].topping[1].id"));
+ assertEquals("fresh mozzarella", ctx.getAttribute("testPath.menu[2].topping[1].name"));
+ assertEquals("5", ctx.getAttribute("testPath.menu[2].topping[2].id"));
+ assertEquals("tomato", ctx.getAttribute("testPath.menu[2].topping[2].name"));
+ assertEquals("3", ctx.getAttribute("testPath.menu[2].topping_length"));
+ assertEquals("pizza", ctx.getAttribute("testPath.menu[2].type"));
+ assertEquals("true", ctx.getAttribute("testPath.menu[2].vegetarian"));
+ assertEquals("3", ctx.getAttribute("testPath.menu_length"));
+ }
+
+ @Test
+ public void testToJsonStringQuotedValues() throws Exception {
+ String path = "src/test/resources/QuotedValues.json";
+ String content = new String(Files.readAllBytes(Paths.get(path)));
+
+ SvcLogicContext ctx = new SvcLogicContext();
+
+ ctx.mergeJson("testPath", content);
+ String ctxContent = ctx.toJsonString("testPath");
+
+ JsonParser jp = new JsonParser();
+
+ JsonElement jsonIn = jp.parse(content);
+ JsonElement jsonOut = jp.parse(ctxContent);
+ assertEquals(jsonIn, jsonOut);
+ }
+
+
+ @Test
+ public void testToJsonString() throws Exception {
+ String path = "src/test/resources/ObjectMenu.json";
+ String content = new String(Files.readAllBytes(Paths.get(path)));
+
+ SvcLogicContext ctx = new SvcLogicContext();
+
+ ctx.mergeJson("testPath", content);
+ String ctxContent = ctx.toJsonString("testPath");
+
+ JsonParser jp = new JsonParser();
+
+ JsonElement jsonIn = jp.parse(content);
+ JsonElement jsonOut = jp.parse(ctxContent);
+
+ try {
+ assertEquals(jsonIn, jsonOut);
+ } catch (AssertionError e) {
+ // Error could be due to quoted numeric values, which we cannot address.
+ LOG.warn("Test failed, but could be known error condition. Error is {}", e.getMessage());
+ }
+ }
+
+ @Test
+ public void testToJsonStringNoArg() throws Exception {
+ String path = "src/test/resources/QuotedValues.json";
+ String content = new String(Files.readAllBytes(Paths.get(path)));
+
+ SvcLogicContext ctx = new SvcLogicContext();
+
+ ctx.mergeJson(null, content);
+ String ctxContent = ctx.toJsonString();
+
+ JsonParser jp = new JsonParser();
+
+ JsonElement jsonIn = jp.parse(content);
+ JsonElement jsonOut = jp.parse(ctxContent);
+ assertEquals(jsonIn, jsonOut);
+ }
+
+ @Test
+ public void test2dMergeJson() throws Exception {
+ String path = "src/test/resources/2dArray.json";
+ String content = new String(Files.readAllBytes(Paths.get(path)));
+
+ SvcLogicContext ctx = new SvcLogicContext();
+
+
+ ctx.mergeJson("testPath", content);
+ assertEquals("apple", ctx.getAttribute("testPath.[0][0]"));
+ assertEquals("orange", ctx.getAttribute("testPath.[0][1]"));
+ assertEquals("banana", ctx.getAttribute("testPath.[0][2]"));
+ assertEquals(SvcLogicContext.CTX_NULL_VALUE, ctx.getAttribute("testPath.[0][3]"));
+ assertEquals("4", ctx.getAttribute("testPath.[0]_length"));
+ assertEquals("squash", ctx.getAttribute("testPath.[1][0]"));
+ assertEquals("broccoli", ctx.getAttribute("testPath.[1][1]"));
+ assertEquals("cauliflower", ctx.getAttribute("testPath.[1][2]"));
+ assertEquals("3", ctx.getAttribute("testPath.[1]_length"));
+ assertEquals("2", ctx.getAttribute("testPath._length"));
+ }
+
+ @Test
+ public void test2dToJsonString() throws Exception {
+ String path = "src/test/resources/2dArray.json";
+ String content = new String(Files.readAllBytes(Paths.get(path)));
+
+ SvcLogicContext ctx = new SvcLogicContext();
+
+
+ ctx.mergeJson("testPath", content);
+ String ctxContent = ctx.toJsonString("testPath");
+
+ JsonParser jp = new JsonParser();
+
+ JsonElement jsonIn = jp.parse(content);
+ JsonElement jsonOut = jp.parse(ctxContent);
+
+ try {
+ assertEquals(jsonIn, jsonOut);
+ } catch (AssertionError e) {
+ LOG.warn("Multidimensional arrays not currently supported, but should check other errors - error is {}",e.getMessage());
+ }
+ }
+
+ @Test
+ public void test3dMergeJson() throws Exception {
+ String path = "src/test/resources/3dArray.json";
+ String content = new String(Files.readAllBytes(Paths.get(path)));
+
+ SvcLogicContext ctx = new SvcLogicContext();
+
+ ctx.mergeJson("testPath", content);
+ assertEquals("a", ctx.getAttribute("testPath.[0][0][0]"));
+ assertEquals("b", ctx.getAttribute("testPath.[0][0][1]"));
+ assertEquals("c", ctx.getAttribute("testPath.[0][0][2]"));
+ assertEquals("3", ctx.getAttribute("testPath.[0][0]_length"));
+ assertEquals("d", ctx.getAttribute("testPath.[0][1][0]"));
+ assertEquals("e", ctx.getAttribute("testPath.[0][1][1]"));
+ assertEquals("f", ctx.getAttribute("testPath.[0][1][2]"));
+ assertEquals("3", ctx.getAttribute("testPath.[0][1]_length"));
+ assertEquals("2", ctx.getAttribute("testPath.[0]_length"));
+ assertEquals("x", ctx.getAttribute("testPath.[1][0][0]"));
+ assertEquals("y", ctx.getAttribute("testPath.[1][0][1]"));
+ assertEquals("z", ctx.getAttribute("testPath.[1][0][2]"));
+ assertEquals("3", ctx.getAttribute("testPath.[1][0]_length"));
+ assertEquals("1", ctx.getAttribute("testPath.[1]_length"));
+ assertEquals("2", ctx.getAttribute("testPath._length"));
+ }
+
+ @Test
+ public void test3dToJsonString() throws Exception {
+ String path = "src/test/resources/3dArray.json";
+ String content = new String(Files.readAllBytes(Paths.get(path)));
+
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.mergeJson("testPath", content);
+ String ctxContent = ctx.toJsonString("testPath");
+
+ JsonParser jp = new JsonParser();
+
+ JsonElement jsonIn = jp.parse(content);
+ JsonElement jsonOut = jp.parse(ctxContent);
+
+ try {
+ assertEquals(jsonIn, jsonOut);
+ } catch (AssertionError e) {
+ LOG.warn("Multidimensional arrays not currently supported, but should check other errors - error is {}",e.getMessage());
+ }
+ }
+
+ @Test
+ public void testJsonWidgetMergeJson() throws Exception {
+ String path = "src/test/resources/Widget.json";
+ String content = new String(Files.readAllBytes(Paths.get(path)));
+
+ SvcLogicContext ctx = new SvcLogicContext();
+
+ ctx.mergeJson("testPath", content);
+ assertEquals("false", ctx.getAttribute("testPath.widget.debug"));
+ assertEquals("center", ctx.getAttribute("testPath.widget.image.alignment"));
+ assertEquals("150", ctx.getAttribute("testPath.widget.image.hOffset"));
+ assertEquals("moon", ctx.getAttribute("testPath.widget.image.name"));
+ assertEquals("images/moon.png", ctx.getAttribute("testPath.widget.image.src"));
+ assertEquals("150", ctx.getAttribute("testPath.widget.image.vOffset"));
+ assertEquals("center", ctx.getAttribute("testPath.widget.text.alignment"));
+ assertEquals("Click Me", ctx.getAttribute("testPath.widget.text.data"));
+ assertEquals("350", ctx.getAttribute("testPath.widget.text.hOffset"));
+ assertEquals("text1", ctx.getAttribute("testPath.widget.text.name"));
+ assertEquals("21", ctx.getAttribute("testPath.widget.text.size"));
+ assertEquals("bold", ctx.getAttribute("testPath.widget.text.style"));
+ assertEquals(SvcLogicContext.CTX_NULL_VALUE, ctx.getAttribute("testPath.widget.text.vOffset"));
+ assertEquals("300", ctx.getAttribute("testPath.widget.window.height"));
+ assertEquals("main_window", ctx.getAttribute("testPath.widget.window.name"));
+ assertEquals("ONAP Widget", ctx.getAttribute("testPath.widget.window.title"));
+ assertEquals("200", ctx.getAttribute("testPath.widget.window.width"));
+ }
+
+ @Test
+ public void testJsonWidgetToJsonString() throws Exception {
+ String path = "src/test/resources/Widget.json";
+ String content = new String(Files.readAllBytes(Paths.get(path)));
+
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.mergeJson("testPath", content);
+ String ctxContent = ctx.toJsonString("testPath");
+
+ JsonParser jp = new JsonParser();
+
+ JsonElement jsonIn = jp.parse(content);
+ JsonElement jsonOut = jp.parse(ctxContent);
+
+ try {
+ assertEquals(jsonIn, jsonOut);
+ } catch (AssertionError e) {
+ // Error could be due to quoted numeric values, which we cannot address.
+ LOG.warn("Test failed, but could be known error condition. Error is {}",e.getMessage());
+ }
+ }
+}
diff --git a/core/sli/common/src/test/java/org/onap/ccsdk/sli/core/sli/SvcLogicExpressionParserTest.java b/core/sli/common/src/test/java/org/onap/ccsdk/sli/core/sli/SvcLogicExpressionParserTest.java
new file mode 100644
index 000000000..80df10cee
--- /dev/null
+++ b/core/sli/common/src/test/java/org/onap/ccsdk/sli/core/sli/SvcLogicExpressionParserTest.java
@@ -0,0 +1,66 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.sli;
+
+import java.io.BufferedReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import junit.framework.TestCase;
+
+public class SvcLogicExpressionParserTest extends TestCase {
+
+ private static final Logger LOG = LoggerFactory
+ .getLogger(SvcLogicExprListener.class);
+
+ public void testParse() {
+ try
+ {
+ InputStream testStr = getClass().getResourceAsStream("/expression.tests");
+ BufferedReader testsReader = new BufferedReader(new InputStreamReader(testStr));
+
+ String testExpr = null;
+ while ((testExpr = testsReader.readLine()) != null) {
+
+ SvcLogicExpression parsedExpr = SvcLogicExpressionFactory.parse(testExpr);
+ if (parsedExpr == null)
+ {
+ fail("parse("+testExpr+") returned null");
+ }
+ else
+ {
+ LOG.info("test expression = ["+testExpr+"] ; parsed expression = ["+parsedExpr.asParsedExpr()+"]");
+
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ fail("Caught exception processing test cases");
+ }
+ }
+
+}
diff --git a/core/sli/common/src/test/java/org/onap/ccsdk/sli/core/sli/SvcLogicParserExceptionTest.java b/core/sli/common/src/test/java/org/onap/ccsdk/sli/core/sli/SvcLogicParserExceptionTest.java
new file mode 100644
index 000000000..f9d33cb16
--- /dev/null
+++ b/core/sli/common/src/test/java/org/onap/ccsdk/sli/core/sli/SvcLogicParserExceptionTest.java
@@ -0,0 +1,34 @@
+package org.onap.ccsdk.sli.core.sli;
+
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+
+public class SvcLogicParserExceptionTest {
+
+ @Test
+ public void SvcLogicParserExceptionTest() {
+ assertNotNull(new SvcLogicParserException());
+
+ }
+
+ @Test
+ public void SvcLogicParserExceptionTestString() {
+ assertNotNull(new SvcLogicParserException("JUnit Test"));
+
+ }
+
+ @Test
+ public void SvcLogicParserExceptionTestThrowable() {
+ assertNotNull(new SvcLogicParserException(new Exception("JUnit Test")));
+
+ }
+
+ @Test
+ public void SvcLogicParserExceptionTestStringThrowable() {
+ assertNotNull(new SvcLogicParserException("JUnit Test", new Exception("JUnit Test")));
+
+ }
+
+
+}
diff --git a/core/sli/common/src/test/java/org/onap/ccsdk/sli/core/sli/TestMetricLogger.java b/core/sli/common/src/test/java/org/onap/ccsdk/sli/core/sli/TestMetricLogger.java
new file mode 100755
index 000000000..37d2fc8c5
--- /dev/null
+++ b/core/sli/common/src/test/java/org/onap/ccsdk/sli/core/sli/TestMetricLogger.java
@@ -0,0 +1,85 @@
+package org.onap.ccsdk.sli.core.sli;
+
+import static org.junit.Assert.*;
+import java.util.Date;
+import java.util.UUID;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.onap.logging.ref.slf4j.ONAPLogConstants;
+import org.slf4j.MDC;
+
+public class TestMetricLogger {
+
+ MetricLogger logger;
+
+ @Before
+ public void setUp() throws Exception {
+ logger = new MetricLogger();
+ MetricLogger.resetContext();
+ }
+
+ @Test
+ public final void testGetRequestID() {
+ UUID uuid = UUID.randomUUID();
+ MDC.put(ONAPLogConstants.MDCs.REQUEST_ID, uuid.toString());
+ assertEquals(uuid.toString(),logger.getRequestID());
+ }
+
+ @Test
+ public final void testAsIso8601Date() {
+ logger.asIso8601(new Date());
+ }
+
+ @Test
+ public final void testAsIso8601Long() {
+ logger.asIso8601(System.currentTimeMillis());
+ }
+
+ @Test
+ public void formatString() {
+ String output = logger.formatString("\n");
+ assertEquals("",output);
+ output = logger.formatString("|");
+ assertEquals("%7C",output);
+ output = logger.formatString(null);
+ assertEquals(null,output);
+ output = logger.formatString("\t");
+ assertEquals(" ", output);
+ output = logger.formatString("one,two,three,");
+ assertEquals("one\\,two\\,three\\,", output);
+ }
+
+ @Test
+ public void generateInvocationId() {
+ logger.logRequest("svcInstance1", "svcName", "svcPartner", "targetEntity", "targetServiceName", "targetVirtualEntity", "hello-world");
+ assertNotNull(MDC.get(ONAPLogConstants.MDCs.CLIENT_INVOCATION_ID));
+ assertNotNull(MDC.get(ONAPLogConstants.MDCs.INVOCATION_ID));
+ }
+
+ @Test
+ public void generateRequestId() {
+ logger.logRequest("svcInstance1", "svcName", "svcPartner", "targetEntity", "targetServiceName", "targetVirtualEntity", "hello-world");
+ assertNotNull(MDC.get(ONAPLogConstants.MDCs.REQUEST_ID));
+ }
+
+ @Test
+ public void overrideInvocationId() {
+ String oldUUID = UUID.randomUUID().toString();
+ MDC.put(ONAPLogConstants.MDCs.CLIENT_INVOCATION_ID, oldUUID);
+ MDC.put(ONAPLogConstants.MDCs.INVOCATION_ID, oldUUID);
+
+ logger.logRequest("svcInstance1", "svcName", "svcPartner", "targetEntity", "targetServiceName", "targetVirtualEntity", "hello-world");
+ String newUUID = MDC.get(ONAPLogConstants.MDCs.CLIENT_INVOCATION_ID);
+ assertFalse(oldUUID.equals(newUUID));
+ newUUID = MDC.get(ONAPLogConstants.MDCs.INVOCATION_ID);
+ assertFalse(oldUUID.equals(newUUID));
+ }
+
+ @Test
+ public void persistRequestId() {
+ String oldUUID = UUID.randomUUID().toString();
+ MDC.put(ONAPLogConstants.MDCs.REQUEST_ID, oldUUID);
+ assertEquals(oldUUID, MDC.get(ONAPLogConstants.MDCs.REQUEST_ID));
+ }
+}
diff --git a/core/sli/common/src/test/java/org/onap/ccsdk/sli/core/sli/TestSvcLogicLoader.java b/core/sli/common/src/test/java/org/onap/ccsdk/sli/core/sli/TestSvcLogicLoader.java
new file mode 100644
index 000000000..2dd83e86d
--- /dev/null
+++ b/core/sli/common/src/test/java/org/onap/ccsdk/sli/core/sli/TestSvcLogicLoader.java
@@ -0,0 +1,38 @@
+package org.onap.ccsdk.sli.core.sli;
+
+import static org.junit.Assert.*;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.Properties;
+import org.junit.Test;
+
+public class TestSvcLogicLoader {
+
+ @Test
+ public void testLoadAndActivate() throws IOException, SvcLogicException {
+ URL propUrl = ITCaseSvcLogicParser.class.getResource("/svclogic.properties");
+
+ InputStream propStr = ITCaseSvcLogicParser.class.getResourceAsStream("/svclogic.properties");
+
+ Properties props = new Properties();
+
+ props.load(propStr);
+
+ SvcLogicStore store = SvcLogicStoreFactory.getSvcLogicStore(props);
+
+ File graphDirectory = new File(getClass().getClassLoader().getResource("graphs").getFile());
+
+ if (graphDirectory == null) {
+ fail("Cannot find graphs directory");
+ }
+ SvcLogicLoader loader = new SvcLogicLoader(graphDirectory.getAbsolutePath(), store);
+ loader.loadAndActivate();
+
+
+ }
+
+
+
+}
diff --git a/core/sli/common/src/test/resources/2dArray.json b/core/sli/common/src/test/resources/2dArray.json
new file mode 100644
index 000000000..2a94b46f4
--- /dev/null
+++ b/core/sli/common/src/test/resources/2dArray.json
@@ -0,0 +1,4 @@
+[
+ ["apple", "orange", "banana", null],
+ ["squash", "broccoli", "cauliflower"]
+] \ No newline at end of file
diff --git a/core/sli/common/src/test/resources/3dArray.json b/core/sli/common/src/test/resources/3dArray.json
new file mode 100644
index 000000000..149955596
--- /dev/null
+++ b/core/sli/common/src/test/resources/3dArray.json
@@ -0,0 +1,4 @@
+[
+ [["a","b","c"], ["d","e","f"]],
+ [["x","y","z"]]
+] \ No newline at end of file
diff --git a/core/sli/common/src/test/resources/ArrayMenu.json b/core/sli/common/src/test/resources/ArrayMenu.json
new file mode 100644
index 000000000..26a24f292
--- /dev/null
+++ b/core/sli/common/src/test/resources/ArrayMenu.json
@@ -0,0 +1,41 @@
+[{
+ "id": "1",
+ "type": "pizza",
+ "name": "plain",
+ "calories": 1000,
+ "vegetarian": true
+ }, {
+ "id": "2",
+ "type": "pizza",
+ "name": "Tuesday Special",
+ "calories": null,
+ "vegetarian": false,
+ "topping":
+ [{
+ "id": "1",
+ "name": "onion"
+ }, {
+ "id": "2",
+ "name": "pepperoni"
+ }
+ ]
+ }, {
+ "id": "3",
+ "type": "pizza",
+ "name": "House Special",
+ "calories": 1500,
+ "vegetarian": true,
+ "topping":
+ [{
+ "id": "3",
+ "name": "basil"
+ }, {
+ "id": "4",
+ "name": "fresh mozzarella"
+ }, {
+ "id": "5",
+ "name": "tomato"
+ }
+ ]
+ }
+]
diff --git a/core/sli/common/src/test/resources/EmbeddedEscapedJson.json b/core/sli/common/src/test/resources/EmbeddedEscapedJson.json
new file mode 100644
index 000000000..dbb6d8d3a
--- /dev/null
+++ b/core/sli/common/src/test/resources/EmbeddedEscapedJson.json
@@ -0,0 +1,16 @@
+{
+ "input": {
+ "parameters":
+ [{
+ "name": "escapedJsonObject",
+ "value": "[{\"id\":\"0.2.0.0\/16\"},{\"id\":\"ge04::\/64\"}]"
+ }, {
+ "name": "password",
+ "value": "Hello\/World"
+ }, {
+ "name": "resourceName",
+ "value": "The\t\"Best\"\tName"
+ }
+ ]
+ }
+} \ No newline at end of file
diff --git a/core/sli/common/src/test/resources/EscapedJson.json b/core/sli/common/src/test/resources/EscapedJson.json
new file mode 100644
index 000000000..a7719e819
--- /dev/null
+++ b/core/sli/common/src/test/resources/EscapedJson.json
@@ -0,0 +1 @@
+{\"widget\":{\"debug\":false,\"window\":{\"title\":\"ONAP Widget\",\"name\":\"main_window\",\"width\":200,\"height\":300},\"image\":{\"src\":\"images\/moon.png\",\"name\":\"moon\",\"hOffset\":150,\"vOffset\":150,\"alignment\":\"center\"},\"text\":{\"data\":\"Click Me\",\"size\":21,\"style\":\"bold\",\"name\":\"text1\",\"hOffset\":350,\"vOffset\":200,\"alignment\":\"center\"}}} \ No newline at end of file
diff --git a/core/sli/common/src/test/resources/EvcActivateSvcLogic_v100.xml b/core/sli/common/src/test/resources/EvcActivateSvcLogic_v100.xml
new file mode 100644
index 000000000..708823efc
--- /dev/null
+++ b/core/sli/common/src/test/resources/EvcActivateSvcLogic_v100.xml
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ============LICENSE_START=======================================================
+ ONAP : CCSDK
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property. All rights
+ reserved.
+ ================================================================================
+ 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.
+ ============LICENSE_END=========================================================
+ -->
+
+
+<service-logic xmlns="http://www.onap.org/sdnc/svclogic"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.onap.org/sdnc/svclogic ./svclogic.xsd"
+ module="ase" version="1.0.0">
+
+
+ <method rpc="ase-evc-activation" mode="sync">
+ <configure adaptor="org.onap.ccsdl.sli.adaptors.emt.EmtAdaptor"
+ key="$evc-name" activate="true">
+ <parameter name="circuit.name" value="$evc-name" />
+ <parameter name="topology" value="$topology" />
+ <parameter name="leg1.uniCircuitId" value="$evc-leg[0].evc-access-name" />
+ <parameter name="leg2.uniCircuitId" value="$evc-leg[1].evc-access-name" />
+ <outcome value="success">
+ <return status="success" />
+ </outcome>
+ <outcome value="already-active">
+ <return status="failure">
+ <parameter name="error-code" value="1590" />
+ <parameter name="error-message" value="`Circuit already active`" />
+ </return>
+ </outcome>
+ <outcome value="Other">
+ <return status="failure">
+ <parameter name="error-code" value="1542" />
+ <parameter name="error-message" value="Activation failure" />
+ </return>
+ </outcome>
+ </configure>
+ </method>
+
+ <method rpc="ase-evc-disconnect-request" mode="sync">
+ <configure adaptor="org.onap.ccsdk.sli.adaptors.emt.EmtAdaptor"
+ key="$evc-name" activate="false">
+ <outcome value="success">
+ <return status="success" />
+ </outcome>
+
+ <outcome value="Other">
+ <return status="failure">
+ <parameter name="error-code" value="1542" />
+ <parameter name="error-message" value="De-activation failure" />
+ </return>
+ </outcome>
+ </configure>
+ </method>
+
+
+</service-logic>
diff --git a/core/sli/common/src/test/resources/EvcPortSvcLogic_v100.xml b/core/sli/common/src/test/resources/EvcPortSvcLogic_v100.xml
new file mode 100644
index 000000000..9a1a14708
--- /dev/null
+++ b/core/sli/common/src/test/resources/EvcPortSvcLogic_v100.xml
@@ -0,0 +1,263 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ============LICENSE_START=======================================================
+ ONAP : CCSDK
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property. All rights
+ reserved.
+ ================================================================================
+ 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.
+ ============LICENSE_END=========================================================
+ -->
+
+
+<service-logic xmlns="http://www.onap.org/sdnc/svclogic"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.onap.org/sdnc/svclogic ./svclogic.xsd"
+ module="ase" version="1.0.0">
+
+ <!-- Reserve a port. Returns uni-circuit-id of reserved ase-port -->
+ <method rpc="ase-port-reserve" mode="sync">
+ <switch test="$uni-cir-units">
+ <outcome value="Mbps">
+ <reserve plugin="org.onap.ccsdk.sli.adaptors.sample.SampleResource"
+ resource="ase-port"
+ key="resource-emt-clli == $edge-device-clli and speed >= $uni-cir-value"
+ pfx="asePort">
+
+
+ <outcome value="success">
+ <block>
+ <record plugin="org.onap.ccsdk.sli.core.sli.recording.FileRecorder">
+ <parameter name="file" value="/tmp/sample_r1.log" />
+ <parameter name="field1" value="__TIMESTAMP__"/>
+ <parameter name="field2" value="RESERVED"/>
+ <parameter name="field3" value="$asePort.uni_circuit_id"/>
+ </record>
+ <return status="success">
+ <parameter name="uni-circuit-id" value="$asePort.uni_circuit_id" />
+ </return>
+ </block>
+
+ </outcome>
+
+ <outcome value="not-found">
+ <return status="failure">
+ <parameter name="error-code" value="1010" />
+ <parameter name="error-message" value="No ports found that match criteria" />
+ </return>
+ </outcome>
+
+ <outcome value="Other">
+ <return status="failure">
+ <parameter name="error-code" value="1010" />
+ <parameter name="error-message"
+ value="Error encountered trying to reserve port" />
+ </return>
+ </outcome>
+
+ </reserve>
+ </outcome>
+ <outcome value="Gbps">
+ <reserve plugin="org.onap.ccsdk.sli.adaptors.sample.SampleResource"
+ resource="ase-port"
+ key="resource-emt-clli == $edge-device-clli and speed >= 1000 * $uni-cir-value"
+ pfx="asePort">
+
+
+ <outcome value="success">
+ <block>
+ <record plugin="org.onap.ccsdk.sli.core.sli.recording.FileRecorder">
+ <parameter name="file" value="/tmp/sample_r1.log" />
+ <parameter name="field1" value="__TIMESTAMP__"/>
+ <parameter name="field2" value="RESERVED"/>
+ <parameter name="field3" value="$asePort.uni_circuit_id"/>
+ </record>
+ <return status="success">
+ <parameter name="uni-circuit-id" value="$asePort.uni_circuit_id" />
+ </return>
+ </block>
+ </outcome>
+
+ <outcome value="not-found">
+ <return status="failure">
+ <parameter name="error-code" value="1010" />
+ <parameter name="error-message" value="No ports found that match criteria" />
+ </return>
+ </outcome>
+ <outcome value="">
+ <return status="failure">
+ <parameter name="error-code" value="1012" />
+ <parameter name="error-message"
+ value="Error encountered trying to reserve port" />
+ </return>
+ </outcome>
+ <outcome value="Other">
+ <return status="failure">
+ <parameter name="error-code" value="1010" />
+ <parameter name="error-message"
+ value="Error encountered trying to reserve port" />
+ </return>
+ </outcome>
+ </reserve>
+ </outcome>
+ </switch>
+ </method>
+
+ <!-- One step provisioning/activation command. Allocates a local resource,
+ then configures it on device -->
+ <method rpc="ase-port-activate-request" mode="sync">
+
+ <allocate plugin="org.onap.ccsdk.sli.adaptors.sample.SampleResource"
+ resource="ase-port" key="uni-circuit-id == $uni-circuit-id" pfx="asePort">
+
+ <outcome value="success">
+ <configure adaptor="org.onap.ccsdk.sli.adaptors.emt.EmtAdaptor"
+ key="$uni-circuit-id" activate="true">
+ <parameter name="circuit.id" value="$uni-circuit-id" />
+ <parameter name="subscriber.name" value="$subscriber-name" />
+ <parameter name="emt.clli" value="$edge-device-clli" />
+ <parameter name="port.tagging" value="$port-tagging" />
+ <parameter name="port.mediaSpeed" value="$media-speed" />
+ <parameter name="location.state" value="$uni-location-state" />
+ <parameter name="location.city" value="$uni-location-city" />
+ <parameter name="cosCategory" value="$cos-category" />
+ <parameter name="gosProfile" value="$gos-profile" />
+ <parameter name="lldp" value="$asePort.resource-lldp" />
+ <parameter name="mtu" value="$asePort.resource-mtu" />
+ <outcome value="success">
+ <block>
+ <record plugin="org.onap.ccsdk.sli.core.sli.recording.FileRecorder">
+ <parameter name="file" value="/tmp/sample_r1.log" />
+ <parameter name="field1" value="__TIMESTAMP__"/>
+ <parameter name="field2" value="ACTIVE"/>
+ <parameter name="field3" value="$uni-circuit-id"/>
+ </record>
+ <return status="success">
+ <parameter name="edge-device-clli" value="$asePort.resource-emt-clli" />
+ </return>
+ </block>
+
+ </outcome>
+ <outcome value="already-active">
+ <return status="failure">
+ <parameter name="error-code" value="1590" />
+ <parameter name="error-message" value="Port already active" />
+ </return>
+ </outcome>
+ <outcome value="Other">
+ <return status="failure">
+ <parameter name="error-code" value="1542" />
+ <parameter name="error-message" value="Activation failure" />
+ </return>
+ </outcome>
+ </configure>
+ </outcome>
+
+ <outcome value="not-found">
+
+ <return status="failure">
+ <parameter name="error-code" value="1220" />
+ <parameter name="error-message" value="Circuit not found" />
+ </return>
+
+ </outcome>
+
+ <outcome value="Other">
+ <return status="failure">
+ <parameter name="error-code" value="1230" />
+ <parameter name="error-message" value="Error occurred trying to find circuit" />
+ </return>
+ </outcome>
+ </allocate>
+ </method>
+
+
+
+ <!-- Change provisioning w/o activation -->
+ <method rpc="ase-change-port-prov-request" mode="sync">
+ <allocate plugin="org.onap.ccsdk.sli.adaptors.sample.SampleResource"
+ resource="ase-port" key="uni-circuit-id == $uni-circuit-id" pfx="asePort">
+
+ <outcome value="success">
+ <return status="success">
+ <parameter name="edge-device-clli" value="$asePort.resource-emt-clli" />
+ </return>
+ </outcome>
+
+ <outcome value="not-found">
+ <return status="failure">
+ <parameter name="error-code" value="1220" />
+ <parameter name="error-message" value="Circuit not found" />
+ </return>
+ </outcome>
+
+ <outcome value="Other">
+ <return status="failure">
+ <parameter name="error-code" value="1230" />
+ <parameter name="error-message" value="Error occurred trying to find circuit" />
+ </return>
+ </outcome>
+ </allocate>
+ </method>
+
+
+
+
+ <!-- Release port -->
+
+ <method rpc="ase-release-port-request" mode="sync">
+ <exists plugin="org.onap.ccsdk.sli.adaptors.sample.SampleResource"
+ resource="ase-evc" key="uni-circuit-id == $uni-circuit-id">
+
+ <outcome value="true">
+ <return status="failure">
+ <parameter name="error-code" value="1130" />
+ <parameter name="error-message"
+ value="Cannot release port - used in existing EVC" />
+ </return>
+ </outcome>
+ <outcome value="false">
+ <release plugin="org.onap.ccsdk.sli.adaptors.sample.SampleResource"
+ resource="ase-port" key="uni-circuit-id == $uni-circuit-id">
+ <outcome value="success">
+ <block>
+ <record plugin="org.onap.ccsdk.sli.core.sli.recording.FileRecorder">
+ <parameter name="file" value="/tmp/sample_r1.log" />
+ <parameter name="field1" value="__TIMESTAMP__"/>
+ <parameter name="field2" value="RELEASED"/>
+ <parameter name="field3" value="$uni-circuit-id"/>
+ </record>
+ <return status="success"/>
+ </block>
+ </outcome>
+
+ <outcome value="not-found">
+ <return status="failure">
+ <parameter name="error-code" value="1110" />
+ <parameter name="error-message" value="No port found for this uni-circuit-id" />
+ </return>
+ </outcome>
+
+ <outcome value="Other">
+ <return status="failure">
+ <parameter name="error-code" value="1130" />
+ <parameter name="error-message"
+ value="Error encountered trying to release port" />
+ </return>
+ </outcome>
+ </release>
+ </outcome>
+ </exists>
+ </method>
+
+</service-logic>
+
diff --git a/core/sli/common/src/test/resources/JsonObject.json b/core/sli/common/src/test/resources/JsonObject.json
new file mode 100644
index 000000000..0578368f8
--- /dev/null
+++ b/core/sli/common/src/test/resources/JsonObject.json
@@ -0,0 +1,5 @@
+{
+ "aaa": "123",
+ "bbb": "xyz",
+ "c.d": "abc"
+} \ No newline at end of file
diff --git a/core/sli/common/src/test/resources/ObjectMenu.json b/core/sli/common/src/test/resources/ObjectMenu.json
new file mode 100644
index 000000000..56f842d48
--- /dev/null
+++ b/core/sli/common/src/test/resources/ObjectMenu.json
@@ -0,0 +1,43 @@
+{
+ "menu": [{
+ "id": "1",
+ "type": "pizza",
+ "name": "plain",
+ "calories": 1000,
+ "vegetarian": true
+ }, {
+ "id": "2",
+ "type": "pizza",
+ "name": "Tuesday Special",
+ "calories": 2000,
+ "vegetarian": false,
+ "topping":
+ [{
+ "id": "1",
+ "name": "onion"
+ }, {
+ "id": "2",
+ "name": "pepperoni"
+ }
+ ]
+ }, {
+ "id": "3",
+ "type": "pizza",
+ "name": "House Special",
+ "calories": 1500,
+ "vegetarian": true,
+ "topping":
+ [{
+ "id": "3",
+ "name": "basil"
+ }, {
+ "id": "4",
+ "name": "fresh mozzarella"
+ }, {
+ "id": "5",
+ "name": "tomato"
+ }
+ ]
+ }
+ ]
+}
diff --git a/core/sli/common/src/test/resources/QuotedValues.json b/core/sli/common/src/test/resources/QuotedValues.json
new file mode 100644
index 000000000..8bf91c66b
--- /dev/null
+++ b/core/sli/common/src/test/resources/QuotedValues.json
@@ -0,0 +1,43 @@
+{
+ "menu": [{
+ "id": "1",
+ "type": "pizza",
+ "name": "plain",
+ "calories": "1000",
+ "vegetarian": true
+ }, {
+ "id": "2",
+ "type": "pizza",
+ "name": "Tuesday Special",
+ "calories": "2000",
+ "vegetarian": false,
+ "topping":
+ [{
+ "id": "1",
+ "name": "onion"
+ }, {
+ "id": "2",
+ "name": "pepperoni"
+ }
+ ]
+ }, {
+ "id": "3",
+ "type": "pizza",
+ "name": "House Special",
+ "calories": "1500",
+ "vegetarian": true,
+ "topping":
+ [{
+ "id": "3",
+ "name": "basil"
+ }, {
+ "id": "4",
+ "name": "fresh mozzarella"
+ }, {
+ "id": "5",
+ "name": "tomato"
+ }
+ ]
+ }
+ ]
+}
diff --git a/core/sli/common/src/test/resources/ReleasePortSvcLogic_v101.xml b/core/sli/common/src/test/resources/ReleasePortSvcLogic_v101.xml
new file mode 100644
index 000000000..cee027f75
--- /dev/null
+++ b/core/sli/common/src/test/resources/ReleasePortSvcLogic_v101.xml
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ============LICENSE_START=======================================================
+ ONAP : CCSDK
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property. All rights
+ reserved.
+ ================================================================================
+ 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.
+ ============LICENSE_END=========================================================
+ -->
+
+
+<service-logic xmlns="http://www.onap.org/sdnc/svclogic"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.onap.org/sdnc/svclogic ./svclogic.xsd"
+ module="ase" version="1.0.1">
+
+ <!-- Updated release port logic : deactivate the released port on the EMT -->
+ <method rpc="ase-release-port-request" mode="sync">
+ <exists plugin="org.onap.ccsdk.sli.adaptors.sample.SampleResource"
+ resource="ase-evc" key="uni-circuit-id == $uni-circuit-id">
+
+ <outcome value="true">
+ <return status="failure">
+ <parameter name="error-code" value="1130" />
+ <parameter name="error-message"
+ value="Cannot release port - used in existing EVC" />
+ </return>
+ </outcome>
+ <outcome value="false">
+ <release plugin="org.onap.ccsdk.sli.adaptors.sample.SampleResource"
+ resource="ase-port" key="uni-circuit-id == $uni-circuit-id">
+ <outcome value="success">
+ <configure adaptor="org.onap.ccsdk.sli.adaptors.emt.EmtAdaptor"
+ key="$uni-circuit-id" activate="false">
+
+ <outcome value="success">
+ <block>
+ <record plugin="org.onap.ccsdk.sli.core.sli.recording.FileRecorder">
+ <parameter name="file" value="/tmp/sample_r1.log" />
+ <parameter name="field1" value="__TIMESTAMP__" />
+ <parameter name="field2" value="RELEASED" />
+ <parameter name="field3" value="$uni-circuit-id" />
+ </record>
+ <return status="success">
+ <parameter name="uni-circuit-id" value="$asePort.uni_circuit_id" />
+ </return>
+ </block>
+ </outcome>
+ <outcome value="Other">
+ <return status="failure">
+ <parameter name="error-code" value="1130" />
+ <parameter name="error-message"
+ value="Error encountered trying to de-activate port" />
+ </return>
+ </outcome>
+ </configure>
+ </outcome>
+
+ <outcome value="not-found">
+ <return status="failure">
+ <parameter name="error-code" value="1110" />
+ <parameter name="error-message" value="No port found for this uni-circuit-id" />
+ </return>
+ </outcome>
+
+ <outcome value="Other">
+ <return status="failure">
+ <parameter name="error-code" value="1130" />
+ <parameter name="error-message"
+ value="Error encountered trying to release port" />
+ </return>
+ </outcome>
+ </release>
+ </outcome>
+ </exists>
+ </method>
+
+</service-logic>
+
diff --git a/core/sli/common/src/test/resources/Widget.json b/core/sli/common/src/test/resources/Widget.json
new file mode 100644
index 000000000..6b90907ce
--- /dev/null
+++ b/core/sli/common/src/test/resources/Widget.json
@@ -0,0 +1,27 @@
+{
+ "widget": {
+ "debug": false,
+ "window": {
+ "title": "ONAP Widget",
+ "name": "main_window",
+ "width": 200,
+ "height": 300
+ },
+ "image": {
+ "src": "images/moon.png",
+ "name": "moon",
+ "hOffset": 150,
+ "vOffset": 150,
+ "alignment": "center"
+ },
+ "text": {
+ "data": "Click Me",
+ "size": 21,
+ "style": "bold",
+ "name": "text1",
+ "hOffset": 350,
+ "vOffset": null,
+ "alignment": "center"
+ }
+ }
+} \ No newline at end of file
diff --git a/core/sli/common/src/test/resources/bad_neutron_logic_v11.xml b/core/sli/common/src/test/resources/bad_neutron_logic_v11.xml
new file mode 100644
index 000000000..e6ec8614b
--- /dev/null
+++ b/core/sli/common/src/test/resources/bad_neutron_logic_v11.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ============LICENSE_START=======================================================
+ ONAP : CCSDK
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property. All rights
+ reserved.
+ ================================================================================
+ 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.
+ ============LICENSE_END=========================================================
+ -->
+
+
+<service-logic xmlns="http://www.onap.org/sdnc/svclogic"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.onap.org/sdnc/svclogic ./svclogic.xsd"
+ module="neutron" version="1.0.0">
+
+ <method rpc="canCreateNetwork" mode="sync">
+ <switch test="true">
+ <return status="success">
+ <parameter name="error-code" value="200" />
+ </return>
+ </switch>
+ </method>
+
+ <method rpc="networkCreated" mode="sync">
+ <switch test="`(length($network.segment[0].provider-physical-network) >= 5) and (substr($network.segment[0].provider-physical-network,0,5) == 'dvspg')`">
+ <outcome value="true">
+ <block>
+ <set>
+ <parameter name="vlanlist" value="`$network.segment[0].provider-segmentation-id`"/>
+ </set>
+ <for index="i" start="1" end="`$network.num-segments`">
+ <set>
+ <parameter name="vlanlist" value="`$vlanlist+','+$network.segment[$i].provider-segmentation-id`"/>
+ </set>
+ </for>
+
+ <switch test="true">
+ <return status="success"/>
+ </switch>
+ </block>
+ </outcome>
+ <outcome value="Other">
+ <return status="success">
+ <parameter name="error-code" value="200"/>
+ </return>
+ </outcome>
+ </switch>
+ </method>
+
+</service-logic>
diff --git a/core/sli/common/src/test/resources/dblib.properties b/core/sli/common/src/test/resources/dblib.properties
new file mode 100755
index 000000000..f08dce7a0
--- /dev/null
+++ b/core/sli/common/src/test/resources/dblib.properties
@@ -0,0 +1,14 @@
+org.onap.ccsdk.sli.dbtype=jdbc
+org.onap.ccsdk.sli.jdbc.hosts=sdnctldb01,sdnctldb02
+org.onap.ccsdk.sli.jdbc.url=jdbc:derby:memory:test;create=true
+org.onap.ccsdk.sli.jdbc.driver=org.apache.derby.jdbc.EmbeddedDriver
+org.onap.ccsdk.sli.jdbc.database=test
+org.onap.ccsdk.sli.jdbc.user=test
+org.onap.ccsdk.sli.jdbc.password=test
+org.onap.ccsdk.sli.jdbc.connection.name=sdnctldb01
+
+org.onap.ccsdk.sli.jdbc.connection.timeout=50
+org.onap.ccsdk.sli.jdbc.request.timeout=100
+org.onap.ccsdk.sli.jdbc.limit.init=10
+org.onap.ccsdk.sli.jdbc.limit.min=10
+org.onap.ccsdk.sli.jdbc.limit.max=20
diff --git a/core/sli/common/src/test/resources/expression.tests b/core/sli/common/src/test/resources/expression.tests
new file mode 100755
index 000000000..c352e9b08
--- /dev/null
+++ b/core/sli/common/src/test/resources/expression.tests
@@ -0,0 +1,19 @@
+$uni-circuit-id
+$asePort
+length($uni-circuit-id) > 0
+$asePort.uni-circuit-id
+$uni-cir-units * 1000 * 100 / 100
+$uni-cir-units / 1000
+$uni-cir-units - 100
+$uni-cir-units + 100
+(value * 3 - $arg1 > 0) and (length($uni-circuit-id) == 0)
+'pg-'+$network.name
+$network.segment[0].provider-physical-network
+length($network_segment[0].provider-physical-network) >= 5
+substr($network_segment[0].provider-physical-network,0,5) == 'dvspg'
+length($network_segment[0].provider-physical-network) >= 5 and substr($network_segment[0].provider-physical-network,0,5) == 'dvspg'
+(length($network_segment[0].provider-physical-network) >= 5) and (substr($network_segment[0].provider-physical-network,0,5) == 'dvspg')
+4-2-2
+1+1
+1
+1+2*3-4
diff --git a/core/sli/common/src/test/resources/graphs/sliapi/graph.versions b/core/sli/common/src/test/resources/graphs/sliapi/graph.versions
new file mode 100644
index 000000000..d72920a43
--- /dev/null
+++ b/core/sli/common/src/test/resources/graphs/sliapi/graph.versions
@@ -0,0 +1 @@
+sli healthcheck 1.0.0 sync
diff --git a/core/sli/common/src/test/resources/graphs/sliapi/sli_healthcheck.xml b/core/sli/common/src/test/resources/graphs/sliapi/sli_healthcheck.xml
new file mode 100644
index 000000000..d512f546f
--- /dev/null
+++ b/core/sli/common/src/test/resources/graphs/sliapi/sli_healthcheck.xml
@@ -0,0 +1,27 @@
+<!--
+ ============LICENSE_START=======================================================
+ openECOMP : SDN-C
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property. All rights
+ reserved.
+ ================================================================================
+ 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.
+ ============LICENSE_END=========================================================
+ -->
+
+<service-logic xmlns="http://www.onap.org/sdnc/svclogic"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.onap.org/sdnc/svclogic ./svclogic.xsd" module='sli' version='1.0.0'><method rpc='healthcheck' mode='sync'>
+<set>
+<parameter name='error-code' value='200' />
+<parameter name='error-message' value='SDN-C is healthy'/>
+<parameter name='ack-final' value='Y'/>
+</set></method></service-logic>
diff --git a/core/sli/common/src/test/resources/l3sdn_logic_v10.xml b/core/sli/common/src/test/resources/l3sdn_logic_v10.xml
new file mode 100644
index 000000000..58a420f9e
--- /dev/null
+++ b/core/sli/common/src/test/resources/l3sdn_logic_v10.xml
@@ -0,0 +1,208 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- ============LICENSE_START=======================================================
+ ONAP : CCSDK ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. ================================================================================
+ 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. ============LICENSE_END========================================================= -->
+
+
+<service-logic xmlns="http://www.onap.org/sdnc/svclogic"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.onap.org/sdnc/svclogic ./svclogic.xsd"
+ module="neutron" version="1.0.0">
+
+ <method rpc="canCreateNetwork" mode="sync">
+ <return status="success">
+ <parameter name="error-code" value="200" />
+ </return>
+ </method>
+
+ <method rpc="switchTester" mode="sync">
+
+ <switch test="`$test-value`">
+ <outcome value="">
+ <return status="success">
+ <parameter name="visited-outcome" value="empty string" />
+ </return>
+ </outcome>
+ <outcome value="Other">
+ <return status="success">
+ <parameter name="visited-outcome" value="Other" />
+ </return>
+ </outcome>
+ </switch>
+
+
+ </method>
+
+ <method rpc="forRecordTester" mode="sync">
+ <for index="i" start="0" end="1">
+ <record plugin="org.onap.ccsdk.sli.core.sli.provider.DummyRecorder">
+ <parameter name="level" value="INFO"/>
+ <parameter name="field1" value="`forRecordTester message $i`"/>
+ </record>
+ </for>
+ </method>
+
+ <method rpc="whileNodeTester" mode="sync">
+ <while test="`$test-value`">
+ <break/>
+ </while>
+
+ </method>
+
+ <method rpc="resourceTester" mode="sync">
+ <block>
+ <set>
+ <parameter name='resource-plugin'
+ value='org.onap.ccsdk.sli.core.sli.provider.DummyResource' />
+ </set>
+
+ <save plugin="`$resource-plugin`" resource="sample" key="sample-key == 'resourceTester.status'">
+ <parameter name="sample-key" value="resourceTester.status"/>
+ <parameter name="sample-value" value="FAILED"/>
+ </save>
+
+ <update plugin="`$resource-plugin`" resource="sample" key="sample-key == 'resourceTester.status'">
+ <parameter name="sample-key" value="resourceTester.status"/>
+ <parameter name="sample-value" value="PASSED"/>
+ </update>
+
+ <get-resource plugin="`$resource-plugin`" resource="sample" key="sample-key == 'resourceTester.status'" pfx="sample"/>
+
+ <exists plugin="`$resource-plugin`" resource="sample" key="sample-key == 'resourceTester.status'"/>
+
+ <is-available plugin="`$resource-plugin`" resource="sample" key="sample-key == 'resourceTester.status'"/>
+
+ <reserve plugin="`$resource-plugin`" resource="sample" key="sample-key == 'resourceTester.status'"/>
+
+ <release plugin="`$resource-plugin`" resource="sample" key="sample-key == 'resourceTester.status'"/>
+
+
+ <reserve plugin="`$resource-plugin`" resource="sample" key="sample-key == 'resourceTester.status'"/>
+
+ <notify plugin="`$resource-plugin`" resource="sample" action="RESERVE"/>
+
+ <delete plugin="`$resource-plugin`" resource="sample" key="sample-key == 'resourceTester.status'"/>
+
+
+
+ </block>
+ </method>
+
+ <method rpc="configureTester" mode="sync">
+ <block>
+ <set>
+ <parameter name='configure-plugin'
+ value='org.onap.ccsdk.sli.core.sli.provider.DummyAdaptor' />
+ </set>
+ <configure adaptor="`$configure-plugin`" key="dummy" activate="true">
+ <parameter name="field1" value="1"/>
+ </configure>
+ <configure adaptor="`$configure-plugin`" key="SUCCESS" activate="true">
+ <parameter name="field1" value="1"/>
+ </configure>
+ <configure adaptor="`$configure-plugin`" key="ALREADY_ACTIVE" activate="true">
+ <parameter name="field1" value="1"/>
+ </configure>
+ <configure adaptor="`$configure-plugin`" key="NOT_FOUND" activate="true">
+ <parameter name="field1" value="1"/>
+ </configure>
+ <configure adaptor="`$configure-plugin`" key="NOT_READY" activate="true">
+ <parameter name="field1" value="1"/>
+ </configure>
+ <configure adaptor="`$configure-plugin`" key="FAILURE" activate="true">
+ <parameter name="field1" value="1"/>
+ </configure>
+ <configure adaptor="`$configure-plugin`" key="dummy" activate="false">
+ <parameter name="field1" value="1"/>
+ </configure>
+ <configure adaptor="`$configure-plugin`" key="SUCCESS" activate="false">
+ <parameter name="field1" value="1"/>
+ </configure>
+ <configure adaptor="`$configure-plugin`" key="ALREADY_ACTIVE" activate="false">
+ <parameter name="field1" value="1"/>
+ </configure>
+ <configure adaptor="`$configure-plugin`" key="NOT_FOUND" activate="false">
+ <parameter name="field1" value="1"/>
+ </configure>
+ <configure adaptor="`$configure-plugin`" key="NOT_READY" activate="false">
+ <parameter name="field1" value="1"/>
+ </configure>
+ <configure adaptor="`$configure-plugin`" key="FAILURE" activate="false">
+ <parameter name="field1" value="1"/>
+ </configure>
+
+ </block>
+ </method>
+
+
+ <method rpc="javaPluginTester" mode="sync">
+ <block>
+ <set>
+ <parameter name='java-plugin'
+ value='org.onap.ccsdk.sli.core.sli.provider.VoidDummyPlugin' />
+ </set>
+ <execute plugin="`$java-plugin`" method="dummy"/>
+ </block>
+ </method>
+
+ <method rpc="allNodesTester" mode="sync">
+ <block>
+ <set>
+ <parameter name='resource-plugin'
+ value='org.onap.ccsdk.sli.core.sli.provider.DummyResource' />
+ <parameter name='configure-plugin'
+ value='org.onap.ccsdk.sli.core.sli.provider.DummyAdaptor' />
+ <parameter name='java-plugin'
+ value='org.onap.ccsdk.sli.core.sli.provider.VoidDummyPlugin' />
+
+ </set>
+
+ <call rpc="switchTester" mode="sync" />
+
+ <call rpc="forRecordTester" mode="sync"/>
+
+ <call rpc="resourceTester" mode="sync"/>
+
+ <call rpc="configureTester" mode="sync"/>
+
+ <call rpc="javaPluginTester" mode="sync"/>
+
+ <call rpc="whileNodeTester" mode="sync"/>
+
+ </block>
+ </method>
+
+ <method rpc="networkCreated" mode="sync">
+ <switch
+ test="length($network.segment[0].provider-physical-network) >= 5 and substr($network.segment[0].provider-physical-network,0,5) == 'dvspg'">
+ <outcome value="true">
+ <block>
+ <set>
+ <parameter name="$vlanlist"
+ value="$network.segment[0].provider-segmentation-id" />
+ </set>
+ <for index="i" start="1" end="$network.num-segments">
+ <set>
+ <parameter name="$vlanlist"
+ value="eval($vlanlist+','+$network.segment[i].provider-segmentation-id)" />
+ </set>
+ </for>
+
+ </block>
+ </outcome>
+ <outcome value="Other">
+ <return status="success">
+ <parameter name="error-code" value="200" />
+ </return>
+ </outcome>
+ </switch>
+ </method>
+
+</service-logic>
diff --git a/core/sli/common/src/test/resources/log4j2.properties b/core/sli/common/src/test/resources/log4j2.properties
new file mode 100644
index 000000000..3a5d8ef76
--- /dev/null
+++ b/core/sli/common/src/test/resources/log4j2.properties
@@ -0,0 +1,39 @@
+###
+# ============LICENSE_START=======================================================
+# ONAP : CCSDK
+# ================================================================================
+# Copyright (C) 2020 AT&T Intellectual Property. All rights
+# reserved.
+# ================================================================================
+# 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.
+# ============LICENSE_END=========================================================
+###
+
+status = error
+name = PropertiesConfig
+
+filters = threshold
+
+filter.threshold.type = ThresholdFilter
+filter.threshold.level = debug
+
+appenders = console
+
+appender.console.type = Console
+appender.console.name = STDOUT
+appender.console.layout.type = PatternLayout
+appender.console.layout.pattern = %d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
+
+rootLogger.level = debug
+rootLogger.appenderRefs = stdout
+rootLogger.appenderRef.stdout.ref = STDOUT
diff --git a/core/sli/common/src/test/resources/mergetest.xml b/core/sli/common/src/test/resources/mergetest.xml
new file mode 100644
index 000000000..95c26da27
--- /dev/null
+++ b/core/sli/common/src/test/resources/mergetest.xml
@@ -0,0 +1,54 @@
+<!--
+ ============LICENSE_START=======================================================
+ ONAP : CCSDK
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property. All rights
+ reserved.
+ ================================================================================
+ 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.
+ ============LICENSE_END=========================================================
+ -->
+
+<multicast-parameters xmlns="org.onap.sdnc:test">
+ <vpn-v4-multicast-enabled>Y</vpn-v4-multicast-enabled>
+ <v4-multicast>
+ <v4-pim-ssm-default-range>Y</v4-pim-ssm-default-range>
+ <v4-data-mdt>11.11.11.11</v4-data-mdt>
+ <v4-data-mdt-wildcard-mask>2.2.2.2</v4-data-mdt-wildcard-mask>
+ <max-routes-limit>100</max-routes-limit>
+ <v4-default-mdt>1.1.1.1</v4-default-mdt>
+ <v4-pim-sm-static-override>N</v4-pim-sm-static-override>
+ <v4-pim-ssm-groups>
+ <v4-pim-ssm-group-address>4.4.4.4</v4-pim-ssm-group-address>
+ </v4-pim-ssm-groups>
+ <v4-pim-ssm-groups>
+ <v4-pim-ssm-group-address>3.3.3.3</v4-pim-ssm-group-address>
+ </v4-pim-ssm-groups>
+ <v4-static-rp-triplet>
+ <rp-address>8.8.8.8</rp-address>
+ <c-groups>
+ <c-group-address-prefix>10.10.10.10</c-group-address-prefix>
+ </c-groups>
+ <c-groups>
+ <c-group-address-prefix>9.9.9.9</c-group-address-prefix>
+ </c-groups>
+ </v4-static-rp-triplet>
+ <v4-static-rp-triplet>
+ <rp-address>7.7.7.7</rp-address>
+ <c-groups>
+ <c-group-address-prefix>6.6.6.6</c-group-address-prefix>
+ </c-groups>
+ <c-groups>
+ <c-group-address-prefix>5.5.5.5</c-group-address-prefix>
+ </c-groups>
+ </v4-static-rp-triplet>
+ </v4-multicast>
+</multicast-parameters>
diff --git a/core/sli/common/src/test/resources/neutron_logic_v10.xml b/core/sli/common/src/test/resources/neutron_logic_v10.xml
new file mode 100644
index 000000000..74088036b
--- /dev/null
+++ b/core/sli/common/src/test/resources/neutron_logic_v10.xml
@@ -0,0 +1,56 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ============LICENSE_START=======================================================
+ ONAP : CCSDK
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property. All rights
+ reserved.
+ ================================================================================
+ 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.
+ ============LICENSE_END=========================================================
+ -->
+
+
+<service-logic xmlns="http://www.onap.org/sdnc/svclogic"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.onap.org/sdnc/svclogic ./svclogic.xsd"
+ module="neutron" version="1.0.0">
+
+ <method rpc="canCreateNetwork" mode="sync">
+ <return status="success">
+ <parameter name="error-code" value="200" />
+ </return>
+ </method>
+
+ <method rpc="networkCreated" mode="sync">
+ <switch test="`(length($network.segment[0].provider-physical-network) >= 5) and (substr($network.segment[0].provider-physical-network,0,5) == 'dvspg')`">
+ <outcome value="true">
+ <block>
+ <set>
+ <parameter name="vlanlist" value="`$network.segment[0].provider-segmentation-id`"/>
+ </set>
+ <for index="i" start="1" end="`$network.num-segments`">
+ <set>
+ <parameter name="vlanlist" value="`$vlanlist+','+$network.segment[$i].provider-segmentation-id`"/>
+ </set>
+ </for>
+
+ </block>
+ </outcome>
+ <outcome value="Other">
+ <return status="success">
+ <parameter name="error-code" value="200"/>
+ </return>
+ </outcome>
+ </switch>
+ </method>
+
+</service-logic>
diff --git a/core/sli/common/src/test/resources/nonsense.xml b/core/sli/common/src/test/resources/nonsense.xml
new file mode 100644
index 000000000..c30c6bfc6
--- /dev/null
+++ b/core/sli/common/src/test/resources/nonsense.xml
@@ -0,0 +1,24 @@
+<!--
+ ============LICENSE_START=======================================================
+ ONAP : CCSDK
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property. All rights
+ reserved.
+ ================================================================================
+ 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.
+ ============LICENSE_END=========================================================
+ -->
+
+<non>
+<sense>Hello world</sense>
+</non>
diff --git a/core/sli/common/src/test/resources/parser-bad.tests b/core/sli/common/src/test/resources/parser-bad.tests
new file mode 100755
index 000000000..82913afc2
--- /dev/null
+++ b/core/sli/common/src/test/resources/parser-bad.tests
@@ -0,0 +1,3 @@
+bad_neutron_logic_v11.xml
+EvcActivateSvcLogic_v100.xml
+nonsense.xml \ No newline at end of file
diff --git a/core/sli/common/src/test/resources/parser-good.tests b/core/sli/common/src/test/resources/parser-good.tests
new file mode 100755
index 000000000..4147fdb62
--- /dev/null
+++ b/core/sli/common/src/test/resources/parser-good.tests
@@ -0,0 +1,3 @@
+ReleasePortSvcLogic_v101.xml
+neutron_logic_v10.xml
+l3sdn_logic_v10.xml
diff --git a/core/sli/common/src/test/resources/simplelogger.properties b/core/sli/common/src/test/resources/simplelogger.properties
new file mode 100644
index 000000000..73e4d3a99
--- /dev/null
+++ b/core/sli/common/src/test/resources/simplelogger.properties
@@ -0,0 +1,24 @@
+###
+# ============LICENSE_START=======================================================
+# ONAP : CCSDK
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights
+# reserved.
+# ================================================================================
+# 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.
+# ============LICENSE_END=========================================================
+###
+
+org.slf4j.simpleLogger.defaultLogLevel=info
+org.slf4j.simplelogger.log.org.onap.ccsdk.sli.core.sli.SvcLogicContext=debug
+org.slf4j.simplelogger.log.SvcLogicContext=debug
diff --git a/core/sli/common/src/test/resources/svclogic.properties b/core/sli/common/src/test/resources/svclogic.properties
new file mode 100644
index 000000000..426960f76
--- /dev/null
+++ b/core/sli/common/src/test/resources/svclogic.properties
@@ -0,0 +1,27 @@
+###
+# ============LICENSE_START=======================================================
+# ONAP : CCSDK
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights
+# reserved.
+# ================================================================================
+# 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.
+# ============LICENSE_END=========================================================
+###
+
+org.onap.ccsdk.sli.dbtype = jdbc
+org.onap.ccsdk.sli.jdbc.url=jdbc:derby:memory:sdnctl;create=true
+org.onap.ccsdk.sli.jdbc.driver=org.apache.derby.jdbc.EmbeddedDriver
+org.onap.ccsdk.sli.jdbc.database = sdnctl
+org.onap.ccsdk.sli.jdbc.user = test
+org.onap.ccsdk.sli.jdbc.password = test
diff --git a/core/sli/common/src/test/resources/svclogic.sh b/core/sli/common/src/test/resources/svclogic.sh
new file mode 100644
index 000000000..67977c3d9
--- /dev/null
+++ b/core/sli/common/src/test/resources/svclogic.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+
+###
+# ============LICENSE_START=======================================================
+# ONAP : CCSDK
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights
+# reserved.
+# ================================================================================
+# 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.
+# ============LICENSE_END=========================================================
+###
+
+MYSQL_JDBC_DRIVER=${MYSQL_JDBC_DRIVER:-/home/ubuntu/mysql-connector-java-5.1.38.1.jar}
+SLI_COMMON_TARGETDIR=${SLI_COMMON_TARGETDIR:-/home/ubuntu/opendaylight/plugins}
+#SLI_COMMON_TARGETDIR=${SLI_COMMON_TARGETDIR:-/home/ubuntu/git/sdnctl/sli/common/target}
+SLI_VERSION=${SLI_VERSION:-1.1.0-SNAPSHOT}
+SLI_COMMON_JAR=${SLI_COMMON_JAR:=${SLI_COMMON_TARGETDIR}/sli-common-${SLI_VERSION}.jar}
+
+echo SLI_COMMON_JAR is $SLI_COMMON_JAR
+
+java -cp ${CLASSPATH}:${MYSQL_JDBC_DRIVER}:${SLI_COMMON_JAR} org.onap.ccsdk.sli.core.sli.SvcLogicParser $*
diff --git a/core/sli/installer/pom.xml b/core/sli/installer/pom.xml
new file mode 100755
index 000000000..40776bdcf
--- /dev/null
+++ b/core/sli/installer/pom.xml
@@ -0,0 +1,144 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>odlparent-lite</artifactId>
+ <version>2.1.0-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sli-installer</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>pom</packaging>
+
+ <name>ccsdk-sli-core :: sli :: ${project.artifactId}</name>
+
+ <properties>
+ <application.name>ccsdk-sli</application.name>
+ <features.boot>${application.name}</features.boot>
+ <features.repositories>mvn:org.onap.ccsdk.sli.core/${features.boot}/${project.version}/xml/features</features.repositories>
+ <include.transitive.dependencies>false</include.transitive.dependencies>
+ </properties>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>dblib-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+ <dependencies>
+
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sli-common</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sli-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>maven-repo-zip</id>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ <phase>package</phase>
+ <configuration>
+ <attach>true</attach>
+ <finalName>stage/${application.name}-${project.version}</finalName>
+ <descriptors>
+ <descriptor>src/assembly/assemble_mvnrepo_zip.xml</descriptor>
+ </descriptors>
+ <appendAssemblyId>true</appendAssemblyId>
+ </configuration>
+ </execution>
+ <execution>
+ <id>installer-zip</id>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ <phase>package</phase>
+ <configuration>
+ <attach>true</attach>
+ <finalName>${application.name}-${project.version}-installer</finalName>
+ <descriptors>
+ <descriptor>src/assembly/assemble_installer_zip.xml</descriptor>
+ </descriptors>
+ <appendAssemblyId>false</appendAssemblyId>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>copy-dependencies</id>
+ <goals>
+ <goal>copy-dependencies</goal>
+ </goals>
+ <phase>prepare-package</phase>
+ <configuration>
+ <transitive>false</transitive>
+ <outputDirectory>${project.build.directory}/assembly/system</outputDirectory>
+ <overWriteReleases>false</overWriteReleases>
+ <overWriteSnapshots>true</overWriteSnapshots>
+ <overWriteIfNewer>true</overWriteIfNewer>
+ <useRepositoryLayout>true</useRepositoryLayout>
+ <addParentPoms>false</addParentPoms>
+ <copyPom>false</copyPom>
+ <includeGroupIds>org.onap.ccsdk.sli.core</includeGroupIds>
+ <excludeArtifactIds>utils-provider,dblib-provider</excludeArtifactIds>
+ <scope>provided</scope>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <artifactId>maven-resources-plugin</artifactId>
+ <version>2.6</version>
+ <executions>
+ <execution>
+ <id>copy-version</id>
+ <goals>
+ <goal>copy-resources</goal>
+ </goals><!-- here the phase you need -->
+ <phase>validate</phase>
+ <configuration>
+ <outputDirectory>${basedir}/target/stage</outputDirectory>
+ <resources>
+ <resource>
+ <directory>src/main/resources/scripts</directory>
+ <includes>
+ <include>install-feature.sh</include>
+ </includes>
+ <filtering>true</filtering>
+ </resource>
+ </resources>
+ </configuration>
+ </execution>
+
+ </executions>
+ </plugin>
+
+ </plugins>
+ </build>
+</project>
diff --git a/core/sli/installer/src/assembly/assemble_installer_zip.xml b/core/sli/installer/src/assembly/assemble_installer_zip.xml
new file mode 100644
index 000000000..2d3c0606d
--- /dev/null
+++ b/core/sli/installer/src/assembly/assemble_installer_zip.xml
@@ -0,0 +1,59 @@
+<!--
+ ============LICENSE_START=======================================================
+ ONAP : CCSDK
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property. All rights
+ reserved.
+ ================================================================================
+ 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.
+ ============LICENSE_END=========================================================
+ -->
+
+<!-- Defines how we build the .zip file which is our distribution. -->
+
+<assembly
+ xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
+ <id>bin</id>
+ <formats>
+ <format>zip</format>
+ </formats>
+
+ <!-- we want "system" and related files right at the root level
+ as this file is suppose to be unzip on top of a karaf
+ distro. -->
+ <includeBaseDirectory>false</includeBaseDirectory>
+
+ <fileSets>
+ <fileSet>
+ <directory>target/stage/</directory>
+ <outputDirectory>${application.name}</outputDirectory>
+ <fileMode>755</fileMode>
+ <includes>
+ <include>*.sh</include>
+ </includes>
+ </fileSet>
+ <fileSet>
+ <directory>target/stage/</directory>
+ <outputDirectory>${application.name}</outputDirectory>
+ <fileMode>644</fileMode>
+ <excludes>
+ <exclude>*.sh</exclude>
+ </excludes>
+ </fileSet>
+ </fileSets>
+
+
+
+</assembly>
diff --git a/core/sli/installer/src/assembly/assemble_mvnrepo_zip.xml b/core/sli/installer/src/assembly/assemble_mvnrepo_zip.xml
new file mode 100644
index 000000000..6a21012dc
--- /dev/null
+++ b/core/sli/installer/src/assembly/assemble_mvnrepo_zip.xml
@@ -0,0 +1,42 @@
+<!-- ============LICENSE_START=======================================================
+ ONAP : CCSDK
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property. All rights
+ reserved.
+ ================================================================================
+ 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.
+ ============LICENSE_END========================================================= -->
+
+<!-- Defines how we build the .zip file which is our distribution. -->
+
+<assembly
+ xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
+ <id>repo</id>
+ <formats>
+ <format>zip</format>
+ </formats>
+
+ <!-- we want "system" and related files right at the root level as this
+ file is suppose to be unzip on top of a karaf distro. -->
+ <includeBaseDirectory>false</includeBaseDirectory>
+
+ <fileSets>
+ <fileSet>
+ <directory>target/assembly/</directory>
+ <outputDirectory>.</outputDirectory>
+ <excludes>
+ </excludes>
+ </fileSet>
+ </fileSets>
+
+
+
+</assembly>
diff --git a/core/sli/installer/src/main/resources/scripts/install-feature.sh b/core/sli/installer/src/main/resources/scripts/install-feature.sh
new file mode 100644
index 000000000..74b95b5c8
--- /dev/null
+++ b/core/sli/installer/src/main/resources/scripts/install-feature.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+
+###
+# ============LICENSE_START=======================================================
+# ONAP : CCSDK
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights
+# reserved.
+# ================================================================================
+# 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.
+# ============LICENSE_END=========================================================
+###
+
+ODL_HOME=${ODL_HOME:-/opt/opendaylight/current}
+ODL_KARAF_CLIENT=${ODL_KARAF_CLIENT:-${ODL_HOME}/bin/client}
+INSTALLERDIR=$(dirname $0)
+
+REPOZIP=${INSTALLERDIR}/${features.boot}-${project.version}.zip
+
+if [ -f ${REPOZIP} ]
+then
+ unzip -d ${ODL_HOME} ${REPOZIP}
+else
+ echo "ERROR : repo zip ($REPOZIP) not found"
+ exit 1
+fi
+
+${ODL_KARAF_CLIENT} feature:repo-add ${features.repositories}
+${ODL_KARAF_CLIENT} feature:install ${features.boot}
diff --git a/core/sli/model/pom.xml b/core/sli/model/pom.xml
new file mode 100755
index 000000000..0b859e7d2
--- /dev/null
+++ b/core/sli/model/pom.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>binding-parent</artifactId>
+ <version>2.1.0-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sli-model</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>bundle</packaging>
+
+ <name>ccsdk-sli-core :: sli :: ${project.artifactId}</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.mdsal.binding.model.ietf</groupId>
+ <artifactId>rfc6991</artifactId>
+ </dependency>
+
+
+ </dependencies>
+</project>
diff --git a/core/sli/model/src/main/yang/sliapi.yang b/core/sli/model/src/main/yang/sliapi.yang
new file mode 100755
index 000000000..a7d52928b
--- /dev/null
+++ b/core/sli/model/src/main/yang/sliapi.yang
@@ -0,0 +1,123 @@
+module SLI-API {
+
+ yang-version 1;
+
+ namespace "org:onap:ccsdk:sli:core:sliapi";
+
+ prefix sample;
+
+ import ietf-inet-types { prefix "inet"; revision-date 2013-07-15; }
+
+ organization "ONAP";
+
+ contact
+ "Dan Timoney";
+
+ description
+ "Defines API to service logic interpreter";
+
+ revision "2016-11-10" {
+ description
+ "REST API to Service Logic Interpreter";
+ }
+
+ grouping parameter-setting {
+ description
+ "Parameter setting";
+
+ leaf parameter-name {
+ type string;
+ description "Parameter name";
+ }
+
+ leaf int-value {
+ type int32;
+ }
+ leaf string-value {
+ type string;
+ }
+ leaf boolean-value {
+ type boolean;
+ }
+ leaf ipaddress-value {
+ type inet:ip-address;
+ }
+ leaf ipprefix-value {
+ type inet:ip-prefix;
+ }
+ leaf port-number {
+ type inet:port-number;
+ }
+ leaf dscp {
+ type inet:dscp;
+ }
+ }
+
+ grouping response-fields {
+ leaf response-code {
+ type string;
+ }
+ leaf ack-final-indicator {
+ type string;
+ }
+ leaf response-message {
+ type string;
+ }
+ leaf context-memory-json {
+ type string;
+ }
+ }
+
+ container test-results {
+ description "Test results";
+
+ list test-result {
+ key "test-identifier";
+
+ leaf test-identifier {
+ type string;
+ }
+
+ leaf-list results {
+ type string;
+ }
+ }
+ }
+
+ rpc execute-graph {
+ description " Method to add a new parameter.";
+ input {
+
+ leaf module-name {
+ type string;
+ }
+
+ leaf rpc-name {
+ type string;
+ }
+
+ leaf mode {
+ type enumeration {
+ enum sync;
+ enum async;
+ }
+ }
+
+ list sli-parameter {
+ key "parameter-name";
+ uses parameter-setting;
+ }
+ }
+
+ output {
+ uses response-fields;
+ }
+ }
+
+ rpc healthcheck {
+ output {
+ uses response-fields;
+ }
+ }
+
+}
diff --git a/core/sli/model/src/main/yang/test-model@2019-07-23.yang b/core/sli/model/src/main/yang/test-model@2019-07-23.yang
new file mode 100755
index 000000000..fc8e8b007
--- /dev/null
+++ b/core/sli/model/src/main/yang/test-model@2019-07-23.yang
@@ -0,0 +1,210 @@
+module test-model {
+
+ yang-version 1;
+
+ namespace "org:onap:ccsdk:sli:core:testmodel";
+
+ prefix sample;
+
+ import ietf-inet-types { prefix "inet"; revision-date 2013-07-15; }
+
+ organization "ONAP";
+
+ contact
+ "Test Author";
+
+ description
+ "A test model not used in business flows";
+
+ revision "2019-07-23" {
+ description
+ "First release of the test model";
+ }
+
+ identity sample-identity {
+ description
+ "Base identity";
+ }
+
+ typedef percentage {
+ type uint8 {
+ range "0 .. 100";
+ }
+ description "represents a percentage";
+ }
+
+ grouping builtin {
+ leaf sample-binary {
+ type binary;
+ }
+ leaf sample-bits {
+ type bits{
+ bit fan-running {
+ position 0;
+ }
+ bit hd-led {
+ position 1;
+ }
+ bit power-led {
+ position 2;
+ }
+ }
+ }
+ leaf sample-boolean {
+ type boolean;
+ }
+ leaf sample-decimal64 {
+ type decimal64{
+ fraction-digits 1;
+ }
+ }
+ leaf sample-empty {
+ type empty;
+ }
+ leaf sample-enumeration {
+ type enumeration{
+ enum "shelf.slot.port";
+ enum "not available";
+ enum "CURRENTLY_AVAILABLE";
+ enum "200OK";
+ enum "hyphen-separated-value";
+ }
+ }
+ leaf sample-identityref {
+ type identityref {
+ base "sample-identity";
+ }
+ }
+ leaf sample-int8 {
+ type int8;
+ }
+ leaf sample-int16 {
+ type int16;
+ }
+ leaf sample-int32 {
+ type int32;
+ }
+ leaf sample-int64 {
+ type int64;
+ }
+ leaf sample-leafref {
+ type leafref {
+ path "../sample-boolean";
+ }
+ }
+ leaf sample-string {
+ type string;
+ }
+ leaf sample-uint8 {
+ type uint8;
+ }
+ leaf sample-uint16 {
+ type uint16;
+ }
+ leaf sample-uint32 {
+ type uint32;
+ }
+ leaf sample-uint64 {
+ type uint64;
+ }
+ leaf sample-union {
+ type union {
+ type int32;
+ type enumeration {
+ enum "unbounded";
+ }
+ }
+ }
+ leaf percent-completed {
+ type percentage;
+ }
+ }
+
+ grouping inet-types-grouping {
+ leaf ip-version {
+ type inet:ip-version;
+ }
+ leaf dscp {
+ type inet:dscp;
+ }
+ leaf port-number {
+ type inet:port-number;
+ }
+ leaf ipv6-flow-label {
+ type inet:ipv6-flow-label;
+ }
+ leaf as-number {
+ type inet:as-number;
+ }
+ leaf ip-address {
+ type inet:ip-address;
+ }
+ leaf ipv4-address {
+ type inet:ipv4-address;
+ }
+ leaf ipv6-address {
+ type inet:ipv6-address;
+ }
+ leaf ip-address-no-zone {
+ type inet:ip-address-no-zone;
+ }
+ leaf ipv4-address-no-zone {
+ type inet:ipv4-address-no-zone;
+ }
+ leaf ipv6-address-no-zone {
+ type inet:ipv6-address-no-zone;
+ }
+ leaf ip-prefix {
+ type inet:ip-prefix;
+ }
+ leaf ipv4-prefix {
+ type inet:ipv4-prefix;
+ }
+ leaf ipv6-prefix {
+ type inet:ipv6-prefix;
+ }
+ leaf domain-name {
+ type inet:domain-name;
+ }
+ leaf host {
+ type inet:host;
+ }
+ leaf uri {
+ type inet:uri;
+ }
+ anyxml data;
+ }
+
+ container sample-container {
+ leaf customer-name {
+ type string;
+ }
+
+ leaf-list customer-nicknames {
+ type string;
+ }
+
+ container login {
+ leaf message {
+ type string;
+ description
+ "Message given at start of login session";
+ }
+
+ list customer-addresses {
+ key "address-name";
+ leaf address-name {
+ type string;
+ }
+ leaf street-address {
+ type string;
+ }
+ leaf state {
+ type string;
+ }
+ }
+ }
+ uses builtin;
+ uses inet-types-grouping;
+ }
+}
diff --git a/core/sli/pom.xml b/core/sli/pom.xml
new file mode 100755
index 000000000..cfb7656d1
--- /dev/null
+++ b/core/sli/pom.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>odlparent-lite</artifactId>
+ <version>2.1.0-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sli</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>pom</packaging>
+
+ <name>ccsdk-sli-core :: sli</name>
+ <description>The Service Logic Interpreter (SLI) allows service planners to design the flow of logic within the SDN controller in an XML format, without a need for custom Java code. </description>
+ <organization>
+ <name>ONAP</name>
+ </organization>
+
+ <modules>
+ <module>provider-base</module>
+ <module>model</module>
+ <module>common</module>
+ <module>provider</module>
+ <module>installer</module>
+ </modules>
+</project>
diff --git a/core/sli/provider-base/pom.xml b/core/sli/provider-base/pom.xml
new file mode 100644
index 000000000..eedce9154
--- /dev/null
+++ b/core/sli/provider-base/pom.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>binding-parent</artifactId>
+ <version>2.1.0-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sli-provider-base</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+
+ <name>ccsdk-sli-core :: sli :: ${project.artifactId}</name>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <sonar.coverage.jacoco.xmlReportPaths>${project.reporting.outputDirectory}/jacoco-ut/jacoco.xml,${project.reporting.outputDirectory}/jacoco-it/jacoco.xml,../provider/target/site/jacoco-aggregate/jacoco.xml</sonar.coverage.jacoco.xmlReportPaths>
+ </properties>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>dblib-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sli-common</artifactId>
+ <version>${project.version}</version>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>commons-lang</groupId>
+ <artifactId>commons-lang</artifactId>
+ <scope>compile</scope>
+ </dependency>
+
+ <!-- Testing Dependencies -->
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ </dependencies>
+</project>
diff --git a/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/AbstractSvcLogicNodeExecutor.java b/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/AbstractSvcLogicNodeExecutor.java
new file mode 100644
index 000000000..031beba2a
--- /dev/null
+++ b/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/AbstractSvcLogicNodeExecutor.java
@@ -0,0 +1,121 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.sli.provider.base;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+import org.onap.ccsdk.sli.core.sli.SvcLogicAdaptor;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.core.sli.SvcLogicExpression;
+import org.onap.ccsdk.sli.core.sli.SvcLogicJavaPlugin;
+import org.onap.ccsdk.sli.core.sli.SvcLogicNode;
+import org.onap.ccsdk.sli.core.sli.SvcLogicRecorder;
+import org.onap.ccsdk.sli.core.sli.SvcLogicResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public abstract class AbstractSvcLogicNodeExecutor {
+ protected SvcLogicResolver resolver;
+ public abstract SvcLogicNode execute(SvcLogicServiceBase svc, SvcLogicNode node, SvcLogicContext ctx) throws SvcLogicException;
+
+ private static final Logger LOG = LoggerFactory.getLogger(AbstractSvcLogicNodeExecutor.class);
+ protected static final String PARAMETER_DEBUG_PATTERN = "Parameter: ({}) resolves to: ({}) which came from the expression: ({})";
+ protected static final String SETTING_DEBUG_PATTERN = "Setting context attribute: ({}) to: ({}) which came from the expression: ({})";
+
+ protected String evaluateNodeTest(SvcLogicNode node, SvcLogicContext ctx)
+ throws SvcLogicException {
+ if (node == null) {
+ return null;
+ }
+
+ return (SvcLogicExpressionResolver.evaluate(node.getAttribute("test"),
+ node, ctx));
+
+ }
+
+ public void setResolver(SvcLogicResolver resolver) {
+ this.resolver = resolver;
+ }
+
+ protected SvcLogicAdaptor getAdaptor(String adaptorName) {
+ return resolver.getSvcLogicAdaptor(adaptorName);
+ }
+
+ protected SvcLogicResource getSvcLogicResource(String resourceName) {
+ return resolver.getSvcLogicResource(resourceName);
+ }
+
+ protected SvcLogicRecorder getSvcLogicRecorder(String recorderName) {
+ return resolver.getSvcLogicRecorder(recorderName);
+ }
+
+ protected SvcLogicJavaPlugin getSvcLogicJavaPlugin(String pluginName){
+ return resolver.getSvcLogicJavaPlugin(pluginName);
+ }
+
+ protected SvcLogicNode getNextNode(SvcLogicNode node, String outValue) {
+ SvcLogicNode nextNode = node.getOutcomeValue(outValue);
+ if (nextNode != null) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("about to execute " + outValue + " branch");
+ }
+ return (nextNode);
+ }
+
+ nextNode = node.getOutcomeValue("Other");
+ if (nextNode != null) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("about to execute Other branch");
+ }
+ } else {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("no " + outValue + " or Other branch found");
+ }
+ }
+ return (nextNode);
+ }
+
+ protected Map<String, String> getResolvedParameters(SvcLogicNode node, SvcLogicContext ctx) throws SvcLogicException{
+ Map<String, String> parmMap = new HashMap<>();
+
+ Set<Map.Entry<String, SvcLogicExpression>> parmSet = node
+ .getParameterSet();
+
+ for (Iterator<Map.Entry<String, SvcLogicExpression>> iter = parmSet
+ .iterator(); iter.hasNext();) {
+ Map.Entry<String, SvcLogicExpression> curEnt = iter.next();
+ String curName = curEnt.getKey();
+
+ SvcLogicExpression curExpr = curEnt.getValue();
+ String curExprValue = SvcLogicExpressionResolver.evaluate(curExpr, node, ctx);
+ LOG.trace(PARAMETER_DEBUG_PATTERN, curName, curExprValue, curExpr);
+ parmMap.put(curName, curExprValue);
+ }
+
+ return parmMap;
+ }
+
+}
diff --git a/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/BlockNodeExecutor.java b/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/BlockNodeExecutor.java
new file mode 100644
index 000000000..7079e263b
--- /dev/null
+++ b/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/BlockNodeExecutor.java
@@ -0,0 +1,71 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.sli.provider.base;
+
+import org.onap.ccsdk.sli.core.sli.SvcLogicConstants;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.core.sli.SvcLogicExpression;
+import org.onap.ccsdk.sli.core.sli.SvcLogicNode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class BlockNodeExecutor extends AbstractSvcLogicNodeExecutor {
+
+ private static final Logger LOG = LoggerFactory
+ .getLogger(BlockNodeExecutor.class);
+
+ @Override
+ public SvcLogicNode execute(SvcLogicServiceBase svc, SvcLogicNode node, SvcLogicContext ctx)
+ throws SvcLogicException {
+
+ SvcLogicExpression atomicExpr = node.getAttribute("atomic");
+ String atomicStr = SvcLogicExpressionResolver.evaluate(atomicExpr, node, ctx);
+ boolean isAtomic = "true".equalsIgnoreCase(atomicStr);
+
+ // Initialize status to success so that at least one outcome will execute
+ ctx.markSuccess();
+
+ int numOutcomes = node.getNumOutcomes();
+
+ for (int i = 0; i < numOutcomes; i++) {
+ if (SvcLogicConstants.FAILURE.equals(ctx.getStatus()) && isAtomic) {
+ LOG.info("Block - stopped executing nodes due to failure status");
+ return(null);
+ }
+
+ SvcLogicNode nextNode = node.getOutcomeValue("" + (i + 1));
+ if (nextNode != null) {
+
+ while (nextNode != null)
+ {
+ nextNode = svc.executeNode(nextNode, ctx);
+ }
+ }
+ }
+
+ return (null);
+ }
+
+
+
+}
diff --git a/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/BreakNodeExecutor.java b/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/BreakNodeExecutor.java
new file mode 100644
index 000000000..603d7abc5
--- /dev/null
+++ b/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/BreakNodeExecutor.java
@@ -0,0 +1,42 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.sli.provider.base;
+
+import org.onap.ccsdk.sli.core.sli.BreakNodeException;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.core.sli.SvcLogicNode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class BreakNodeExecutor extends AbstractSvcLogicNodeExecutor {
+
+ private static final Logger LOG = LoggerFactory.getLogger(BreakNodeExecutor.class);
+
+ @Override
+ public SvcLogicNode execute(SvcLogicServiceBase svc, SvcLogicNode node, SvcLogicContext ctx) throws SvcLogicException {
+ String message = "BreakNodeExecutor encountered break with nodeId " + node.getNodeId();
+ LOG.debug(message);
+ throw new BreakNodeException(message);
+ }
+
+}
diff --git a/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/CallNodeExecutor.java b/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/CallNodeExecutor.java
new file mode 100644
index 000000000..766826f7d
--- /dev/null
+++ b/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/CallNodeExecutor.java
@@ -0,0 +1,170 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Modifications Copyright (C) 2018 IBM.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.sli.provider.base;
+
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.core.sli.SvcLogicExpression;
+import org.onap.ccsdk.sli.core.sli.SvcLogicGraph;
+import org.onap.ccsdk.sli.core.sli.SvcLogicNode;
+import org.onap.ccsdk.sli.core.sli.SvcLogicStore;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class CallNodeExecutor extends AbstractSvcLogicNodeExecutor {
+
+ private static final Logger LOG = LoggerFactory
+ .getLogger(CallNodeExecutor.class);
+ private static final String CURRENT_GRAPH="currentGraph";
+
+ @Override
+ public SvcLogicNode execute(SvcLogicServiceBase svc, SvcLogicNode node, SvcLogicContext ctx)
+ throws SvcLogicException {
+
+ String outValue = "not-found";
+
+ SvcLogicGraph myGraph = node.getGraph();
+
+ if (myGraph == null)
+ {
+ LOG.debug("execute: getGraph returned null");
+ }
+
+ SvcLogicExpression moduleExpr = null;
+
+ String module = null;
+
+ moduleExpr = node.getAttribute("module");
+ if (moduleExpr != null)
+ {
+ module = SvcLogicExpressionResolver.evaluate(moduleExpr, node, ctx);
+ }
+
+ if ((module == null) || (module.length() == 0))
+ {
+ if (myGraph != null)
+ {
+ module = myGraph.getModule();
+ }
+ }
+
+ SvcLogicExpression rpcExpr = null;
+ String rpc = null;
+ rpcExpr = node.getAttribute("rpc");
+ if (rpcExpr != null)
+ {
+ rpc = SvcLogicExpressionResolver.evaluate(rpcExpr, node, ctx);
+ }
+
+ if ((rpc == null) || (rpc.length() == 0))
+ {
+ if (myGraph != null)
+ {
+ rpc = myGraph.getRpc();
+ }
+ }
+
+ String mode = null;
+
+ moduleExpr = node.getAttribute("mode");
+ if (moduleExpr != null)
+ {
+ mode = SvcLogicExpressionResolver.evaluate(moduleExpr, node, ctx);
+ }
+
+ if ((mode == null) || (mode.length() == 0))
+ {
+ if (myGraph != null)
+ {
+ mode = myGraph.getMode();
+ }
+ }
+
+ String version = null;
+
+ moduleExpr = node.getAttribute("version");
+ if (moduleExpr != null)
+ {
+ version = SvcLogicExpressionResolver.evaluate(moduleExpr, node, ctx);
+ }
+
+ String parentGraph = ctx.getAttribute(CURRENT_GRAPH);
+ ctx.setAttribute("parentGraph", parentGraph);
+
+ SvcLogicStore store = svc.getStore();
+ String errorMessage = "Parent " + parentGraph + " failed to call child [" + module + "," + rpc + "," + version + "," + mode + "] because the graph could not be found";
+ boolean graphWasCalled = false;
+ if (store != null) {
+ SvcLogicGraph calledGraph = store.fetch(module, rpc, version, mode);
+ if (calledGraph != null) {
+ LOG.debug("Parent " + parentGraph + " is calling child " + calledGraph.toString());
+ ctx.setAttribute(CURRENT_GRAPH, calledGraph.toString());
+ svc.execute(calledGraph, ctx);
+ outValue = ctx.getStatus();
+ graphWasCalled = true;
+ } else {
+ LOG.debug(errorMessage);
+ }
+ } else {
+ LOG.debug("Could not get SvcLogicStore reference");
+ }
+
+ SvcLogicNode nextNode = node.getOutcomeValue(outValue);
+ if (nextNode != null) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("about to execute " + outValue + " branch");
+ }
+ ctx.setAttribute(CURRENT_GRAPH, parentGraph);
+ return (nextNode);
+ }
+
+ nextNode = node.getOutcomeValue("Other");
+ if (nextNode != null) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("about to execute Other branch");
+ }
+ } else {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("no " + outValue + " or Other branch found");
+ }
+ }
+
+ if (graphWasCalled == false) {
+ if (node.getOutcomeValue("catch") != null) {
+ nextNode = node.getOutcomeValue("catch");
+ LOG.debug("graph could not be called, but catch node was found and will be executed");
+ } else {
+ LOG.debug("graph could not be called and no catch node was found, throwing exception");
+ throw new SvcLogicException(errorMessage);
+ }
+ }
+
+ ctx.setAttribute(CURRENT_GRAPH, parentGraph);
+ ctx.setAttribute("parentGraph", null);
+
+ return (nextNode);
+
+ }
+
+}
diff --git a/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/ConfigureNodeExecutor.java b/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/ConfigureNodeExecutor.java
new file mode 100644
index 000000000..a0e3af189
--- /dev/null
+++ b/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/ConfigureNodeExecutor.java
@@ -0,0 +1,242 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Modifications Copyright (C) 2018 IBM.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.sli.provider.base;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+import org.onap.ccsdk.sli.core.sli.SvcLogicAdaptor;
+import org.onap.ccsdk.sli.core.sli.SvcLogicConstants;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.core.sli.SvcLogicExpression;
+import org.onap.ccsdk.sli.core.sli.SvcLogicNode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ConfigureNodeExecutor extends AbstractSvcLogicNodeExecutor {
+ private static final Logger LOG = LoggerFactory
+ .getLogger(ConfigureNodeExecutor.class);
+ private static final String CAUGHT_EXCEPTION_MSG="Caught exception from ";
+ private static final String ALREADY_ACTIVE= "already-active";
+ private static final String NOT_FOUND= "not-found";
+
+ public SvcLogicNode execute(SvcLogicServiceBase svc, SvcLogicNode node,
+ SvcLogicContext ctx) throws SvcLogicException {
+
+ String adaptorName = SvcLogicExpressionResolver.evaluate(
+ node.getAttribute("adaptor"), node, ctx);
+ String outValue = SvcLogicConstants.FAILURE;
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("configure node encountered - looking for adaptor "
+ + adaptorName);
+ }
+
+ SvcLogicAdaptor adaptor = getAdaptor(adaptorName);
+
+ if (adaptor != null) {
+ String activate = SvcLogicExpressionResolver.evaluate(
+ node.getAttribute("activate"), node, ctx);
+ String key = SvcLogicExpressionResolver.evaluate(
+ node.getAttribute("key"), node, ctx);
+
+ boolean hasParms = false;
+
+ Map<String, String> parmMap = getResolvedParameters(node,ctx);
+ if(!parmMap.isEmpty()) {
+ hasParms = true;
+ }
+
+ if (hasParms) {
+ SvcLogicAdaptor.ConfigStatus confStatus = SvcLogicAdaptor.ConfigStatus.FAILURE;
+
+ try {
+ confStatus = adaptor.configure(key, parmMap, ctx);
+ } catch (Exception e) {
+ LOG.warn(CAUGHT_EXCEPTION_MSG+adaptorName+".configure", e);
+ confStatus = SvcLogicAdaptor.ConfigStatus.FAILURE;
+ }
+
+ switch (confStatus) {
+ case SUCCESS:
+ outValue = SvcLogicConstants.SUCCESS;
+ if ((activate != null) && (activate.length() > 0)) {
+ if ("true".equalsIgnoreCase(activate)) {
+ SvcLogicAdaptor.ConfigStatus activateStatus = SvcLogicAdaptor.ConfigStatus.FAILURE;
+
+ try {
+ activateStatus = adaptor.activate(key, ctx);
+ } catch (Exception e) {
+
+ LOG.warn(CAUGHT_EXCEPTION_MSG+adaptorName+".activate", e);
+ activateStatus = SvcLogicAdaptor.ConfigStatus.FAILURE;
+ }
+ switch (activateStatus) {
+ case SUCCESS:
+ break;
+ case ALREADY_ACTIVE:
+ outValue = ALREADY_ACTIVE;
+ break;
+ case NOT_FOUND:
+ outValue = NOT_FOUND;
+ break;
+ case NOT_READY:
+ outValue = "not-ready";
+ break;
+ case FAILURE:
+ default:
+ outValue = SvcLogicConstants.FAILURE;
+ }
+ } else if ("false".equalsIgnoreCase(activate)) {
+ SvcLogicAdaptor.ConfigStatus deactivateStatus = SvcLogicAdaptor.ConfigStatus.FAILURE;
+
+ try {
+ deactivateStatus = adaptor.deactivate(key, ctx);
+ } catch (Exception e) {
+
+ LOG.warn(CAUGHT_EXCEPTION_MSG+adaptorName+".deactivate", e);
+ deactivateStatus = SvcLogicAdaptor.ConfigStatus.FAILURE;
+ }
+ switch (deactivateStatus) {
+ case SUCCESS:
+ break;
+ case ALREADY_ACTIVE:
+ outValue = ALREADY_ACTIVE;
+ break;
+ case NOT_FOUND:
+ outValue = NOT_FOUND;
+ break;
+ case NOT_READY:
+ outValue = "not-ready";
+ break;
+ case FAILURE:
+ default:
+ outValue = SvcLogicConstants.FAILURE;
+ }
+ }
+ }
+ break;
+ case ALREADY_ACTIVE:
+ outValue = ALREADY_ACTIVE;
+ break;
+ case NOT_FOUND:
+ outValue = NOT_FOUND;
+ break;
+ case NOT_READY:
+ outValue = "not-ready";
+ break;
+ case FAILURE:
+ default:
+ outValue = SvcLogicConstants.FAILURE;
+ }
+ } else {
+ if ((activate != null) && (activate.length() > 0)) {
+ if ("true".equalsIgnoreCase(activate)) {
+ SvcLogicAdaptor.ConfigStatus activateStatus = SvcLogicAdaptor.ConfigStatus.FAILURE;
+ try {
+ activateStatus = adaptor.activate(key, ctx);
+ } catch (Exception e) {
+ LOG.warn(CAUGHT_EXCEPTION_MSG+adaptorName+".activate", e);
+ activateStatus = SvcLogicAdaptor.ConfigStatus.FAILURE;
+ }
+ switch (activateStatus) {
+ case SUCCESS:
+ outValue = SvcLogicConstants.SUCCESS;
+ break;
+ case ALREADY_ACTIVE:
+ outValue = ALREADY_ACTIVE;
+ break;
+ case NOT_FOUND:
+ outValue = NOT_FOUND;
+ break;
+ case NOT_READY:
+ outValue = "not-ready";
+ break;
+ case FAILURE:
+ default:
+ outValue = SvcLogicConstants.FAILURE;
+ }
+ } else if ("false".equalsIgnoreCase(activate)) {
+ SvcLogicAdaptor.ConfigStatus deactivateStatus = SvcLogicAdaptor.ConfigStatus.FAILURE;
+
+ try {
+ deactivateStatus = adaptor.deactivate(key, ctx);
+ } catch (Exception e) {
+ LOG.warn(CAUGHT_EXCEPTION_MSG+adaptorName+".deactivate", e);
+ deactivateStatus = SvcLogicAdaptor.ConfigStatus.FAILURE;
+ }
+ switch (deactivateStatus) {
+ case SUCCESS:
+ outValue = SvcLogicConstants.SUCCESS;
+ break;
+ case ALREADY_ACTIVE:
+ outValue = ALREADY_ACTIVE;
+ break;
+ case NOT_FOUND:
+ outValue = NOT_FOUND;
+ break;
+ case NOT_READY:
+ outValue = "not-ready";
+ break;
+ case FAILURE:
+ default:
+ outValue = SvcLogicConstants.FAILURE;
+ }
+ }
+ } else {
+ LOG.warn("Nothing to configure - no parameters passed, and activate attribute is not set");
+ outValue = SvcLogicConstants.SUCCESS;
+ }
+ }
+ } else {
+ if (LOG.isWarnEnabled()) {
+ LOG.warn("Adaptor for " + adaptorName + " not found");
+ }
+ }
+
+ SvcLogicNode nextNode = node.getOutcomeValue(outValue);
+ if (nextNode != null) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("about to execute " + outValue + " branch");
+ }
+ return (nextNode);
+ }
+
+ nextNode = node.getOutcomeValue("Other");
+ if (nextNode != null) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("about to execute Other branch");
+ }
+ } else {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("no " + outValue + " or Other branch found");
+ }
+ }
+ return (nextNode);
+ }
+
+}
diff --git a/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/DeleteNodeExecutor.java b/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/DeleteNodeExecutor.java
new file mode 100644
index 000000000..00f0629cb
--- /dev/null
+++ b/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/DeleteNodeExecutor.java
@@ -0,0 +1,75 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.sli.provider.base;
+
+import org.onap.ccsdk.sli.core.sli.SvcLogicConstants;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.core.sli.SvcLogicNode;
+import org.onap.ccsdk.sli.core.sli.SvcLogicResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class DeleteNodeExecutor extends AbstractSvcLogicNodeExecutor {
+
+ private static final Logger LOG = LoggerFactory.getLogger(DeleteNodeExecutor.class);
+ private static final String FAILURE=SvcLogicConstants.FAILURE;
+
+ @Override
+ public SvcLogicNode execute(SvcLogicServiceBase svc, SvcLogicNode node, SvcLogicContext ctx)
+ throws SvcLogicException {
+
+ String plugin = SvcLogicExpressionResolver.evaluate(node.getAttribute("plugin"), node, ctx);
+ String resourceType = SvcLogicExpressionResolver.evaluate(node.getAttribute("resource"), node, ctx);
+ String key = SvcLogicExpressionResolver.evaluateAsKey(node.getAttribute("key"), node, ctx);
+
+ String outValue = FAILURE;
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("delete node encountered - looking for resource class " + plugin);
+ }
+
+ SvcLogicResource resourcePlugin = getSvcLogicResource(plugin);
+ if (resourcePlugin != null) {
+ try {
+ switch (resourcePlugin.delete(resourceType, key, ctx)) {
+ case SUCCESS:
+ outValue = SvcLogicConstants.SUCCESS;
+ break;
+ case NOT_FOUND:
+ outValue = "not-found";
+ break;
+ case FAILURE:
+ default:
+ outValue = FAILURE;
+ }
+ } catch (SvcLogicException e) {
+ LOG.error("Caught exception from resource plugin", e);
+ outValue = FAILURE;
+ }
+ } else {
+ LOG.warn("Could not find SvcLogicResource object for plugin " + plugin);
+ }
+ return (getNextNode(node, outValue));
+ }
+
+}
diff --git a/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/ExecuteNodeExecutor.java b/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/ExecuteNodeExecutor.java
new file mode 100644
index 000000000..b23662a6c
--- /dev/null
+++ b/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/ExecuteNodeExecutor.java
@@ -0,0 +1,127 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Modifications Copyright (C) 2018 IBM.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.sli.provider.base;
+
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Map;
+import org.onap.ccsdk.sli.core.sli.SvcLogicConstants;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.core.sli.SvcLogicExpression;
+import org.onap.ccsdk.sli.core.sli.SvcLogicJavaPlugin;
+import org.onap.ccsdk.sli.core.sli.SvcLogicNode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ExecuteNodeExecutor extends AbstractSvcLogicNodeExecutor {
+ private static final Logger LOG = LoggerFactory
+ .getLogger(ExecuteNodeExecutor.class);
+ private static final String FAILURE=SvcLogicConstants.FAILURE;
+
+ private static final String pluginErrorMessage = "Could not execute plugin. SvcLogic status will be set to failure.";
+ public SvcLogicNode execute(SvcLogicServiceBase svc, SvcLogicNode node,
+ SvcLogicContext ctx) throws SvcLogicException {
+
+ String pluginName = SvcLogicExpressionResolver.evaluate(
+ node.getAttribute("plugin"), node, ctx);
+ String outValue = FAILURE;
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("execute node encountered - looking for plugin "
+ + pluginName);
+ }
+
+ SvcLogicJavaPlugin plugin = getSvcLogicJavaPlugin(pluginName);
+
+ if (plugin == null) {
+ outValue = "not-found";
+ } else {
+
+ String methodName = evaluate(node.getAttribute("method"), node, ctx);
+
+ Class pluginClass = plugin.getClass();
+
+ Method pluginMethod = null;
+
+ try {
+ LOG.debug("executing method {} on plugin {}", methodName, pluginName);
+ pluginMethod = pluginClass.getMethod(methodName, Map.class, SvcLogicContext.class);
+ } catch (NoSuchMethodException e) {
+ LOG.error(pluginErrorMessage, e);
+ }
+
+ if (pluginMethod == null) {
+ outValue = "unsupported-method";
+ } else {
+ try {
+
+
+ Map<String, String> parmMap = getResolvedParameters(node,ctx);
+ Object o = pluginMethod.invoke(plugin, parmMap, ctx);
+ String emitsOutcome = SvcLogicExpressionResolver.evaluate(node.getAttribute("emitsOutcome"), node, ctx);
+
+ outValue = mapOutcome(o, emitsOutcome);
+
+ } catch (InvocationTargetException e) {
+ if(e.getCause() != null){
+ LOG.error(pluginErrorMessage, e.getCause());
+ }else{
+ LOG.error(pluginErrorMessage, e);
+ }
+ outValue = FAILURE;
+ ctx.markFailed();
+ } catch (IllegalAccessException e) {
+ LOG.error(pluginErrorMessage, e);
+ outValue = FAILURE;
+ ctx.markFailed();
+ } catch (IllegalArgumentException e) {
+ LOG.error(pluginErrorMessage, e);
+ outValue = FAILURE;
+ ctx.markFailed();
+ }
+ }
+
+ }
+ return (getNextNode(node, outValue));
+ }
+
+ protected String evaluate(SvcLogicExpression expr, SvcLogicNode node, SvcLogicContext ctx) throws SvcLogicException {
+ return SvcLogicExpressionResolver.evaluate(node.getAttribute("method"), node, ctx);
+ }
+
+ public String mapOutcome(Object o, String emitsOutcome) {
+ if (emitsOutcome != null) {
+ Boolean nodeEmitsOutcome = Boolean.valueOf(emitsOutcome);
+ if (nodeEmitsOutcome) {
+ return (String) o;
+ } else {
+ return SvcLogicConstants.SUCCESS;
+ }
+ } else {
+ return SvcLogicConstants.SUCCESS;
+ }
+ }
+
+}
diff --git a/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/ExistsNodeExecutor.java b/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/ExistsNodeExecutor.java
new file mode 100644
index 000000000..ca12e35d8
--- /dev/null
+++ b/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/ExistsNodeExecutor.java
@@ -0,0 +1,76 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.sli.provider.base;
+
+import org.onap.ccsdk.sli.core.sli.SvcLogicConstants;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.core.sli.SvcLogicNode;
+import org.onap.ccsdk.sli.core.sli.SvcLogicResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ExistsNodeExecutor extends AbstractSvcLogicNodeExecutor {
+
+ private static final Logger LOG = LoggerFactory.getLogger(ExistsNodeExecutor.class);
+
+ @Override
+ public SvcLogicNode execute(SvcLogicServiceBase svc, SvcLogicNode node, SvcLogicContext ctx)
+ throws SvcLogicException {
+
+ String plugin = SvcLogicExpressionResolver.evaluate(node.getAttribute("plugin"), node, ctx);
+ String resourceType = SvcLogicExpressionResolver.evaluate(node.getAttribute("resource"), node, ctx);
+ String key = SvcLogicExpressionResolver.evaluateAsKey(node.getAttribute("key"), node, ctx);
+ String pfx = SvcLogicExpressionResolver.evaluate(node.getAttribute("pfx"), node, ctx);
+
+ String outValue = SvcLogicConstants.FAILURE;
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("exists node encountered - looking for resource class " + plugin);
+ }
+
+ SvcLogicResource resourcePlugin = getSvcLogicResource(plugin);
+
+ if (resourcePlugin != null) {
+ try {
+ switch (resourcePlugin.exists(resourceType, key, pfx, ctx)) {
+ case SUCCESS:
+ outValue = "true";
+ break;
+ case NOT_FOUND:
+ outValue = "false";
+ break;
+ case FAILURE:
+ default:
+ outValue = "false";
+ }
+ } catch (SvcLogicException e) {
+ LOG.error("Caught exception from resource plugin", e);
+ outValue = SvcLogicConstants.FAILURE;
+ }
+ } else {
+ LOG.warn("Could not find SvcLogicResource object for plugin " + plugin);
+ }
+ return (getNextNode(node, outValue));
+ }
+
+}
diff --git a/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/ExitNodeExecutor.java b/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/ExitNodeExecutor.java
new file mode 100644
index 000000000..828e10152
--- /dev/null
+++ b/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/ExitNodeExecutor.java
@@ -0,0 +1,42 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.sli.provider.base;
+
+import org.onap.ccsdk.sli.core.sli.ExitNodeException;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.core.sli.SvcLogicNode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ExitNodeExecutor extends AbstractSvcLogicNodeExecutor {
+
+ private static final Logger LOG = LoggerFactory.getLogger(ExitNodeExecutor.class);
+
+ @Override
+ public SvcLogicNode execute(SvcLogicServiceBase svc, SvcLogicNode node, SvcLogicContext ctx) throws SvcLogicException {
+ String message = "ExitNodeExecutor encountered exit with nodeId " + node.getNodeId();
+ LOG.debug(message);
+ throw new ExitNodeException(message);
+ }
+
+}
diff --git a/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/ForNodeExecutor.java b/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/ForNodeExecutor.java
new file mode 100644
index 000000000..2d9721c7f
--- /dev/null
+++ b/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/ForNodeExecutor.java
@@ -0,0 +1,110 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.sli.provider.base;
+
+import org.onap.ccsdk.sli.core.sli.BreakNodeException;
+import org.onap.ccsdk.sli.core.sli.SvcLogicConstants;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.core.sli.SvcLogicExpression;
+import org.onap.ccsdk.sli.core.sli.SvcLogicNode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ForNodeExecutor extends AbstractSvcLogicNodeExecutor {
+
+ private static final Logger LOG = LoggerFactory
+ .getLogger(ForNodeExecutor.class);
+
+ @Override
+ public SvcLogicNode execute(SvcLogicServiceBase svc, SvcLogicNode node,
+ SvcLogicContext ctx) throws SvcLogicException {
+
+ SvcLogicExpression atomicExpr = node.getAttribute("atomic");
+ String atomicStr = SvcLogicExpressionResolver.evaluate(atomicExpr, node, ctx);
+ boolean isAtomic = !("false".equalsIgnoreCase(atomicStr));
+
+ int numOutcomes = node.getNumOutcomes();
+ String idxVar = SvcLogicExpressionResolver.evaluate(
+ node.getAttribute("index"), node, ctx);
+ String startVal = SvcLogicExpressionResolver.evaluate(
+ node.getAttribute("start"), node, ctx);
+ String endVal = SvcLogicExpressionResolver.evaluate(
+ node.getAttribute("end"), node, ctx);
+
+ LOG.debug("Executing "+ (isAtomic ? "atomic" : "non-atomic") + " for loop - for (int " + idxVar + " = " + startVal
+ + "; " + idxVar + " < " + endVal + "; " + idxVar + "++)");
+
+ int startIdx = 0;
+ int endIdx = 0;
+
+ try {
+ startIdx = Integer.parseInt(startVal);
+ endIdx = Integer.parseInt(endVal);
+ } catch (NumberFormatException e) {
+ SvcLogicExpression silentFailureExpr = node.getAttribute("silentFailure");
+ String silentFailure = SvcLogicExpressionResolver.evaluate(silentFailureExpr, node, ctx);
+ boolean isSilentFailure = Boolean.parseBoolean(silentFailure);
+ String message = "Invalid index values [" + startVal + "," + endVal + "]";
+ if(!isSilentFailure){
+ throw new SvcLogicException(message);
+ }else{
+ LOG.debug(message + ". Not exiting because silentFailure was set to true.");
+ return(null);
+ }
+ }
+
+ try {
+ for (int ctr = startIdx; ctr < endIdx; ctr++) {
+
+ ctx.setAttribute(idxVar, "" + ctr);
+
+ for (int i = 0; i < numOutcomes; i++) {
+
+ if (SvcLogicConstants.FAILURE.equals(ctx.getStatus()) && isAtomic) {
+ LOG.info("For - stopped executing nodes due to failure status");
+ return(null);
+ }
+
+ SvcLogicNode nextNode = node.getOutcomeValue("" + (i + 1));
+ if (nextNode != null) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("For - executing outcome " + (i + 1));
+ }
+ SvcLogicNode innerNextNode = nextNode;
+ while (innerNextNode != null) {
+ innerNextNode = svc.executeNode(innerNextNode, ctx);
+ }
+ } else {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("For - done: no outcome " + (i + 1));
+ }
+ }
+ }
+ }
+ } catch (BreakNodeException br) {
+ LOG.trace("ForNodeExecutor caught break" + br.getMessage());
+ }
+ return (null);
+ }
+
+}
diff --git a/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/GetResourceNodeExecutor.java b/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/GetResourceNodeExecutor.java
new file mode 100644
index 000000000..f7cfc66d2
--- /dev/null
+++ b/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/GetResourceNodeExecutor.java
@@ -0,0 +1,100 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.sli.provider.base;
+
+import org.onap.ccsdk.sli.core.sli.SvcLogicConstants;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.core.sli.SvcLogicExpression;
+import org.onap.ccsdk.sli.core.sli.SvcLogicNode;
+import org.onap.ccsdk.sli.core.sli.SvcLogicResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class GetResourceNodeExecutor extends AbstractSvcLogicNodeExecutor {
+
+ private static final Logger LOG = LoggerFactory.getLogger(GetResourceNodeExecutor.class);
+
+ public SvcLogicNode execute(SvcLogicServiceBase svc, SvcLogicNode node, SvcLogicContext ctx)
+ throws SvcLogicException {
+
+ String plugin = SvcLogicExpressionResolver.evaluate(node.getAttribute("plugin"), node, ctx);
+ String resourceType = SvcLogicExpressionResolver.evaluate(node.getAttribute("resource"), node, ctx);
+ String key = SvcLogicExpressionResolver.evaluateAsKey(node.getAttribute("key"), node, ctx);
+ String pfx = SvcLogicExpressionResolver.evaluate(node.getAttribute("pfx"), node, ctx);
+
+ String localOnlyStr = SvcLogicExpressionResolver.evaluate(node.getAttribute("local-only"), node, ctx);
+
+ // Note: for get-resource, only refresh from A&AI if the DG explicitly set
+ // local-only to false. Otherwise, just read from local database.
+ boolean localOnly = true;
+
+ if ("false".equalsIgnoreCase(localOnlyStr)) {
+ localOnly = false;
+ }
+
+ SvcLogicExpression selectExpr = node.getAttribute("select");
+ String select = null;
+
+ if (selectExpr != null) {
+ select = SvcLogicExpressionResolver.evaluateAsKey(selectExpr, node, ctx);
+ }
+
+ SvcLogicExpression orderByExpr = node.getAttribute("order-by");
+ String orderBy = null;
+
+ if (orderByExpr != null) {
+ orderBy = SvcLogicExpressionResolver.evaluateAsKey(orderByExpr, node, ctx);
+ }
+
+ String outValue = SvcLogicConstants.FAILURE;
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug(node.getNodeType() + " node encountered - looking for resource class " + plugin);
+ }
+
+ SvcLogicResource resourcePlugin = getSvcLogicResource(plugin);
+
+ if (resourcePlugin != null) {
+ try {
+ switch (resourcePlugin.query(resourceType, localOnly, select, key, pfx, orderBy, ctx)) {
+ case SUCCESS:
+ outValue = SvcLogicConstants.SUCCESS;
+ break;
+ case NOT_FOUND:
+ outValue = "not-found";
+ break;
+ case FAILURE:
+ default:
+ outValue = SvcLogicConstants.FAILURE;
+ }
+ } catch (SvcLogicException e) {
+ LOG.error("Caught exception from resource plugin", e);
+ outValue = SvcLogicConstants.FAILURE;
+ }
+ } else {
+ LOG.warn("Could not find SvcLogicResource object for plugin " + plugin);
+ }
+ return (getNextNode(node, outValue));
+ }
+
+}
diff --git a/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/HashMapResolver.java b/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/HashMapResolver.java
new file mode 100644
index 000000000..d33312784
--- /dev/null
+++ b/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/HashMapResolver.java
@@ -0,0 +1,52 @@
+package org.onap.ccsdk.sli.core.sli.provider.base;
+
+import java.util.HashMap;
+import java.util.Map;
+import org.onap.ccsdk.sli.core.sli.SvcLogicAdaptor;
+import org.onap.ccsdk.sli.core.sli.SvcLogicJavaPlugin;
+import org.onap.ccsdk.sli.core.sli.SvcLogicRecorder;
+import org.onap.ccsdk.sli.core.sli.SvcLogicResource;
+
+public class HashMapResolver implements SvcLogicResolver {
+ Map<String, SvcLogicResource> svcLogicResourceMap = new HashMap<String, SvcLogicResource>();
+ Map<String, SvcLogicJavaPlugin> svcLogicJavaPluginMap = new HashMap<String, SvcLogicJavaPlugin>();
+ Map<String, SvcLogicAdaptor> adaptorMap = new HashMap<String, SvcLogicAdaptor>();
+ Map<String, SvcLogicRecorder> recorderMap = new HashMap<String, SvcLogicRecorder>();
+
+ @Override
+ public SvcLogicResource getSvcLogicResource(String resourceName) {
+ return svcLogicResourceMap.get(resourceName);
+ }
+
+ @Override
+ public SvcLogicRecorder getSvcLogicRecorder(String recorderName) {
+ return recorderMap.get(recorderName);
+ }
+
+ @Override
+ public SvcLogicJavaPlugin getSvcLogicJavaPlugin(String pluginName) {
+ return svcLogicJavaPluginMap.get(pluginName);
+ }
+
+ @Override
+ public SvcLogicAdaptor getSvcLogicAdaptor(String adaptorName) {
+ return adaptorMap.get(adaptorName);
+ }
+
+ public void addSvcLogicAdaptor(String adaptorName, SvcLogicAdaptor adaptor) {
+ adaptorMap.put(adaptorName, adaptor);
+ }
+
+ public void addSvcLogicRecorder(String recorderName, SvcLogicRecorder recorder) {
+ recorderMap.put(recorderName, recorder);
+ }
+
+ public void addSvcLogicSvcLogicJavaPlugin(String pluginName, SvcLogicJavaPlugin plugin) {
+ svcLogicJavaPluginMap.put(pluginName, plugin);
+ }
+
+ public void addSvcLogicResource(String resourceName, SvcLogicResource resource) {
+ svcLogicResourceMap.put(resourceName, resource);
+ }
+
+}
diff --git a/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/InMemorySvcLogicStore.java b/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/InMemorySvcLogicStore.java
new file mode 100644
index 000000000..ddf464fe7
--- /dev/null
+++ b/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/InMemorySvcLogicStore.java
@@ -0,0 +1,66 @@
+package org.onap.ccsdk.sli.core.sli.provider.base;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.core.sli.SvcLogicGraph;
+import org.onap.ccsdk.sli.core.sli.SvcLogicStore;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class InMemorySvcLogicStore implements SvcLogicStore {
+ private static final Logger logger = LoggerFactory.getLogger(InMemorySvcLogicStore.class);
+ public Map<String, SvcLogicGraph> graphStore;
+
+ public InMemorySvcLogicStore() {
+ graphStore = new HashMap<String, SvcLogicGraph>();
+ }
+
+ @Override
+ public boolean hasGraph(String module, String rpc, String version, String mode) throws SvcLogicException {
+ String storeId = new String(module + ":" + rpc);
+ return graphStore.containsKey(storeId);
+ }
+
+ @Override
+ public SvcLogicGraph fetch(String module, String rpc, String version, String mode) throws SvcLogicException {
+ String storeId = new String(module + ":" + rpc);
+ return graphStore.get(storeId);
+ }
+
+ @Override
+ public void store(SvcLogicGraph graph) throws SvcLogicException {
+ if (graph != null) {
+ String storeId = new String(graph.getModule() + ":" + graph.getRpc());
+ graphStore.put(storeId, graph);
+ logger.info(graph.toString() + " stored in InMemorySvcLogicStore.");
+ }
+ }
+
+ @Override
+ public void init(Properties props) throws SvcLogicException {
+ // noop
+ }
+
+ @Override
+ public void delete(String module, String rpc, String version, String mode) throws SvcLogicException {
+ String storeId = new String(module + ":" + rpc);
+ if (graphStore.containsKey(storeId)) {
+ graphStore.remove(storeId);
+ }
+ }
+
+ @Override
+ public void activate(SvcLogicGraph graph) throws SvcLogicException {
+ // noop
+ }
+
+ @Override
+ public void activate(String module, String rpc, String version, String mode) throws SvcLogicException {
+ // noop
+ }
+
+}
diff --git a/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/IsAvailableNodeExecutor.java b/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/IsAvailableNodeExecutor.java
new file mode 100644
index 000000000..1d6e34e85
--- /dev/null
+++ b/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/IsAvailableNodeExecutor.java
@@ -0,0 +1,72 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.sli.provider.base;
+
+import org.onap.ccsdk.sli.core.sli.SvcLogicConstants;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.core.sli.SvcLogicNode;
+import org.onap.ccsdk.sli.core.sli.SvcLogicResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class IsAvailableNodeExecutor extends AbstractSvcLogicNodeExecutor {
+
+ private static final Logger LOG = LoggerFactory.getLogger(IsAvailableNodeExecutor.class);
+
+ @Override
+ public SvcLogicNode execute(SvcLogicServiceBase svc, SvcLogicNode node, SvcLogicContext ctx)
+ throws SvcLogicException {
+
+ String plugin = SvcLogicExpressionResolver.evaluate(node.getAttribute("plugin"), node, ctx);
+ String resourceType = SvcLogicExpressionResolver.evaluate(node.getAttribute("resource"), node, ctx);
+ String key = SvcLogicExpressionResolver.evaluateAsKey(node.getAttribute("key"), node, ctx);
+ String pfx = SvcLogicExpressionResolver.evaluate(node.getAttribute("pfx"), node, ctx);
+
+ String outValue = SvcLogicConstants.FAILURE;
+
+ SvcLogicResource resourcePlugin = getSvcLogicResource(plugin);
+
+ if (resourcePlugin != null) {
+ try {
+ switch (resourcePlugin.isAvailable(resourceType, key, pfx, ctx)) {
+ case SUCCESS:
+ outValue = "true";
+ break;
+ case NOT_FOUND:
+ outValue = "false";
+ break;
+ case FAILURE:
+ default:
+ outValue = "false";
+ }
+ } catch (SvcLogicException e) {
+ LOG.error("Caught exception from resource plugin", e);
+ outValue = SvcLogicConstants.FAILURE;
+ }
+ } else {
+ LOG.warn("Could not find SvcLogicResource object for plugin " + plugin);
+ }
+ return (getNextNode(node, outValue));
+ }
+
+}
diff --git a/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/NotifyNodeExecutor.java b/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/NotifyNodeExecutor.java
new file mode 100644
index 000000000..fb560db5f
--- /dev/null
+++ b/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/NotifyNodeExecutor.java
@@ -0,0 +1,75 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.sli.provider.base;
+
+import org.onap.ccsdk.sli.core.sli.SvcLogicConstants;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.core.sli.SvcLogicNode;
+import org.onap.ccsdk.sli.core.sli.SvcLogicResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class NotifyNodeExecutor extends AbstractSvcLogicNodeExecutor {
+
+ private static final Logger LOG = LoggerFactory.getLogger(NotifyNodeExecutor.class);
+
+ @Override
+ public SvcLogicNode execute(SvcLogicServiceBase svc, SvcLogicNode node, SvcLogicContext ctx)
+ throws SvcLogicException {
+
+ String plugin = SvcLogicExpressionResolver.evaluate(node.getAttribute("plugin"), node, ctx);
+ String resourceType = SvcLogicExpressionResolver.evaluate(node.getAttribute("resource"), node, ctx);
+ String action = SvcLogicExpressionResolver.evaluateAsKey(node.getAttribute("action"), node, ctx);
+ String key = SvcLogicExpressionResolver.evaluateAsKey(node.getAttribute("key"), node, ctx);
+
+ String outValue = SvcLogicConstants.FAILURE;
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("release node encountered - looking for resource class " + plugin);
+ }
+
+ SvcLogicResource resourcePlugin = getSvcLogicResource(plugin);
+ if (resourcePlugin != null) {
+ try {
+ switch (resourcePlugin.notify(resourceType, action, key, ctx)) {
+ case SUCCESS:
+ outValue = SvcLogicConstants.SUCCESS;
+ break;
+ case NOT_FOUND:
+ outValue = "not-found";
+ break;
+ case FAILURE:
+ default:
+ outValue = SvcLogicConstants.FAILURE;
+ }
+ } catch (SvcLogicException e) {
+ LOG.error("Caught exception from resource plugin", e);
+ outValue = SvcLogicConstants.FAILURE;
+ }
+ } else {
+ LOG.warn("Could not find SvcLogicResource object for plugin " + plugin);
+ }
+ return (getNextNode(node, outValue));
+ }
+
+}
diff --git a/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/RecordNodeExecutor.java b/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/RecordNodeExecutor.java
new file mode 100644
index 000000000..2dd5a081e
--- /dev/null
+++ b/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/RecordNodeExecutor.java
@@ -0,0 +1,65 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Modifications Copyright (C) 2018 IBM.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.sli.provider.base;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import org.onap.ccsdk.sli.core.sli.SvcLogicConstants;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.core.sli.SvcLogicExpression;
+import org.onap.ccsdk.sli.core.sli.SvcLogicNode;
+import org.onap.ccsdk.sli.core.sli.SvcLogicRecorder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class RecordNodeExecutor extends AbstractSvcLogicNodeExecutor {
+
+ private static final Logger LOG = LoggerFactory.getLogger(RecordNodeExecutor.class);
+
+ @Override
+ public SvcLogicNode execute(SvcLogicServiceBase svc, SvcLogicNode node, SvcLogicContext ctx)
+ throws SvcLogicException {
+
+ String plugin = SvcLogicExpressionResolver.evaluate(node.getAttribute("plugin"), node, ctx);
+ String outValue = SvcLogicConstants.FAILURE;
+
+ Map<String, String> parmMap = getResolvedParameters(node,ctx);
+
+ SvcLogicRecorder recorder = getSvcLogicRecorder(plugin);
+ if (recorder != null) {
+ try {
+ recorder.record(parmMap);
+ } catch (SvcLogicException e) {
+ LOG.error("Caught exception from recorder plugin", e);
+ outValue = SvcLogicConstants.FAILURE;
+ }
+ } else {
+ LOG.warn("Could not find SvcLogicRecorder object for plugin " + plugin);
+ }
+ return (getNextNode(node, outValue));
+ }
+}
diff --git a/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/ReleaseNodeExecutor.java b/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/ReleaseNodeExecutor.java
new file mode 100644
index 000000000..ee06031d6
--- /dev/null
+++ b/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/ReleaseNodeExecutor.java
@@ -0,0 +1,74 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.sli.provider.base;
+
+import org.onap.ccsdk.sli.core.sli.SvcLogicConstants;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.core.sli.SvcLogicNode;
+import org.onap.ccsdk.sli.core.sli.SvcLogicResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ReleaseNodeExecutor extends AbstractSvcLogicNodeExecutor {
+
+ private static final Logger LOG = LoggerFactory.getLogger(ReleaseNodeExecutor.class);
+
+ @Override
+ public SvcLogicNode execute(SvcLogicServiceBase svc, SvcLogicNode node, SvcLogicContext ctx)
+ throws SvcLogicException {
+
+ String plugin = SvcLogicExpressionResolver.evaluate(node.getAttribute("plugin"), node, ctx);
+ String resourceType = SvcLogicExpressionResolver.evaluate(node.getAttribute("resource"), node, ctx);
+ String key = SvcLogicExpressionResolver.evaluateAsKey(node.getAttribute("key"), node, ctx);
+
+ String outValue = SvcLogicConstants.FAILURE;
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("release node encountered - looking for resource class " + plugin);
+ }
+
+ SvcLogicResource resourcePlugin = getSvcLogicResource(plugin);
+ if (resourcePlugin != null) {
+ try {
+ switch (resourcePlugin.release(resourceType, key, ctx)) {
+ case SUCCESS:
+ outValue = SvcLogicConstants.SUCCESS;
+ break;
+ case NOT_FOUND:
+ outValue = "not-found";
+ break;
+ case FAILURE:
+ default:
+ outValue = SvcLogicConstants.FAILURE;
+ }
+ } catch (SvcLogicException e) {
+ LOG.error("Caught exception from resource plugin", e);
+ outValue = SvcLogicConstants.FAILURE;
+ }
+ } else {
+ LOG.warn("Could not find SvcLogicResource object for plugin " + plugin);
+ }
+ return (getNextNode(node, outValue));
+ }
+
+}
diff --git a/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/ReserveNodeExecutor.java b/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/ReserveNodeExecutor.java
new file mode 100644
index 000000000..d22d36ebb
--- /dev/null
+++ b/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/ReserveNodeExecutor.java
@@ -0,0 +1,88 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.sli.provider.base;
+
+import org.onap.ccsdk.sli.core.sli.SvcLogicConstants;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.core.sli.SvcLogicExpression;
+import org.onap.ccsdk.sli.core.sli.SvcLogicNode;
+import org.onap.ccsdk.sli.core.sli.SvcLogicResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ReserveNodeExecutor extends AbstractSvcLogicNodeExecutor {
+
+ private static final Logger LOG = LoggerFactory.getLogger(ReserveNodeExecutor.class);
+
+ @Override
+ public SvcLogicNode execute(SvcLogicServiceBase svc, SvcLogicNode node, SvcLogicContext ctx)
+ throws SvcLogicException {
+
+ String plugin = SvcLogicExpressionResolver.evaluate(node.getAttribute("plugin"), node, ctx);
+ String resourceType = SvcLogicExpressionResolver.evaluate(node.getAttribute("resource"), node, ctx);
+ String key = SvcLogicExpressionResolver.evaluateAsKey(node.getAttribute("key"), node, ctx);
+ String pfx = SvcLogicExpressionResolver.evaluate(node.getAttribute("pfx"), node, ctx);
+
+
+ SvcLogicExpression selectExpr = node.getAttribute("select");
+ String select = null;
+
+ if (selectExpr != null) {
+ select = SvcLogicExpressionResolver.evaluateAsKey(selectExpr, node, ctx);
+ }
+
+ String outValue = SvcLogicConstants.FAILURE;
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("reserve node encountered - looking for resource class " + plugin);
+ }
+
+
+
+ SvcLogicResource resourcePlugin = getSvcLogicResource(plugin);
+
+ if (resourcePlugin != null) {
+
+ try {
+ switch (resourcePlugin.reserve(resourceType, select, key, pfx, ctx)) {
+ case SUCCESS:
+ outValue = SvcLogicConstants.SUCCESS;
+ break;
+ case NOT_FOUND:
+ outValue = "not-found";
+ break;
+ case FAILURE:
+ default:
+ outValue = SvcLogicConstants.FAILURE;
+ }
+ } catch (SvcLogicException e) {
+ LOG.error("Caught exception from resource plugin", e);
+ outValue = SvcLogicConstants.FAILURE;
+ }
+ } else {
+ LOG.warn("Could not find SvcLogicResource object for plugin " + plugin);
+ }
+ return (getNextNode(node, outValue));
+ }
+
+}
diff --git a/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/ReturnNodeExecutor.java b/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/ReturnNodeExecutor.java
new file mode 100644
index 000000000..8ee465774
--- /dev/null
+++ b/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/ReturnNodeExecutor.java
@@ -0,0 +1,77 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.sli.provider.base;
+
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.core.sli.SvcLogicExpression;
+import org.onap.ccsdk.sli.core.sli.SvcLogicNode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ReturnNodeExecutor extends AbstractSvcLogicNodeExecutor {
+
+ private static final Logger LOG = LoggerFactory
+ .getLogger(ReturnNodeExecutor.class);
+
+ @Override
+ public SvcLogicNode execute(SvcLogicServiceBase svc, SvcLogicNode node,
+ SvcLogicContext ctx) throws SvcLogicException {
+
+ String status = SvcLogicExpressionResolver.evaluate(
+ node.getAttribute("status"), node, ctx);
+
+ if (status != null) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Returning status " + status);
+ }
+ ctx.setStatus(status);
+ } else {
+ if (LOG.isWarnEnabled()) {
+ LOG.warn("Return node has no status attribute set");
+ }
+ }
+
+ Set<Map.Entry<String, SvcLogicExpression>> parameterSet = node
+ .getParameterSet();
+
+ for (Iterator<Map.Entry<String, SvcLogicExpression>> iter = parameterSet
+ .iterator(); iter.hasNext();) {
+ Map.Entry<String, SvcLogicExpression> curEnt = iter.next();
+ String curName = curEnt.getKey();
+ String curValue = SvcLogicExpressionResolver.evaluate(
+ curEnt.getValue(), node, ctx);
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug(SETTING_DEBUG_PATTERN, curName, curValue, curEnt.getValue());
+ }
+ ctx.setAttribute(curName, curValue);
+ }
+ return null;
+ }
+
+
+}
diff --git a/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/SaveNodeExecutor.java b/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/SaveNodeExecutor.java
new file mode 100644
index 000000000..b0b70f1f2
--- /dev/null
+++ b/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/SaveNodeExecutor.java
@@ -0,0 +1,94 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Modifications Copyright (C) 2018 IBM.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.sli.provider.base;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import org.onap.ccsdk.sli.core.sli.SvcLogicConstants;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.core.sli.SvcLogicExpression;
+import org.onap.ccsdk.sli.core.sli.SvcLogicNode;
+import org.onap.ccsdk.sli.core.sli.SvcLogicResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class SaveNodeExecutor extends AbstractSvcLogicNodeExecutor {
+
+ private static final Logger LOG = LoggerFactory.getLogger(SaveNodeExecutor.class);
+ private static final String FAILURE= SvcLogicConstants.FAILURE;
+
+ @Override
+ public SvcLogicNode execute(SvcLogicServiceBase svc, SvcLogicNode node, SvcLogicContext ctx)
+ throws SvcLogicException {
+
+ String plugin = SvcLogicExpressionResolver.evaluate(node.getAttribute("plugin"), node, ctx);
+ String resourceType = SvcLogicExpressionResolver.evaluate(node.getAttribute("resource"), node, ctx);
+ String key = SvcLogicExpressionResolver.evaluateAsKey(node.getAttribute("key"), node, ctx);
+ String forceStr = SvcLogicExpressionResolver.evaluate(node.getAttribute("force"), node, ctx);
+ String localOnlyStr = SvcLogicExpressionResolver.evaluate(node.getAttribute("local-only"), node, ctx);
+ String pfx = SvcLogicExpressionResolver.evaluate(node.getAttribute("pfx"), node, ctx);
+
+ boolean force = "true".equalsIgnoreCase(forceStr);
+ boolean localOnly = "true".equalsIgnoreCase(localOnlyStr);
+
+ Map<String, String> parmMap = getResolvedParameters(node,ctx);
+
+ String outValue = FAILURE;
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("save node encountered - looking for resource class " + plugin);
+ }
+
+
+
+ SvcLogicResource resourcePlugin = getSvcLogicResource(plugin);
+
+ if (resourcePlugin != null) {
+
+ try {
+ switch (resourcePlugin.save(resourceType, force, localOnly, key, parmMap, pfx, ctx)) {
+ case SUCCESS:
+ outValue = SvcLogicConstants.SUCCESS;
+ break;
+ case NOT_FOUND:
+ outValue = "not-found";
+ break;
+ case FAILURE:
+ default:
+ outValue = FAILURE;
+ }
+ } catch (SvcLogicException e) {
+ LOG.error("Caught exception from resource plugin", e);
+ outValue = FAILURE;
+ }
+ } else {
+ LOG.warn("Could not find SvcLogicResource object for plugin " + plugin);
+ }
+ return (getNextNode(node, outValue));
+ }
+
+}
diff --git a/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/SetNodeExecutor.java b/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/SetNodeExecutor.java
new file mode 100644
index 000000000..7e07d29bf
--- /dev/null
+++ b/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/SetNodeExecutor.java
@@ -0,0 +1,179 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Modifications Copyright (C) 2018 IBM.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.sli.provider.base;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.Set;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.core.sli.SvcLogicExpression;
+import org.onap.ccsdk.sli.core.sli.SvcLogicExpressionFactory;
+import org.onap.ccsdk.sli.core.sli.SvcLogicNode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class SetNodeExecutor extends AbstractSvcLogicNodeExecutor {
+
+ private static final Logger LOG = LoggerFactory.getLogger(SetNodeExecutor.class);
+ protected final String arrayPattern = "\\[\\d*\\]";
+
+ @Override
+ public SvcLogicNode execute(SvcLogicServiceBase svc, SvcLogicNode node, SvcLogicContext ctx)
+ throws SvcLogicException {
+ execute(node,ctx);
+ return null;
+ }
+
+ public void execute(SvcLogicNode node, SvcLogicContext ctx) throws SvcLogicException {
+ String ifunsetStr = SvcLogicExpressionResolver.evaluate(node.getAttribute("only-if-unset"), node, ctx);
+
+ boolean ifunset = "true".equalsIgnoreCase(ifunsetStr);
+
+ Set<Map.Entry<String, SvcLogicExpression>> parameterSet = node.getParameterSet();
+
+ for (Iterator<Map.Entry<String, SvcLogicExpression>> iter = parameterSet.iterator(); iter.hasNext();) {
+ Map.Entry<String, SvcLogicExpression> curEnt = iter.next();
+ String curName = curEnt.getKey();
+ String lhsVarName = curName;
+
+ // Resolve LHS of assignment (could contain index variables)
+ try {
+ // Backticks symbolize the variable should be handled as an expression instead of as a variable
+ if (curName.trim().startsWith("`")) {
+ int lastParen = curName.lastIndexOf("`");
+ String evalExpr = curName.trim().substring(1, lastParen);
+ SvcLogicExpression lhsExpr = SvcLogicExpressionFactory.parse(evalExpr);
+ lhsVarName = SvcLogicExpressionResolver.evaluate(lhsExpr, node, ctx);
+ } else {
+ SvcLogicExpression lhsExpr = SvcLogicExpressionFactory.parse(curName);
+ lhsVarName = SvcLogicExpressionResolver.resolveVariableName(lhsExpr, node, ctx);
+ }
+ } catch (Exception e) {
+ LOG.warn("Caught exception trying to resolve variable name (" + curName + ")", e);
+ }
+
+ boolean setValue = true;
+
+ if (curName.endsWith(".")) {
+ // Copy subtree - value should be a variable name
+ SvcLogicExpression curValue = curEnt.getValue();
+
+ if (curValue != null) {
+ String rhsRoot = curValue.toString();
+
+ if ((rhsRoot != null) && (rhsRoot.length() > 0)) {
+ if (rhsRoot.endsWith(".")) {
+ rhsRoot = rhsRoot.substring(0, rhsRoot.length() - 1);
+ }
+
+ // SDNGC-2321 : rhsRoot is variable name, possibly with subscript(s) to be resolved
+ try {
+ SvcLogicExpression rhsExpr = SvcLogicExpressionFactory.parse(rhsRoot);
+ rhsRoot = SvcLogicExpressionResolver.resolveVariableName(rhsExpr, node, ctx);
+ } catch (Exception e) {
+ LOG.warn("Caught exception trying to resolve variable name (" + rhsRoot + ")", e);
+ }
+
+ // See if the parameters are reversed (copying service-data to input) .. this
+ // was done as a workaround to earlier issue
+ if (curName.endsWith("-input.") && rhsRoot.startsWith("service-data")) {
+ LOG.warn("Arguments appear to be reversed .. will copy input to service-data instead");
+ lhsVarName = rhsRoot + ".";
+ rhsRoot = curName.substring(0, curName.length() - 1);
+ }
+
+ rhsRoot = rhsRoot + ".";
+ String lhsPrefix = lhsVarName;
+
+ if (lhsPrefix.endsWith(".")) {
+ lhsPrefix = lhsPrefix.substring(0, lhsPrefix.length() - 1);
+ }
+
+ HashMap<String, String> parmsToAdd = new HashMap<>();
+
+ for (String sourceVarName : ctx.getAttributeKeySet()) {
+ if (sourceVarName.startsWith(rhsRoot)) {
+ String targetVar = lhsPrefix + "." + sourceVarName.substring(rhsRoot.length());
+ LOG.debug("Copying {} value to {}", sourceVarName, targetVar);
+ parmsToAdd.put(targetVar, ctx.getAttribute(sourceVarName));
+ }
+ }
+ for (String newParmName : parmsToAdd.keySet()) {
+ ctx.setAttribute(newParmName, parmsToAdd.get(newParmName));
+ }
+ } else {
+ // If RHS is empty, unset attributes in LHS
+ LinkedList<String> parmsToRemove = new LinkedList<>();
+ String prefix = lhsVarName + ".";
+ String arrayPrefix = lhsVarName + "[";
+ //Clear length value in case an array exists with this prefix
+ String lengthParamName = lhsVarName + "_length";
+ LOG.debug("Unsetting {} because prefix {} is being cleared.", lengthParamName, prefix);
+
+ for (String curCtxVarname : ctx.getAttributeKeySet()) {
+ String curCtxVarnameMatchingValue = curCtxVarname;
+ //Special handling for reseting array values, strips out brackets and any numbers between the brackets
+ //when testing if a context memory value starts with a prefix
+ if(!prefix.contains("[") && curCtxVarnameMatchingValue.contains("[")) {
+ curCtxVarnameMatchingValue = curCtxVarname.replaceAll(arrayPattern, "") + ".";
+ }
+ if (curCtxVarnameMatchingValue.startsWith(prefix)) {
+ LOG.debug("Unsetting {} because matching value {} starts with the prefix {}", curCtxVarname, curCtxVarnameMatchingValue, prefix);
+ parmsToRemove.add(curCtxVarname);
+ }else if (curCtxVarnameMatchingValue.startsWith(lengthParamName)) {
+ LOG.debug("Unsetting {} because matching value {} starts with the lengthParamName {}", curCtxVarname, curCtxVarnameMatchingValue, lengthParamName);
+ parmsToRemove.add(curCtxVarname);
+ }else if (curCtxVarnameMatchingValue.startsWith(arrayPrefix)) {
+ LOG.debug("Unsetting {} because matching value {} starts with the arrayPrefix {}", curCtxVarname, curCtxVarnameMatchingValue, arrayPrefix);
+ parmsToRemove.add(curCtxVarname);
+ }
+ }
+ for (String parmName : parmsToRemove) {
+ ctx.setAttribute(parmName, null);
+ }
+ }
+ }
+ } else {
+ if (ifunset) {
+ String ctxValue = ctx.getAttribute(lhsVarName);
+ if ((ctxValue != null) && (ctxValue.length() > 0)) {
+ setValue = false;
+ LOG.debug("Attribute {} already set and only-if-unset is true, so not overriding", lhsVarName);
+ }
+ }
+ if (setValue) {
+ String curValue = SvcLogicExpressionResolver.evaluate(curEnt.getValue(), node, ctx);
+ if (LOG.isDebugEnabled()) {
+ LOG.debug(SETTING_DEBUG_PATTERN, lhsVarName, curValue, curEnt.getValue());
+ }
+ ctx.setAttribute(lhsVarName, curValue);
+ }
+ }
+ }
+ }
+}
+
diff --git a/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/SvcLogicExpressionResolver.java b/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/SvcLogicExpressionResolver.java
new file mode 100644
index 000000000..a3507947f
--- /dev/null
+++ b/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/SvcLogicExpressionResolver.java
@@ -0,0 +1,603 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Modifications Copyright (C) 2018 IBM.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.sli.provider.base;
+
+import java.util.List;
+
+import org.apache.commons.lang.StringUtils;
+import org.onap.ccsdk.sli.core.sli.SvcLogicAtom;
+import org.onap.ccsdk.sli.core.sli.SvcLogicBinaryExpression;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.core.sli.SvcLogicExpression;
+import org.onap.ccsdk.sli.core.sli.SvcLogicFunctionCall;
+import org.onap.ccsdk.sli.core.sli.SvcLogicNode;
+import org.onap.ccsdk.sli.core.sli.SvcLogicVariableTerm;
+import org.onap.ccsdk.sli.core.sli.SvcLogicAtom.AtomType;
+import org.onap.ccsdk.sli.core.sli.SvcLogicBinaryExpression.OperatorType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class SvcLogicExpressionResolver {
+
+ private static final Logger LOG = LoggerFactory
+ .getLogger(SvcLogicExpressionResolver.class);
+ private static final String INVALID_EXPRESSION_MSG= "Invalid expression (";
+ private static final String EXPRESSION_DEBUG_PATTERN = "Expression: ({}) resolves to: (${}) which has the value: ({})";
+
+ public static String evaluate(SvcLogicExpression expr, SvcLogicNode node,
+ SvcLogicContext ctx) throws SvcLogicException {
+ if (expr == null) {
+ return (null);
+ }
+
+ if (expr instanceof SvcLogicAtom) {
+ SvcLogicAtom atom = (SvcLogicAtom) expr;
+
+ AtomType atomType = atom.getAtomType();
+ switch (atomType) {
+ case NUMBER:
+ case STRING:
+ return (atom.toString());
+ case CONTEXT_VAR:
+ case IDENTIFIER:
+
+ String varName = resolveVariableName(atom, node, ctx);
+
+ if (atomType == AtomType.CONTEXT_VAR)
+ {
+ String varValue = ctx.getAttribute(varName);
+ if (varValue == null) {
+ LOG.trace("Context variable: ($"+varName+") unset - treating as empty string");
+ varValue = "";
+ }
+ LOG.trace(EXPRESSION_DEBUG_PATTERN, expr, varName, varValue);
+ return (varValue);
+ }
+
+ SvcLogicExpression parm = node.getParameter(varName);
+ if (parm != null) {
+ String value = evaluate(parm, node, ctx);
+ LOG.trace(EXPRESSION_DEBUG_PATTERN, expr, varName, value);
+ return value;
+ }
+ else {
+ LOG.trace(EXPRESSION_DEBUG_PATTERN, expr, varName, varName);
+ return(varName);
+ }
+ default:
+ return(null);
+ }
+
+ } else if (expr instanceof SvcLogicBinaryExpression) {
+ SvcLogicBinaryExpression binExpr = (SvcLogicBinaryExpression) expr;
+ List<OperatorType> operators = binExpr.getOperators();
+ if (operators.isEmpty())
+ {
+ List<SvcLogicExpression> operands = binExpr.getOperands();
+ if (operands.size() == 1)
+ {
+ return(evaluate(operands.get(0), node, ctx));
+ }
+ else
+ {
+ if (operands.isEmpty())
+ {
+ LOG.error("SvcLogicBinaryExpression has no operators and no operands - evaluating value as null");
+ }
+ else
+ {
+ LOG.error("SvcLogicBinaryExpression has no operators and "+operands.size()+" operands - evaluating value as null");
+ }
+ return(null);
+ }
+ }
+ switch (operators.get(0)) {
+ case addOp:
+ case subOp:
+ case multOp:
+ case divOp:
+ return(evalArithExpression(binExpr, node, ctx));
+ case equalOp:
+ case neOp:
+ case ltOp:
+ case leOp:
+ case gtOp:
+ case geOp:
+ return (evalCompareExpression(binExpr, node, ctx));
+ case andOp:
+ case orOp:
+ return(evalLogicExpression(binExpr, node, ctx));
+
+ default:
+ return(null);
+ }
+ }
+ else if (expr instanceof SvcLogicFunctionCall)
+ {
+ return(evalFunctionCall((SvcLogicFunctionCall)expr, node, ctx));
+ }
+ else
+ {
+ throw new SvcLogicException("Unrecognized expression type ["+expr+"]");
+ }
+ }
+
+ private static String evalArithExpression(SvcLogicBinaryExpression binExpr, SvcLogicNode node, SvcLogicContext ctx) throws SvcLogicException {
+ List<SvcLogicExpression> operands = binExpr.getOperands();
+ List<OperatorType> operators = binExpr.getOperators();
+ if (operands.size() != (operators.size()+1))
+ {
+ throw new SvcLogicException(INVALID_EXPRESSION_MSG+binExpr+")");
+ }
+ String retval = evaluate(operands.get(0), node, ctx);
+ String retsval = retval;
+ long retlval = 0;
+ boolean valueIsLong = false;
+
+ int i = 1;
+ try
+ {
+
+ if ((retval.length() > 0) && StringUtils.isNumeric(retval))
+ {
+ retlval = Long.parseLong(retval);
+ valueIsLong = true;
+ }
+ for (OperatorType operator: operators)
+ {
+ String curOperandValue = evaluate(operands.get(i++), node, ctx);
+ switch(operator) {
+ case addOp:
+ retsval = retsval + curOperandValue;
+ if (valueIsLong)
+ {
+ if ((curOperandValue.length() > 0) && StringUtils.isNumeric(curOperandValue) )
+ {
+ retlval = retlval + Long.parseLong(curOperandValue);
+ }
+ else
+ {
+ valueIsLong = false;
+ }
+ }
+ break;
+ case subOp:
+ retlval = retlval - Long.parseLong(curOperandValue);
+ break;
+ case multOp:
+ retlval = retlval * Long.parseLong(curOperandValue);
+ break;
+ case divOp:
+ retlval = retlval / Long.parseLong(curOperandValue);
+ break;
+ }
+
+ }
+ }
+ catch (NumberFormatException e1)
+ {
+ throw new SvcLogicException("Illegal value in arithmetic expression", e1);
+ }
+
+ if (valueIsLong)
+ {
+ return("" + retlval);
+ }
+ else
+ {
+ return(retsval);
+ }
+
+ }
+
+
+
+ private static String evalCompareExpression(SvcLogicBinaryExpression expr, SvcLogicNode node, SvcLogicContext ctx) throws SvcLogicException
+ {
+
+ List<OperatorType> operators = expr.getOperators();
+ List<SvcLogicExpression> operands = expr.getOperands();
+
+ if ((operators.size() != 1) || (operands.size() != 2))
+ {
+ throw new SvcLogicException ("Invalid comparison expression : "+expr);
+ }
+
+ OperatorType operator = operators.get(0);
+ String op1Value = evaluate(operands.get(0), node, ctx);
+ String op2Value = evaluate(operands.get(1), node, ctx);
+
+ if ((StringUtils.isNotEmpty(op1Value) && StringUtils.isNumeric(op1Value) && StringUtils.isNotEmpty(op2Value) && StringUtils.isNumeric(op2Value)))
+ {
+ try
+ {
+ double op1dbl = Double.parseDouble(op1Value);
+ double op2dbl = Double.parseDouble(op2Value);
+
+ switch(operator)
+ {
+ case equalOp:
+ return(Boolean.toString(op1dbl == op2dbl));
+ case neOp:
+ return(Boolean.toString(op1dbl != op2dbl));
+ case ltOp:
+ return(Boolean.toString(op1dbl < op2dbl));
+ case leOp:
+ return(Boolean.toString(op1dbl <= op2dbl));
+ case gtOp:
+ return(Boolean.toString(op1dbl > op2dbl));
+ case geOp:
+ return(Boolean.toString(op1dbl >= op2dbl));
+ default:
+ return(null);
+ }
+ }
+ catch (NumberFormatException e)
+ {
+ throw new SvcLogicException("Caught exception trying to compare numeric values", e);
+ }
+ }
+ else
+ {
+
+ int compResult = 0;
+
+ if (op1Value == null) {
+ compResult = -1;
+ } else if (op2Value == null ) {
+ compResult = 1;
+ } else {
+ compResult = op1Value.compareToIgnoreCase(op2Value);
+ }
+
+ switch(operator)
+ {
+ case equalOp:
+ return(Boolean.toString(compResult == 0));
+ case neOp:
+ return(Boolean.toString(compResult != 0));
+ case ltOp:
+ return(Boolean.toString(compResult < 0));
+ case leOp:
+ return(Boolean.toString(compResult <= 0));
+ case gtOp:
+ return(Boolean.toString(compResult > 0));
+ case geOp:
+ return(Boolean.toString(compResult >= 0));
+ default:
+ return(null);
+ }
+ }
+
+ }
+
+ private static String evalLogicExpression(SvcLogicBinaryExpression expr, SvcLogicNode node, SvcLogicContext ctx) throws SvcLogicException
+ {
+ boolean retval;
+
+ List<SvcLogicExpression> operands = expr.getOperands();
+ List<OperatorType> operators = expr.getOperators();
+
+ if (operands.size() != (operators.size()+1))
+ {
+ throw new SvcLogicException(INVALID_EXPRESSION_MSG+expr+")");
+ }
+
+ try
+ {
+ retval = Boolean.parseBoolean(evaluate(operands.get(0), node, ctx));
+ int i = 1;
+ for (OperatorType operator : operators)
+ {
+ if (operator == OperatorType.andOp)
+ {
+ retval = retval && Boolean.parseBoolean(evaluate(operands.get(i++), node, ctx));
+ }
+ else
+ {
+
+ retval = retval || Boolean.parseBoolean(evaluate(operands.get(i++), node, ctx));
+ }
+
+ }
+ }
+ catch (Exception e)
+ {
+ throw new SvcLogicException(INVALID_EXPRESSION_MSG+expr+")");
+ }
+
+
+ return(Boolean.toString(retval));
+ }
+
+ private static String evalFunctionCall(SvcLogicFunctionCall func, SvcLogicNode node, SvcLogicContext ctx) throws SvcLogicException
+ {
+ String funcName = func.getFunctionName();
+ List<SvcLogicExpression> operands = func.getOperands();
+
+ if ("length".equalsIgnoreCase(funcName))
+ {
+
+ if (operands.size() == 1)
+ {
+ String opValue = evaluate(operands.get(0), node, ctx);
+ return(""+opValue.length());
+ }
+ else
+ {
+ throw new SvcLogicException("Invalid call to length() function");
+ }
+ }
+ else if ("substr".equalsIgnoreCase(funcName))
+ {
+ if (operands.size() == 3)
+ {
+ String op1Value = evaluate(operands.get(0), node, ctx);
+ String op2Value = evaluate(operands.get(1), node, ctx);
+ String op3Value = evaluate(operands.get(2), node, ctx);
+
+ if (!StringUtils.isNumeric(op2Value) || !StringUtils.isNumeric(op3Value))
+ {
+ throw new SvcLogicException("Invalid arguments to substr() function");
+ }
+
+ try
+ {
+ return(op1Value.substring(Integer.parseInt(op2Value), Integer.parseInt(op3Value)));
+ }
+ catch (Exception e)
+ {
+ throw new SvcLogicException("Caught exception trying to take substring", e);
+ }
+ }
+ else
+ {
+
+ throw new SvcLogicException("Invalid call to substr() function");
+ }
+
+ }
+ else if ("toUpperCase".equalsIgnoreCase(funcName))
+ {
+ if (operands.size() == 1)
+ {
+ String opValue = evaluate(operands.get(0), node, ctx);
+ if (opValue != null) {
+ return(opValue.toUpperCase());
+ } else {
+ return("");
+ }
+ }
+ else
+ {
+ throw new SvcLogicException("Invalid call to toUpperCase() function");
+ }
+ }
+ else if ("toLowerCase".equalsIgnoreCase(funcName))
+ {
+ if (operands.size() == 1)
+ {
+ String opValue = evaluate(operands.get(0), node, ctx);
+ if (opValue != null) {
+ return(opValue.toLowerCase());
+ } else {
+ return("");
+ }
+ }
+ else
+ {
+ throw new SvcLogicException("Invalid call to toLowerCase() function");
+ }
+ }
+ else if ("convertBase".equalsIgnoreCase(funcName)) {
+ int fromBase = 10;
+ int toBase = 10;
+ String srcString = "";
+
+ if (operands.size() == 2)
+ {
+ fromBase = 10;
+ srcString = evaluate(operands.get(0), node, ctx);
+ toBase = Integer.parseInt(evaluate(operands.get(1), node, ctx));
+ } else if (operands.size() == 3) {
+
+ srcString = evaluate(operands.get(0), node, ctx);
+ fromBase = Integer.parseInt(evaluate(operands.get(1), node, ctx));
+ toBase = Integer.parseInt(evaluate(operands.get(2), node, ctx));
+ } else {
+ throw new SvcLogicException("Invalid call to convertBase() function");
+ }
+
+ long srcValue = Long.parseLong(srcString, fromBase);
+ return(Long.toString(srcValue, toBase));
+ }
+ else
+ {
+ throw new SvcLogicException("Unrecognized function ("+funcName+")");
+ }
+
+ }
+
+ public static String evaluateAsKey(SvcLogicExpression expr, SvcLogicNode node,
+ SvcLogicContext ctx) throws SvcLogicException {
+ if (expr == null) {
+ return (null);
+ }
+
+
+
+ if (expr instanceof SvcLogicAtom) {
+ SvcLogicAtom atom = (SvcLogicAtom) expr;
+
+ AtomType atomType = atom.getAtomType();
+ StringBuffer varNameBuff = new StringBuffer();
+ switch (atomType) {
+ case NUMBER:
+ return (atom.toString());
+ case STRING:
+ return("'"+atom.toString()+"'");
+ case CONTEXT_VAR:
+ case IDENTIFIER:
+ boolean needDot = false;
+ for (SvcLogicExpression term : atom.getOperands())
+ {
+ if (needDot)
+ {
+ varNameBuff.append(".");
+ }
+ if (term instanceof SvcLogicVariableTerm)
+ {
+ SvcLogicVariableTerm vterm = (SvcLogicVariableTerm) term;
+ varNameBuff.append(vterm.getName());
+ if (vterm.numOperands() > 0)
+ {
+ varNameBuff.append("[");
+ varNameBuff.append(evaluate(vterm.getSubscript(), node, ctx));
+ varNameBuff.append("]");
+
+ }
+ }
+ else
+ {
+ varNameBuff.append(term.toString());
+ }
+ needDot = true;
+ }
+
+ String varName = varNameBuff.toString();
+ String ctxValue = ctx.getAttribute(varName);
+ if (ctxValue == null)
+ {
+ return(null);
+ }
+ if (StringUtils.isNumeric(ctxValue))
+ {
+ return(ctxValue);
+ }
+ else
+ {
+ return("'"+ctxValue+"'");
+ }
+
+ default:
+ return(null);
+ }
+
+ } else if (expr instanceof SvcLogicBinaryExpression) {
+ SvcLogicBinaryExpression binExpr = (SvcLogicBinaryExpression) expr;
+ List<OperatorType> operators = binExpr.getOperators();
+ List<SvcLogicExpression> operands = binExpr.getOperands();
+ if (operators.isEmpty())
+ {
+ if (operands.size() == 1)
+ {
+ LOG.debug("SvcLogicBinaryExpression as no operator and one operand - evaluating its operand");
+ return(evaluateAsKey(operands.get(0), node, ctx));
+ }
+ else
+ {
+ if (operands.isEmpty())
+ {
+ LOG.error("SvcLogicBinaryExpression has no operators and no operands - evaluating value as null");
+ }
+ else
+ {
+ LOG.error("SvcLogicBinaryExpression has no operators and "+operands.size()+" operands - evaluating value as null");
+ }
+ return(null);
+ }
+ }
+ StringBuffer sbuff = new StringBuffer();
+ sbuff.append(evaluateAsKey(operands.get(0), node, ctx));
+ int i = 1;
+ for (OperatorType operator : operators)
+ {
+ sbuff.append(" ");
+ sbuff.append(operator.toString());
+ sbuff.append(" ");
+ sbuff.append(evaluateAsKey(operands.get(i++), node,ctx));
+ }
+ return(sbuff.toString());
+ }
+ else if (expr instanceof SvcLogicFunctionCall)
+ {
+ StringBuffer sbuff = new StringBuffer();
+ SvcLogicFunctionCall funcCall = (SvcLogicFunctionCall) expr;
+ sbuff.append(funcCall.getFunctionName());
+ sbuff.append("(");
+ boolean needComma = false;
+ for (SvcLogicExpression operand : funcCall.getOperands())
+ {
+ if (needComma)
+ {
+ sbuff.append(",");
+ }
+ else
+ {
+ needComma = true;
+ }
+ sbuff.append(evaluateAsKey(operand, node, ctx));
+ }
+ sbuff.append(")");
+ return(sbuff.toString());
+ }
+ else
+ {
+ throw new SvcLogicException("Unrecognized expression type ["+expr+"]");
+ }
+ }
+
+ public static String resolveVariableName(SvcLogicExpression atom, SvcLogicNode node, SvcLogicContext ctx) throws SvcLogicException
+ {
+ StringBuffer varNameBuff = new StringBuffer();
+
+ boolean needDot = false;
+ for (SvcLogicExpression term : atom.getOperands())
+ {
+ if (needDot)
+ {
+ varNameBuff.append(".");
+ }
+ if (term instanceof SvcLogicVariableTerm)
+ {
+ SvcLogicVariableTerm vterm = (SvcLogicVariableTerm) term;
+ varNameBuff.append(vterm.getName());
+ if (vterm.numOperands() > 0)
+ {
+ varNameBuff.append("[");
+ varNameBuff.append(evaluate(vterm.getSubscript(), node, ctx));
+ varNameBuff.append("]");
+ }
+ }
+ else
+ {
+ varNameBuff.append(term.toString());
+ }
+ needDot = true;
+ }
+ return(varNameBuff.toString());
+ }
+
+}
diff --git a/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/SvcLogicPropertiesProvider.java b/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/SvcLogicPropertiesProvider.java
new file mode 100644
index 000000000..fc108f951
--- /dev/null
+++ b/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/SvcLogicPropertiesProvider.java
@@ -0,0 +1,28 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * onap
+ * ================================================================================
+ * Copyright (C) 2016 - 2017 ONAP
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.sli.provider.base;
+
+import java.util.Properties;
+
+public interface SvcLogicPropertiesProvider {
+
+ public Properties getProperties();;
+}
diff --git a/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/SvcLogicResolver.java b/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/SvcLogicResolver.java
new file mode 100644
index 000000000..08b675958
--- /dev/null
+++ b/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/SvcLogicResolver.java
@@ -0,0 +1,17 @@
+package org.onap.ccsdk.sli.core.sli.provider.base;
+
+import org.onap.ccsdk.sli.core.sli.SvcLogicAdaptor;
+import org.onap.ccsdk.sli.core.sli.SvcLogicJavaPlugin;
+import org.onap.ccsdk.sli.core.sli.SvcLogicRecorder;
+import org.onap.ccsdk.sli.core.sli.SvcLogicResource;
+
+public interface SvcLogicResolver {
+
+ abstract SvcLogicResource getSvcLogicResource(String resourceName);
+
+ abstract SvcLogicRecorder getSvcLogicRecorder(String recorderName);
+
+ abstract SvcLogicJavaPlugin getSvcLogicJavaPlugin(String pluginName);
+
+ abstract SvcLogicAdaptor getSvcLogicAdaptor(String adaptorName);
+}
diff --git a/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/SvcLogicServiceBase.java b/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/SvcLogicServiceBase.java
new file mode 100644
index 000000000..3bade8132
--- /dev/null
+++ b/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/SvcLogicServiceBase.java
@@ -0,0 +1,80 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.sli.provider.base;
+
+import java.util.Properties;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.core.sli.SvcLogicGraph;
+import org.onap.ccsdk.sli.core.sli.SvcLogicNode;
+import org.onap.ccsdk.sli.core.sli.SvcLogicStore;
+
+public interface SvcLogicServiceBase {
+
+
+ /**
+ * Check for existence of a directed graph
+ * @param module - module name
+ * @param rpc - rpc name
+ * @param version - version. If null, looks for active version
+ * @param mode - mode (sync/async)
+ * @return true if directed graph found, false otherwise
+ * @throws SvcLogicException
+ */
+ boolean hasGraph(String module, String rpc, String version, String mode) throws SvcLogicException;
+
+ /**
+ * Execute a directed graph
+ *
+ * @param module - module name
+ * @param rpc - rpc name
+ * @param version - version. If null, use active version
+ * @param mode - mode (sync/async)
+ * @param parms - parameters, used to set SvcLogicContext attributes
+ * @return final values of attributes from SvcLogicContext, as Properties
+ * @throws SvcLogicException
+ *
+ *
+ */
+ Properties execute(String module, String rpc, String version, String mode, Properties parms) throws SvcLogicException;
+ /**
+ * Execute a directed graph
+ *
+ * @param module - module name
+ * @param rpc - rpc name
+ * @param version - version. If null, use active version
+ * @param mode - mode (sync/async)
+ * @param ctx - parameters, as a SvcLogicContext object
+ * @return final values of attributes from SvcLogicContext, as Properties
+ * @throws SvcLogicException
+ *
+ *
+ */
+ SvcLogicContext execute(String module, String rpc, String version, String mode, SvcLogicContext ctx) throws SvcLogicException;
+
+ SvcLogicStore getStore() throws SvcLogicException;
+
+ SvcLogicContext execute(SvcLogicGraph calledGraph, SvcLogicContext ctx) throws SvcLogicException;
+
+ SvcLogicNode executeNode(SvcLogicNode nextNode, SvcLogicContext ctx) throws SvcLogicException;
+
+}
diff --git a/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/SvcLogicServiceImplBase.java b/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/SvcLogicServiceImplBase.java
new file mode 100644
index 000000000..75673f756
--- /dev/null
+++ b/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/SvcLogicServiceImplBase.java
@@ -0,0 +1,180 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Modifications Copyright (C) 2018 IBM.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.sli.provider.base;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+import org.onap.ccsdk.sli.core.sli.ExitNodeException;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.core.sli.SvcLogicGraph;
+import org.onap.ccsdk.sli.core.sli.SvcLogicNode;
+import org.onap.ccsdk.sli.core.sli.SvcLogicStore;
+import org.onap.logging.ref.slf4j.ONAPLogConstants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.slf4j.MDC;
+
+public class SvcLogicServiceImplBase implements SvcLogicServiceBase {
+ protected SvcLogicResolver resolver;
+ protected static final Map<String, AbstractSvcLogicNodeExecutor> BUILTIN_NODES = new HashMap<String, AbstractSvcLogicNodeExecutor>() {
+ {
+ put("block", new BlockNodeExecutor());
+ put("call", new CallNodeExecutor());
+ put("configure", new ConfigureNodeExecutor());
+ put("delete", new DeleteNodeExecutor());
+ put("execute", new ExecuteNodeExecutor());
+ put("exists", new ExistsNodeExecutor());
+ put("for", new ForNodeExecutor());
+ put("get-resource", new GetResourceNodeExecutor());
+ put("is-available", new IsAvailableNodeExecutor());
+ put("notify", new NotifyNodeExecutor());
+ put("record", new RecordNodeExecutor());
+ put("release", new ReleaseNodeExecutor());
+ put("reserve", new ReserveNodeExecutor());
+ put("return", new ReturnNodeExecutor());
+ put("save", new SaveNodeExecutor());
+ put("set", new SetNodeExecutor());
+ put("switch", new SwitchNodeExecutor());
+ put("update", new UpdateNodeExecutor());
+ put("break", new BreakNodeExecutor());
+ put("while", new WhileNodeExecutor());
+ put("exit", new ExitNodeExecutor());
+ }
+ };
+
+ private static final Logger LOG = LoggerFactory.getLogger(SvcLogicServiceImplBase.class);
+ protected HashMap<String, AbstractSvcLogicNodeExecutor> nodeExecutors = null;
+ protected Properties properties;
+ protected SvcLogicStore store;
+ protected static final String CURRENT_GRAPH="currentGraph";
+
+ public SvcLogicServiceImplBase(SvcLogicStore store, SvcLogicResolver resolver) {
+ this.store = store;
+ this.resolver = resolver;
+ }
+
+ protected void registerExecutors() {
+ for (String nodeType : BUILTIN_NODES.keySet()) {
+ registerExecutor(nodeType, BUILTIN_NODES.get(nodeType));
+ }
+ }
+
+ public void registerExecutor(String nodeName, AbstractSvcLogicNodeExecutor executor) {
+ if (nodeExecutors == null) {
+ nodeExecutors = new HashMap<>();
+ }
+ executor.setResolver(resolver);
+ nodeExecutors.put(nodeName, executor);
+ }
+
+ public void unregisterExecutor(String nodeName) {
+ nodeExecutors.remove(nodeName);
+ }
+
+ public SvcLogicContext execute(SvcLogicGraph graph, SvcLogicContext ctx) throws SvcLogicException {
+ if (nodeExecutors == null) {
+ registerExecutors();
+ }
+
+ MDC.put(CURRENT_GRAPH, graph.toString());
+
+ SvcLogicNode curNode = graph.getRootNode();
+ LOG.info("About to execute graph {}", graph.toString());
+ try {
+ while (curNode != null) {
+ SvcLogicNode nextNode = executeNode(curNode, ctx);
+ curNode = nextNode;
+ }
+ } catch (ExitNodeException e) {
+ LOG.debug("SvcLogicServiceImpl caught ExitNodeException");
+ }
+ MDC.remove("nodeId");
+ MDC.remove(CURRENT_GRAPH);
+
+ return (ctx);
+ }
+
+ public SvcLogicNode executeNode(SvcLogicNode node, SvcLogicContext ctx) throws SvcLogicException {
+ if (node == null) {
+ return (null);
+ }
+
+ LOG.info("About to execute node #{} {} node in graph {}", node.getNodeId(), node.getNodeType(), node.getGraph().toString());
+
+ AbstractSvcLogicNodeExecutor executor = nodeExecutors.get(node.getNodeType());
+
+ if (executor != null) {
+ MDC.put("nodeId", node.getNodeId() + " (" + node.getNodeType() + ")");
+ return (executor.execute(this, node, ctx));
+ } else {
+ throw new SvcLogicException("Attempted to execute a node of type " + node.getNodeType() + ", but no executor was registered for this type");
+ }
+ }
+
+ @Override
+ public boolean hasGraph(String module, String rpc, String version, String mode) throws SvcLogicException {
+ return (store.hasGraph(module, rpc, version, mode));
+ }
+
+ @Override
+ public Properties execute(String module, String rpc, String version, String mode, Properties props)
+ throws SvcLogicException {
+
+ SvcLogicContext ctx = new SvcLogicContext(props);
+
+ return(execute(module, rpc, version, mode, ctx).toProperties());
+ }
+
+ @Override
+ public SvcLogicContext execute(String module, String rpc, String version, String mode, SvcLogicContext ctx) throws SvcLogicException {
+ SvcLogicGraph graph = store.fetch(module, rpc, version, mode);
+
+ if (ctx == null) {
+ ctx = new SvcLogicContext();
+ }
+
+ if (graph == null) {
+ ctx.setAttribute("error-code", "401");
+ ctx.setAttribute("error-message",
+ "No service logic found for [" + module + "," + rpc + "," + version + "," + mode + "]");
+ return (ctx);
+ }
+
+
+
+ ctx.setAttribute(CURRENT_GRAPH, graph.toString());
+ // To support legacy code we should not stop populating X-ECOMP-RequestID
+ ctx.setAttribute("X-ECOMP-RequestID", MDC.get(ONAPLogConstants.MDCs.REQUEST_ID));
+ execute(graph, ctx);
+ return (ctx);
+ }
+
+ @Override
+ public SvcLogicStore getStore() throws SvcLogicException {
+ return this.store;
+ }
+
+}
diff --git a/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/SwitchNodeExecutor.java b/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/SwitchNodeExecutor.java
new file mode 100644
index 000000000..2186a38e0
--- /dev/null
+++ b/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/SwitchNodeExecutor.java
@@ -0,0 +1,63 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.sli.provider.base;
+
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.core.sli.SvcLogicNode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class SwitchNodeExecutor extends AbstractSvcLogicNodeExecutor {
+
+ private static final Logger LOG = LoggerFactory
+ .getLogger(SwitchNodeExecutor.class);
+
+ @Override
+
+ public SvcLogicNode execute(SvcLogicServiceBase svc, SvcLogicNode node,
+ SvcLogicContext ctx) throws SvcLogicException {
+
+
+ String testResult = evaluateNodeTest(node, ctx);
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Executing switch node");
+
+
+ LOG.debug("test expression (" + node.getAttribute("test")
+ + ") evaluates to " + testResult);
+ }
+
+ SvcLogicNode nextNode = node.getOutcomeValue(testResult);
+
+ if (LOG.isDebugEnabled()) {
+ if (nextNode != null) {
+ LOG.debug("Next node to execute is node " + nextNode.getNodeId());
+ } else {
+ LOG.debug("No next node found");
+ }
+ }
+ return (nextNode);
+
+ }
+}
diff --git a/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/UpdateNodeExecutor.java b/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/UpdateNodeExecutor.java
new file mode 100644
index 000000000..c22c573cd
--- /dev/null
+++ b/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/UpdateNodeExecutor.java
@@ -0,0 +1,89 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Modifications Copyright (C) 2018 IBM.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.sli.provider.base;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import org.onap.ccsdk.sli.core.sli.SvcLogicConstants;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.core.sli.SvcLogicExpression;
+import org.onap.ccsdk.sli.core.sli.SvcLogicNode;
+import org.onap.ccsdk.sli.core.sli.SvcLogicResource;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class UpdateNodeExecutor extends AbstractSvcLogicNodeExecutor {
+
+ private static final Logger LOG = LoggerFactory.getLogger(UpdateNodeExecutor.class);
+
+ @Override
+ public SvcLogicNode execute(SvcLogicServiceBase svc, SvcLogicNode node, SvcLogicContext ctx)
+ throws SvcLogicException {
+
+ String plugin = SvcLogicExpressionResolver.evaluate(node.getAttribute("plugin"), node, ctx);
+ String resourceType = SvcLogicExpressionResolver.evaluate(node.getAttribute("resource"), node, ctx);
+ String key = SvcLogicExpressionResolver.evaluateAsKey(node.getAttribute("key"), node, ctx);
+ String pfx = SvcLogicExpressionResolver.evaluate(node.getAttribute("pfx"), node, ctx);
+
+
+ Map<String, String> parmMap = getResolvedParameters(node,ctx);
+
+ String outValue = SvcLogicConstants.FAILURE;
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("save node encountered - looking for resource class " + plugin);
+ }
+
+
+ SvcLogicResource resourcePlugin = getSvcLogicResource(plugin);
+
+
+ if (resourcePlugin != null) {
+
+ try {
+ switch (resourcePlugin.update(resourceType, key, parmMap, pfx, ctx)) {
+ case SUCCESS:
+ outValue = SvcLogicConstants.SUCCESS;
+ break;
+ case NOT_FOUND:
+ outValue = "not-found";
+ break;
+ case FAILURE:
+ default:
+ outValue = SvcLogicConstants.FAILURE;
+ }
+ } catch (SvcLogicException e) {
+ LOG.error("Caught exception from resource plugin", e);
+ outValue = SvcLogicConstants.FAILURE;
+ }
+ } else {
+ LOG.warn("Could not find SvcLogicResource object for plugin " + plugin);
+ }
+ return (getNextNode(node, outValue));
+ }
+
+}
diff --git a/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/WhileNodeExecutor.java b/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/WhileNodeExecutor.java
new file mode 100644
index 000000000..3078b3437
--- /dev/null
+++ b/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/WhileNodeExecutor.java
@@ -0,0 +1,75 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.sli.provider.base;
+
+import org.onap.ccsdk.sli.core.sli.BreakNodeException;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.core.sli.SvcLogicExpression;
+import org.onap.ccsdk.sli.core.sli.SvcLogicNode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class WhileNodeExecutor extends AbstractSvcLogicNodeExecutor {
+
+ private static final Logger LOG = LoggerFactory.getLogger(WhileNodeExecutor.class);
+
+ @Override
+ public SvcLogicNode execute(SvcLogicServiceBase svc, SvcLogicNode node, SvcLogicContext ctx) throws SvcLogicException {
+
+ String testResult = evaluateNodeTest(node, ctx);
+ SvcLogicExpression silentFailureExpr = node.getAttribute("do");
+ String doWhile = SvcLogicExpressionResolver.evaluate(silentFailureExpr, node, ctx);
+ if ("true".equals(doWhile)) {
+ LOG.debug("While loop will execute once regardless of expression because do is set to true");
+ }
+
+ try {
+ while ("true".equals(testResult) || "true".equals(doWhile)) {
+ if (!"true".equals(doWhile)) {
+ LOG.debug("Test expression (" + node.getAttribute("test") + ") evaluates to true, executing loop.");
+ }
+ int numOutcomes = node.getNumOutcomes() + 1;
+ for (int i = 0; i < numOutcomes; i++) {
+ SvcLogicNode nextNode = node.getOutcomeValue("" + (i + 1));
+ if (nextNode != null) {
+ while (nextNode != null) {
+ nextNode = svc.executeNode(nextNode, ctx);
+ }
+ } else {
+ if ("true".equals(doWhile)) {
+ LOG.debug("Do executed, will only execute again if test expression is true.");
+ doWhile = "false";
+ }
+ testResult = evaluateNodeTest(node, ctx);
+ LOG.debug("test expression (" + node.getAttribute("test") + ") evaluates to " + testResult);
+ }
+ }
+ }
+ LOG.debug("testResult was " + testResult + " which is not equal to true, exiting while loop.");
+ } catch (BreakNodeException e) {
+ LOG.debug("WhileNodeExecutor caught break" + e.getMessage());
+ }
+ return (null);
+ }
+
+}
diff --git a/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/recording/FileRecorder.java b/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/recording/FileRecorder.java
new file mode 100644
index 000000000..7d690e745
--- /dev/null
+++ b/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/recording/FileRecorder.java
@@ -0,0 +1,113 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Modifications Copyright (C) 2018 IBM.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.sli.recording;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.PrintWriter;
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Map;
+import java.util.TimeZone;
+
+import org.onap.ccsdk.sli.core.sli.ConfigurationException;
+import org.onap.ccsdk.sli.core.utils.PathValidator;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.core.sli.SvcLogicRecorder;
+
+
+public class FileRecorder implements SvcLogicRecorder {
+
+ @Override
+ public void record(Map<String, String> parmMap) throws SvcLogicException {
+
+ String fileName = parmMap.get("file");
+ if (fileName == null)
+ {
+ throw new ConfigurationException("No file parameter specified");
+ }
+
+ if (!PathValidator.isValidFilePath(fileName)) {
+ throw new ConfigurationException("Invalid file name ("+fileName+")");
+ }
+
+ String record = parmMap.get("record");
+ if (record == null)
+ {
+ String delimiter = parmMap.get("delimiter");
+ if (delimiter == null)
+ {
+ delimiter = "|";
+ }
+
+ int idx = 1;
+ boolean moreFields = true;
+ while (moreFields)
+ {
+ String curField = parmMap.get("field"+idx++);
+ if (curField == null)
+ {
+ moreFields = false;
+ }
+ else
+ {
+ if (record == null)
+ {
+ record = delimiter;
+ }
+ record = record + curField + delimiter;
+ }
+ }
+ }
+
+ if (record == null)
+ {
+ throw new ConfigurationException("No record/fields passed in record node");
+ }
+
+ File recordFile = new File(fileName);
+ Date now = new Date();
+
+ TimeZone tz = TimeZone.getTimeZone("UTC");
+ DateFormat dateFmt = new SimpleDateFormat("yyy-MM-dd'T'HH:mm:ss:SS'+00:00'");
+ dateFmt.setTimeZone(tz);
+ if (record.indexOf("__TIMESTAMP__") != -1)
+ {
+ record = record.replaceFirst("__TIMESTAMP__", dateFmt.format(now));
+ }
+
+ try ( FileWriter fileWriter = new FileWriter(recordFile, true);
+ PrintWriter recPrinter = new PrintWriter(fileWriter))
+ {
+ recPrinter.println(record);
+ }
+ catch (Exception e)
+ {
+ throw new SvcLogicException("Cannot write record to file", e);
+ }
+ }
+
+}
+
diff --git a/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/recording/Slf4jRecorder.java b/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/recording/Slf4jRecorder.java
new file mode 100644
index 000000000..4f67c5d9a
--- /dev/null
+++ b/core/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/recording/Slf4jRecorder.java
@@ -0,0 +1,160 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.sli.recording;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Map;
+import java.util.TimeZone;
+
+import org.onap.ccsdk.sli.core.sli.ConfigurationException;
+import org.onap.ccsdk.sli.core.sli.ErrorLogger;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.core.sli.SvcLogicRecorder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class Slf4jRecorder implements SvcLogicRecorder {
+ protected DateFormat dateFmt;
+ protected static final String messageLogName = "message-log";
+
+ public enum Level {
+ ERROR,
+ WARN,
+ INFO,
+ DEBUG,
+ TRACE
+ }
+
+ protected Logger defaultLogger = LoggerFactory.getLogger(Slf4jRecorder.class);
+ protected Logger messageLogger = LoggerFactory.getLogger(messageLogName);
+
+ public Slf4jRecorder() {
+ TimeZone tz = TimeZone.getTimeZone("UTC");
+ dateFmt = new SimpleDateFormat("yyy-MM-dd'T'HH:mm:ss:SS'+00:00'");
+ dateFmt.setTimeZone(tz);
+ }
+
+ @Override
+ public void record(Map<String, String> parmMap) throws SvcLogicException {
+ String lvl = parmMap.get("level");
+ if (lvl == null) {
+ lvl = "INFO";
+ }
+
+ Level level = Level.INFO;
+
+ try {
+ level = Level.valueOf(lvl.toUpperCase());
+ } catch (Exception e) {}
+
+
+
+ String record = parmMap.get("record");
+ if (record == null)
+ {
+ String delimiter = parmMap.get("delimiter");
+ if (delimiter == null)
+ {
+ delimiter = "|";
+ }
+
+ int idx = 1;
+ boolean moreFields = true;
+ while (moreFields)
+ {
+ String curField = parmMap.get("field"+idx++);
+ if (curField == null)
+ {
+ moreFields = false;
+ }
+ else
+ {
+ if (record == null)
+ {
+ record = delimiter;
+ }
+ record = record + curField + delimiter;
+ }
+ }
+ }
+
+ if (record == null)
+ {
+ throw new ConfigurationException("No record/fields passed in record node");
+ }
+
+ String loggerName = parmMap.get("logger");
+ Logger logger = null;
+ if (loggerName == null) {
+ logger = defaultLogger;
+ }else {
+ if(loggerName.equals(messageLogName)){
+ logger = messageLogger;
+ }else {
+ logger = LoggerFactory.getLogger(loggerName);
+ }
+ }
+
+ Date now = new Date();
+
+ if (record.indexOf("__TIMESTAMP__") != -1)
+ {
+ record = record.replaceFirst("__TIMESTAMP__", dateFmt.format(now));
+ }
+
+ switch (level) {
+ case ERROR:
+ String errorCode = parmMap.get("errorCode");
+ String errorDescription = parmMap.get("errorDescription");
+
+ if ((errorCode != null && !errorCode.isEmpty())
+ || (errorDescription != null && !errorDescription.isEmpty())) {
+ ErrorLogger e = new ErrorLogger(logger);
+
+ Integer integerCode = 0;
+ try {
+ integerCode = Integer.valueOf(errorCode);
+ } catch (NumberFormatException nfe) {
+ // do nothing
+ }
+ e.createLogEntry(record, integerCode, errorDescription, null);
+ } else {
+ logger.error(record);
+ }
+ break;
+ case WARN:
+ logger.warn(record);
+ break;
+ case INFO:
+ logger.info(record);
+ break;
+ case DEBUG:
+ logger.debug(record);
+ break;
+ case TRACE:
+ logger.trace(record);
+ }
+ }
+
+}
diff --git a/core/sli/provider-base/src/test/java/org/onap/ccsdk/sli/core/sli/provider/base/BadPlugin.java b/core/sli/provider-base/src/test/java/org/onap/ccsdk/sli/core/sli/provider/base/BadPlugin.java
new file mode 100644
index 000000000..6c5877ebc
--- /dev/null
+++ b/core/sli/provider-base/src/test/java/org/onap/ccsdk/sli/core/sli/provider/base/BadPlugin.java
@@ -0,0 +1,56 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.sli.provider.base;
+
+import java.util.Map;
+
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.core.sli.SvcLogicJavaPlugin;
+
+
+public class BadPlugin implements SvcLogicJavaPlugin {
+ public String selectLunch(Map<String, String> parameters, SvcLogicContext ctx) throws SvcLogicException {
+ String day = parameters.get("day");
+ if (day == null || day.length() < 1) {
+ throw new SvcLogicException("What day is it?");
+ }
+ switch (day) {
+ case ("monday"): {
+ return "pizza";
+ }
+ case ("tuesday"): {
+ return "soup";
+ }
+ case ("wednesday"): {
+ return "salad";
+ }
+ case ("thursday"): {
+ return "sushi";
+ }
+ case ("friday"): {
+ return "bbq";
+ }
+ }
+ throw new SvcLogicException("Lunch cannot be served");
+ }
+}
diff --git a/core/sli/provider-base/src/test/java/org/onap/ccsdk/sli/core/sli/provider/base/ExecuteNodeExecutorTest.java b/core/sli/provider-base/src/test/java/org/onap/ccsdk/sli/core/sli/provider/base/ExecuteNodeExecutorTest.java
new file mode 100644
index 000000000..9a929387f
--- /dev/null
+++ b/core/sli/provider-base/src/test/java/org/onap/ccsdk/sli/core/sli/provider/base/ExecuteNodeExecutorTest.java
@@ -0,0 +1,64 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.sli.provider.base;
+
+import java.util.Properties;
+import org.onap.ccsdk.sli.core.sli.DuplicateValueException;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.core.sli.SvcLogicExpression;
+import org.onap.ccsdk.sli.core.sli.SvcLogicGraph;
+import org.onap.ccsdk.sli.core.sli.SvcLogicJavaPlugin;
+import org.onap.ccsdk.sli.core.sli.SvcLogicNode;
+import junit.framework.TestCase;
+
+public class ExecuteNodeExecutorTest extends TestCase {
+ public class MockExecuteNodeExecutor extends ExecuteNodeExecutor {
+
+ protected SvcLogicJavaPlugin getSvcLogicJavaPlugin(String pluginName) {
+ return (SvcLogicJavaPlugin) new LunchSelectorPlugin();
+ }
+
+ protected String evaluate(SvcLogicExpression expr, SvcLogicNode node,
+ SvcLogicContext ctx) throws SvcLogicException {
+ return "selectLunch";
+ }
+ }
+
+ public void testBadPlugin() throws DuplicateValueException, SvcLogicException {
+ LunchSelectorPlugin p = new LunchSelectorPlugin();
+ MockExecuteNodeExecutor execute = new MockExecuteNodeExecutor();
+ SvcLogicNode node = new SvcLogicNode(0, "", "", new SvcLogicGraph());
+ node.setAttribute("method", "selectLunch");
+ SvcLogicPropertiesProvider resourceProvider = new SvcLogicPropertiesProvider() {
+
+ public Properties getProperties() {
+ return new Properties();
+ };
+ };
+
+
+ execute.execute(new SvcLogicServiceImplBase(null, null), new SvcLogicNode(0, "", "", new SvcLogicGraph()),
+ new SvcLogicContext());
+ }
+
+}
diff --git a/core/sli/provider-base/src/test/java/org/onap/ccsdk/sli/core/sli/provider/base/GraphTests.java b/core/sli/provider-base/src/test/java/org/onap/ccsdk/sli/core/sli/provider/base/GraphTests.java
new file mode 100644
index 000000000..3534d5f90
--- /dev/null
+++ b/core/sli/provider-base/src/test/java/org/onap/ccsdk/sli/core/sli/provider/base/GraphTests.java
@@ -0,0 +1,61 @@
+package org.onap.ccsdk.sli.core.sli.provider.base;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.Map.Entry;
+import org.junit.Test;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.core.sli.SvcLogicGraph;
+import org.onap.ccsdk.sli.core.sli.SvcLogicParser;
+import org.onap.ccsdk.sli.core.sli.SvcLogicRecorder;
+import org.onap.ccsdk.sli.core.sli.SvcLogicStore;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class GraphTests {
+
+ private static final Logger LOG = LoggerFactory.getLogger(GraphTests.class);
+ private static final SvcLogicStore store = new InMemorySvcLogicStore();
+ private static final HashMapResolver resolver = new HashMapResolver();
+ private static final SvcLogicServiceBase svc = new SvcLogicServiceImplBase(store, resolver);
+ private static final SvcLogicParser p = new SvcLogicParser();
+ // Write a very simple recorder so record nodes can be used during debugging
+ private static final SvcLogicRecorder recorder = new SvcLogicRecorder() {
+ @Override
+ public void record(Map<String, String> map) throws SvcLogicException {
+ map.remove("level");
+ for (Entry<String, String> entry : map.entrySet()) {
+ LOG.debug(entry.getKey() + " = " + entry.getValue());
+ }
+ }
+ };
+
+ @Test
+ public void testBreakNode() throws Exception {
+ // This graph as a for node that will loop with start 0 and end 999
+ // in the loop idx is printed and variable "a" is incremented by 1
+ // there is an if block in the loop that when a equals 2 a break node should execute and break out of the for
+ // loop
+ SvcLogicContext ctx = executeGraph("src/test/resources/breakGraph.xml");
+ assertTrue(ctx.isSuccess());
+ assertEquals("2", ctx.getAttribute("idx")); // the break should happen when idx equals 2
+ assertEquals("3", ctx.getAttribute("a")); // incrementing a happens before the break so a should be idx + 1
+ }
+
+ public SvcLogicContext executeGraph(String pathToGraph) throws SvcLogicException {
+ return executeGraph(pathToGraph, new SvcLogicContext());
+ }
+
+ public SvcLogicContext executeGraph(String pathToGraph, SvcLogicContext context) throws SvcLogicException {
+ resolver.addSvcLogicRecorder("org.onap.ccsdk.sli.core.sli.recording.Slf4jRecorder", recorder);
+ LinkedList<SvcLogicGraph> graphList = p.parse(pathToGraph);
+ SvcLogicGraph graph = graphList.get(0);
+ store.store(graph);
+ store.activate(graph);
+ return svc.execute(graph, context);
+ }
+
+}
diff --git a/core/sli/provider-base/src/test/java/org/onap/ccsdk/sli/core/sli/provider/base/HashMapResolverTest.java b/core/sli/provider-base/src/test/java/org/onap/ccsdk/sli/core/sli/provider/base/HashMapResolverTest.java
new file mode 100644
index 000000000..5a2140696
--- /dev/null
+++ b/core/sli/provider-base/src/test/java/org/onap/ccsdk/sli/core/sli/provider/base/HashMapResolverTest.java
@@ -0,0 +1,51 @@
+package org.onap.ccsdk.sli.core.sli.provider.base;
+
+import static org.junit.Assert.assertNotNull;
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+import org.onap.ccsdk.sli.core.sli.SvcLogicAdaptor;
+import org.onap.ccsdk.sli.core.sli.SvcLogicJavaPlugin;
+import org.onap.ccsdk.sli.core.sli.SvcLogicRecorder;
+import org.onap.ccsdk.sli.core.sli.SvcLogicResource;
+
+public class HashMapResolverTest {
+ @Mock
+ SvcLogicResource myResource;
+
+ @Mock
+ SvcLogicRecorder myRecorder;
+
+ @Mock
+ SvcLogicJavaPlugin myJavaPlugin;
+
+ @Mock
+ SvcLogicAdaptor myAdaptor;
+
+ @Rule
+ public MockitoRule mockitoRule = MockitoJUnit.rule();
+
+ @Test
+ public void simpleTest() throws Exception {
+
+ HashMapResolver resolver = new HashMapResolver();
+ String resourceKey = "simple.resource";
+ String recorderKey = "simple.record";
+ String pluginKey = "simple.plugin";
+ String adaptorKey = "simple.adaptor";
+
+ resolver.addSvcLogicAdaptor(adaptorKey, myAdaptor);
+ resolver.addSvcLogicRecorder(recorderKey, myRecorder);
+ resolver.addSvcLogicResource(resourceKey, myResource);
+ resolver.addSvcLogicSvcLogicJavaPlugin(pluginKey, myJavaPlugin);
+
+ assertNotNull(resolver.getSvcLogicAdaptor(adaptorKey));
+ assertNotNull(resolver.getSvcLogicJavaPlugin(pluginKey));
+ assertNotNull(resolver.getSvcLogicRecorder(recorderKey));
+ assertNotNull(resolver.getSvcLogicResource(resourceKey));
+
+
+ }
+}
diff --git a/core/sli/provider-base/src/test/java/org/onap/ccsdk/sli/core/sli/provider/base/InMemorySvcLogicStoreTest.java b/core/sli/provider-base/src/test/java/org/onap/ccsdk/sli/core/sli/provider/base/InMemorySvcLogicStoreTest.java
new file mode 100644
index 000000000..5f8757aa2
--- /dev/null
+++ b/core/sli/provider-base/src/test/java/org/onap/ccsdk/sli/core/sli/provider/base/InMemorySvcLogicStoreTest.java
@@ -0,0 +1,35 @@
+package org.onap.ccsdk.sli.core.sli.provider.base;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import java.util.Properties;
+import org.junit.Test;
+import org.onap.ccsdk.sli.core.sli.SvcLogicGraph;
+
+public class InMemorySvcLogicStoreTest {
+ @Test
+ public void simpleTest() throws Exception {
+ InMemorySvcLogicStore store = new InMemorySvcLogicStore();
+ store.init(new Properties());
+ SvcLogicGraph graph = new SvcLogicGraph();
+ String module = "TEST";
+ String rpc = "NOTIFICATION";
+ String mode = "sync";
+ String version = "1";
+
+ graph.setModule(module);
+ graph.setRpc(rpc);
+ graph.setMode(mode);
+ graph.setVersion(version);
+
+ store.store(graph);
+ assertTrue(store.hasGraph(module, rpc, version, mode));
+ assertNotNull(store.fetch(module, rpc, version, mode));
+ store.activate(graph);
+ store.activate(module, rpc, version, mode);
+
+ store.delete(module, rpc, version, mode);
+ assertNull(store.fetch(module, rpc, version, mode));
+ }
+}
diff --git a/core/sli/provider-base/src/test/java/org/onap/ccsdk/sli/core/sli/provider/base/LunchSelectorPlugin.java b/core/sli/provider-base/src/test/java/org/onap/ccsdk/sli/core/sli/provider/base/LunchSelectorPlugin.java
new file mode 100644
index 000000000..0f4cab748
--- /dev/null
+++ b/core/sli/provider-base/src/test/java/org/onap/ccsdk/sli/core/sli/provider/base/LunchSelectorPlugin.java
@@ -0,0 +1,78 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.sli.provider.base;
+
+import java.util.Map;
+
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.core.sli.SvcLogicJavaPlugin;
+
+
+
+public class LunchSelectorPlugin implements SvcLogicJavaPlugin {
+ public class UnknownLunchDayException extends Exception{
+
+ public UnknownLunchDayException(String string) {
+ super(string);
+ }
+
+ }
+ class Sandwhich {
+ String meat;
+ String cheese;
+
+ public Sandwhich(String meat, String cheese) {
+ this.meat = meat;
+ this.cheese = cheese;
+ }
+ }
+
+ public String selectLunch(Map<String, String> parameters, SvcLogicContext ctx) throws Exception {
+ String day = parameters.get("day");
+ if (day == null || day.length() < 1) {
+ throw new UnknownLunchDayException("What day is it?");
+ }
+ switch (day) {
+ case ("monday"): {
+ return "pizza";
+ }
+ case ("tuesday"): {
+ return "soup";
+ }
+ case ("wednesday"): {
+ return "salad";
+ }
+ case ("thursday"): {
+ return "sushi";
+ }
+ case ("friday"): {
+ return "bbq";
+ }
+ }
+ throw new SvcLogicException("Lunch cannot be served");
+ }
+
+ public Sandwhich makeLunch(Map<String, String> parameters, SvcLogicContext ctx) throws SvcLogicException {
+ return new Sandwhich("ham", "american");
+ }
+}
diff --git a/core/sli/provider-base/src/test/java/org/onap/ccsdk/sli/core/sli/provider/base/PluginTest.java b/core/sli/provider-base/src/test/java/org/onap/ccsdk/sli/core/sli/provider/base/PluginTest.java
new file mode 100644
index 000000000..b154ecf01
--- /dev/null
+++ b/core/sli/provider-base/src/test/java/org/onap/ccsdk/sli/core/sli/provider/base/PluginTest.java
@@ -0,0 +1,113 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.sli.provider.base;
+
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.Map;
+import org.onap.ccsdk.sli.core.sli.SvcLogicConstants;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.core.sli.SvcLogicGraph;
+import org.onap.ccsdk.sli.core.sli.SvcLogicJavaPlugin;
+import org.onap.ccsdk.sli.core.sli.SvcLogicNode;
+import org.onap.ccsdk.sli.core.sli.provider.base.ExecuteNodeExecutor;
+import org.onap.ccsdk.sli.core.sli.provider.base.SvcLogicExpressionResolver;
+
+import junit.framework.TestCase;
+
+public class PluginTest extends TestCase {
+
+ // The existing plugins work just like a VoidDummyPlugin
+ // They will return null simply because they are all void
+ // The attribute emitsOutcome will not be present, the expected outcome is success when no exception is thrown by the plugin
+ public void testOldPlugin() throws Exception {
+ ExecuteNodeExecutor executor = new ExecuteNodeExecutor();
+ SvcLogicJavaPlugin plugin = new SvcLogicJavaPlugin() {
+ public void dummy(Map<String, String> parameters, SvcLogicContext ctx) throws SvcLogicException {
+ return;
+ }
+ };
+
+ Class pluginClass = plugin.getClass();
+ Method pluginMethod = pluginClass.getMethod("dummy", Map.class, SvcLogicContext.class);
+ Map<String, String> parmMap = new HashMap<String, String>();
+ SvcLogicContext ctx = new SvcLogicContext();
+ Object o = pluginMethod.invoke(plugin, parmMap, ctx);
+
+ SvcLogicGraph graph = new SvcLogicGraph();
+ SvcLogicNode node = new SvcLogicNode(1, "return", graph);
+ String emitsOutcome = SvcLogicExpressionResolver.evaluate(node.getAttribute("emitsOutcome"), node, ctx);
+ String outValue = executor.mapOutcome(o, emitsOutcome);
+ assertEquals(SvcLogicConstants.SUCCESS,outValue);
+ }
+
+ //Newer plugins can set the attribute emitsOutcome to true, if so they should return a string
+ //The string represents the outcome value
+ public void testNewPlugin() throws Exception {
+ ExecuteNodeExecutor executor = new ExecuteNodeExecutor();
+ SvcLogicJavaPlugin plugin = new LunchSelectorPlugin();
+
+ Class pluginClass = plugin.getClass();
+ Method pluginMethod = pluginClass.getMethod("selectLunch", Map.class, SvcLogicContext.class);
+
+ Map<String, String> parmMap = new HashMap<String, String>();
+ SvcLogicContext ctx = new SvcLogicContext();
+
+ parmMap.put("day", "monday");
+ Object o = pluginMethod.invoke(plugin, parmMap, ctx);
+ SvcLogicGraph graph = new SvcLogicGraph();
+ SvcLogicNode node = new SvcLogicNode(1, "return", graph);
+ node.setAttribute("emitsOutcome", "true");
+ String emitsOutcome = SvcLogicExpressionResolver.evaluate(node.getAttribute("emitsOutcome"), node, ctx);
+ String outValue = executor.mapOutcome(o, emitsOutcome);
+ assertEquals("pizza", outValue);
+
+ parmMap.put("day", "tuesday");
+ outValue = (String) pluginMethod.invoke(plugin, parmMap, ctx);
+ o = pluginMethod.invoke(plugin, parmMap, ctx);
+ outValue = executor.mapOutcome(o, emitsOutcome);
+ assertEquals("soup",outValue);
+
+ }
+
+ //APPC had some legacy plugins returning objects which should not be treated as outcomes
+ //The attribute emitsOutcome will not be set
+ //The outcome should be success as it has always been
+ public void testObjPlugin() throws Exception{
+ ExecuteNodeExecutor executor = new ExecuteNodeExecutor();
+ SvcLogicJavaPlugin plugin = new LunchSelectorPlugin();
+
+ Class pluginClass = plugin.getClass();
+ Method pluginMethod = pluginClass.getMethod("makeLunch", Map.class, SvcLogicContext.class);
+
+ Map<String, String> parmMap = new HashMap<String, String>();
+ SvcLogicContext ctx = new SvcLogicContext();
+ Object o = pluginMethod.invoke(plugin, parmMap, ctx);
+ SvcLogicGraph graph = new SvcLogicGraph();
+ SvcLogicNode node = new SvcLogicNode(1, "return", graph);
+ String emitsOutcome = SvcLogicExpressionResolver.evaluate(node.getAttribute("emitsOutcome"), node, ctx);
+ String outValue = executor.mapOutcome(o, emitsOutcome);
+ assertEquals(SvcLogicConstants.SUCCESS,outValue);
+ }
+
+}
diff --git a/core/sli/provider-base/src/test/java/org/onap/ccsdk/sli/core/sli/provider/base/SetNodeExecutorTest.java b/core/sli/provider-base/src/test/java/org/onap/ccsdk/sli/core/sli/provider/base/SetNodeExecutorTest.java
new file mode 100644
index 000000000..115989a80
--- /dev/null
+++ b/core/sli/provider-base/src/test/java/org/onap/ccsdk/sli/core/sli/provider/base/SetNodeExecutorTest.java
@@ -0,0 +1,220 @@
+package org.onap.ccsdk.sli.core.sli.provider.base;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import java.util.LinkedList;
+import org.junit.Test;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicGraph;
+import org.onap.ccsdk.sli.core.sli.SvcLogicNode;
+import org.onap.ccsdk.sli.core.sli.SvcLogicParser;
+import org.onap.ccsdk.sli.core.sli.provider.base.SetNodeExecutor;
+
+public class SetNodeExecutorTest {
+ @Test
+ public void clearProperties() throws Exception {
+ SetNodeExecutor sne = new SetNodeExecutor();
+ SvcLogicContext ctx = new SvcLogicContext();
+
+ SvcLogicParser slp = new SvcLogicParser();
+ LinkedList<SvcLogicGraph> graph = slp.parse("src/test/resources/clearValues.xml");
+ SvcLogicNode root = graph.getFirst().getRootNode();
+ SvcLogicNode nodeOne = root.getOutcomeValue("1");
+ SvcLogicNode nodeTwo = root.getOutcomeValue("2");
+
+ sne.execute(nodeOne, ctx);
+ sne.execute(nodeTwo, ctx);
+
+ assertNull(ctx.getAttribute("si.field1"));
+ assertNull(ctx.getAttribute("si.field2"));
+ assertNull(ctx.getAttribute("si.field3"));
+ assertNull(ctx.getAttribute("si.subarray[0]"));
+ assertNull(ctx.getAttribute("si.subarray[1]"));
+ assertNull(ctx.getAttribute("si.subarray[2]"));
+ assertNull(ctx.getAttribute("si.subarray_length"));
+ assertEquals("6", ctx.getAttribute("search1"));
+ assertEquals("KeepMe!", ctx.getAttribute("simonSays"));
+ }
+
+ @Test
+ public void clearMultipleArrayProperties() throws Exception {
+ SetNodeExecutor sne = new SetNodeExecutor();
+ SvcLogicContext ctx = new SvcLogicContext();
+
+ SvcLogicParser slp = new SvcLogicParser();
+ LinkedList<SvcLogicGraph> graph = slp.parse("src/test/resources/clearMultipleArrayValues.xml");
+ SvcLogicNode root = graph.getFirst().getRootNode();
+ SvcLogicNode nodeOne = root.getOutcomeValue("1");
+ SvcLogicNode nodeTwo = root.getOutcomeValue("2");
+
+ sne.execute(nodeOne, ctx);
+ sne.execute(nodeTwo, ctx);
+
+ assertNull(ctx.getAttribute("si[0].field1"));
+ assertNull(ctx.getAttribute("si[1].field2"));
+ assertNull(ctx.getAttribute("si[2].field3"));
+ assertNull(ctx.getAttribute("si_length"));
+ assertNull(ctx.getAttribute("si[0].subarray[0]"));
+ assertNull(ctx.getAttribute("si[0].subarray[1]"));
+ assertNull(ctx.getAttribute("si[0].subarray[2]"));
+ assertNull(ctx.getAttribute("si[0].subarray_length"));
+ assertEquals("6", ctx.getAttribute("search1"));
+ assertEquals("KeepMe!", ctx.getAttribute("simonSays"));
+ }
+
+ @Test
+ public void clearSingleArrayProperties() throws Exception {
+ SetNodeExecutor sne = new SetNodeExecutor();
+ SvcLogicContext ctx = new SvcLogicContext();
+
+ SvcLogicParser slp = new SvcLogicParser();
+ LinkedList<SvcLogicGraph> graph = slp.parse("src/test/resources/clearSingleArrayValues.xml");
+ SvcLogicNode root = graph.getFirst().getRootNode();
+ SvcLogicNode nodeOne = root.getOutcomeValue("1");
+ SvcLogicNode nodeTwo = root.getOutcomeValue("2");
+
+ sne.execute(nodeOne, ctx);
+ sne.execute(nodeTwo, ctx);
+
+ assertNull(ctx.getAttribute("si[0].field1"));
+ assertNull(ctx.getAttribute("si[0].subarray[0]"));
+ assertNull(ctx.getAttribute("si[0].subarray[1]"));
+ assertNull(ctx.getAttribute("si[0].subarray[2]"));
+ assertNull(ctx.getAttribute("si[0].subarray_length"));
+
+ // TODO: This is just setting up elements as null but note reducing the size of Array.
+ assertEquals("3",ctx.getAttribute("si_length"));
+
+ assertEquals("2",ctx.getAttribute("si[1].field2"));
+ assertEquals("3", ctx.getAttribute("si[2].field3"));
+ assertEquals("6", ctx.getAttribute("search1"));
+ assertEquals("KeepMe!", ctx.getAttribute("simonSays"));
+ }
+
+ @Test
+ public void clearSingleSubArrayProperties() throws Exception {
+ SetNodeExecutor sne = new SetNodeExecutor();
+ SvcLogicContext ctx = new SvcLogicContext();
+
+ SvcLogicParser slp = new SvcLogicParser();
+ LinkedList<SvcLogicGraph> graph = slp.parse("src/test/resources/clearSingleSubArrayValues.xml");
+ SvcLogicNode root = graph.getFirst().getRootNode();
+ SvcLogicNode nodeOne = root.getOutcomeValue("1");
+ SvcLogicNode nodeTwo = root.getOutcomeValue("2");
+
+ sne.execute(nodeOne, ctx);
+ sne.execute(nodeTwo, ctx);
+
+ assertEquals("1",ctx.getAttribute("tmp.si[0].field1"));
+ assertEquals("2",ctx.getAttribute("tmp.si[1].field2"));
+ assertEquals("3", ctx.getAttribute("tmp.si[2].field3"));
+ assertEquals("3", ctx.getAttribute("tmp.si_length"));
+
+ assertEquals("a",ctx.getAttribute("tmp.si[0].subarray[0]"));
+
+ // TODO: This is setting up element as Empty instead null
+ //assertNull(ctx.getAttribute("tmp.si[0].subarray[1]"));
+ assertEquals("", ctx.getAttribute("tmp.si[0].subarray[1]"));
+
+ assertEquals("c", ctx.getAttribute("tmp.si[0].subarray[2]"));
+ assertEquals("3", ctx.getAttribute("tmp.si[0].subarray_length"));
+
+ assertEquals("x",ctx.getAttribute("tmp.si[1].subarray[0]"));
+ assertEquals("y",ctx.getAttribute("tmp.si[1].subarray[1]"));
+ assertEquals("z", ctx.getAttribute("tmp.si[1].subarray[2]"));
+ assertEquals("3", ctx.getAttribute("tmp.si[1].subarray_length"));
+
+ assertEquals("6", ctx.getAttribute("search1"));
+ assertEquals("KeepMe!", ctx.getAttribute("simonSays"));
+ }
+
+ @Test
+ public void clearSubArrayProperties() throws Exception {
+ SetNodeExecutor sne = new SetNodeExecutor();
+ SvcLogicContext ctx = new SvcLogicContext();
+
+ SvcLogicParser slp = new SvcLogicParser();
+ LinkedList<SvcLogicGraph> graph = slp.parse("src/test/resources/clearSubArrayValues.xml");
+ SvcLogicNode root = graph.getFirst().getRootNode();
+ SvcLogicNode nodeOne = root.getOutcomeValue("1");
+ SvcLogicNode nodeTwo = root.getOutcomeValue("2");
+
+ sne.execute(nodeOne, ctx);
+ sne.execute(nodeTwo, ctx);
+
+ assertEquals("1", ctx.getAttribute("si[0].field1"));
+ assertEquals("2",ctx.getAttribute("si[1].field2"));
+ assertEquals("3", ctx.getAttribute("si[2].field3"));
+ assertEquals("3", ctx.getAttribute("si_length"));
+ assertNull(ctx.getAttribute("si[0].subarray[0]"));
+ assertNull(ctx.getAttribute("si[0].subarray[1]"));
+ assertNull(ctx.getAttribute("si[0].subarray[2]"));
+ assertNull(ctx.getAttribute("si[0].subarray_length"));
+
+ assertEquals("6", ctx.getAttribute("search1"));
+ assertEquals("KeepMe!", ctx.getAttribute("simonSays"));
+ }
+
+ @Test
+ public void arrayPattern() {
+ SetNodeExecutor sne = new SetNodeExecutor();
+ String source = "one.two[0].three[0].four";
+ assertEquals("one.two.three.four", source.replaceAll(sne.arrayPattern, ""));
+ }
+
+ @Test
+ public void subtreeCopy() throws Exception {
+ SetNodeExecutor sne = new SetNodeExecutor();
+ SvcLogicContext ctx = new SvcLogicContext();
+
+ SvcLogicParser slp = new SvcLogicParser();
+ LinkedList<SvcLogicGraph> graph = slp.parse("src/test/resources/copyValues.xml");
+ SvcLogicNode root = graph.getFirst().getRootNode();
+ SvcLogicNode nodeOne = root.getOutcomeValue("1");
+ SvcLogicNode nodeTwo = root.getOutcomeValue("2");
+
+ sne.execute(nodeOne, ctx);
+ sne.execute(nodeTwo, ctx);
+
+ assertEquals("1", ctx.getAttribute("si.field1"));
+ assertEquals("2", ctx.getAttribute("si.field2"));
+ assertEquals("3", ctx.getAttribute("si.field3"));
+ assertEquals("1", ctx.getAttribute("rootTwo.field1"));
+ assertEquals("2", ctx.getAttribute("rootTwo.field2"));
+ assertEquals("3", ctx.getAttribute("rootTwo.field3"));
+ }
+
+ @Test
+ public void clearNestedSubArrayProperties() throws Exception {
+ SetNodeExecutor sne = new SetNodeExecutor();
+ SvcLogicContext ctx = new SvcLogicContext();
+
+ SvcLogicParser slp = new SvcLogicParser();
+ LinkedList<SvcLogicGraph> graph = slp.parse("src/test/resources/clearNestedSubArrayValues.xml");
+ SvcLogicNode root = graph.getFirst().getRootNode();
+ SvcLogicNode nodeOne = root.getOutcomeValue("1");
+ SvcLogicNode nodeTwo = root.getOutcomeValue("2");
+
+ sne.execute(nodeOne, ctx);
+ sne.execute(nodeTwo, ctx);
+
+ assertEquals("1", ctx.getAttribute("tmp.si[0].field1"));
+ assertEquals("2",ctx.getAttribute("tmp.si[1].field2"));
+ assertEquals("3", ctx.getAttribute("tmp.si[2].field3"));
+ assertEquals("3", ctx.getAttribute("tmp.si_length"));
+
+ assertNull(ctx.getAttribute("tmp.si[0].subarray[0]"));
+ assertNull(ctx.getAttribute("tmp.si[0].subarray[1]"));
+ assertNull(ctx.getAttribute("tmp.si[0].subarray[2]"));
+ assertNull(ctx.getAttribute("tmp.si[0].subarray_length"));
+
+ assertEquals("x", ctx.getAttribute("tmp.si[1].subarray[0]"));
+ assertEquals("y",ctx.getAttribute("tmp.si[1].subarray[1]"));
+ assertEquals("z", ctx.getAttribute("tmp.si[1].subarray[2]"));
+ assertEquals("3", ctx.getAttribute("tmp.si[1].subarray_length"));
+
+ assertEquals("6", ctx.getAttribute("search1"));
+ assertEquals("KeepMe!", ctx.getAttribute("simonSays"));
+ }
+
+}
diff --git a/core/sli/provider-base/src/test/java/org/onap/ccsdk/sli/core/sli/provider/base/SvcLogicExpressionResolverTest.java b/core/sli/provider-base/src/test/java/org/onap/ccsdk/sli/core/sli/provider/base/SvcLogicExpressionResolverTest.java
new file mode 100644
index 000000000..054b38d0f
--- /dev/null
+++ b/core/sli/provider-base/src/test/java/org/onap/ccsdk/sli/core/sli/provider/base/SvcLogicExpressionResolverTest.java
@@ -0,0 +1,280 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.sli.provider.base;
+
+import java.io.BufferedReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.LinkedList;
+
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicExprListener;
+import org.onap.ccsdk.sli.core.sli.SvcLogicExpression;
+import org.onap.ccsdk.sli.core.sli.SvcLogicExpressionFactory;
+import org.onap.ccsdk.sli.core.sli.SvcLogicGraph;
+import org.onap.ccsdk.sli.core.sli.SvcLogicNode;
+import org.onap.ccsdk.sli.core.sli.provider.base.SvcLogicExpressionResolver;
+import org.onap.ccsdk.sli.core.sli.SvcLogicParser;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import junit.framework.Assert;
+import junit.framework.TestCase;
+
+public class SvcLogicExpressionResolverTest extends TestCase {
+
+
+ private static final Logger LOG = LoggerFactory
+ .getLogger(SvcLogicExpressionResolver.class);
+
+ public void testEvaluate()
+ {
+ InputStream testStr = getClass().getResourceAsStream("/expression.tests");
+ BufferedReader testsReader = new BufferedReader(new InputStreamReader(testStr));
+
+ try
+ {
+ SvcLogicContext ctx = new SvcLogicContext();
+ SvcLogicGraph graph = new SvcLogicGraph();
+ SvcLogicNode node = new SvcLogicNode(1, "return", graph);
+ graph.setRootNode(node);
+
+ String line = null;
+ int lineNo = 0;
+ while ((line = testsReader.readLine()) != null) {
+ ++lineNo;
+ if (line.startsWith("#"))
+ {
+ String testExpr = line.trim().substring(1).trim();
+ String[] nameValue = testExpr.split("=");
+ String name = nameValue[0].trim();
+ String value = nameValue[1].trim();
+
+ if (name.startsWith("$"))
+ {
+ LOG.info("Setting context attribute "+name+" = "+value);
+ ctx.setAttribute(name.substring(1), value);
+ }
+ else
+ {
+
+ LOG.info("Setting node attribute "+name+" = "+value);
+ node.setAttribute(name, value);
+
+ }
+ }
+ else
+ {
+ // if the line contains #, what comes before is the expression to evaluate, and what comes after
+ // is the expected value
+ String[] substrings = line.split("#");
+ String expectedValue = substrings.length > 1 ? substrings[1].trim() : null;
+ String testExpr = substrings[0].trim();
+
+ LOG.info("Parsing expression "+testExpr);
+ SvcLogicExpression expr = SvcLogicExpressionFactory.parse(testExpr);
+ if (expr == null)
+ {
+ fail("Unable to parse expression "+testExpr);
+ }
+ else
+ {
+ LOG.info("Evaluating parsed expression "+expr.asParsedExpr());
+ String exprValue = SvcLogicExpressionResolver.evaluate(expr, node, ctx);
+ if (exprValue == null)
+ {
+ fail("Unable to evaluate expression "+testExpr);
+ }
+ else
+ {
+ LOG.info("Expression " + testExpr + " evaluates to " + exprValue);
+ if (expectedValue != null) {
+ Assert.assertEquals("Line " + lineNo + ": " + testExpr, expectedValue, exprValue);
+ }
+ }
+ }
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ LOG.error("Caught exception", e);
+ fail("Caught exception");
+ }
+ }
+
+ public void testSvcLogicExpressions() throws Exception {
+ SwitchNodeExecutor switchNodeExecutor = new SwitchNodeExecutor();
+ SetNodeExecutor setNodeExecutor = new SetNodeExecutor();
+ SvcLogicContext ctx = new SvcLogicContext();
+ SvcLogicParser slp = new SvcLogicParser();
+ LinkedList<SvcLogicGraph> graph = slp.parse("src/test/resources/expressions.xml");
+ SvcLogicNode root = graph.getFirst().getRootNode();
+//Test a set node that makes use of arithmetic operations
+/*
+<set>
+ <parameter name='add' value='`1 + 1`' />
+ <parameter name='sub' value='`2 - 1`' />
+ <parameter name='div' value='`6 / 2`' />
+ <parameter name='multi' value='`2 * 2`' />
+ <parameter name='addDoubleQuotes' value="`1 + 1`" />
+ <parameter name='subDoubleQuotes' value="`2 - 1`" />
+ <parameter name='divDoubleQuotes' value="`6 / 2`" />
+ <parameter name='multiDoubleQuotes' value="`2 * 2`" />
+</set>
+*/
+//the node matching outcome value 1 comes from parsing the block of xml above
+ ctx.setAttribute("a", "5");
+ ctx.setAttribute("b", "3");
+ setNodeExecutor.execute(root.getOutcomeValue("1"), ctx);
+ assertEquals("2", ctx.getAttribute("add"));
+ assertEquals("1", ctx.getAttribute("sub"));
+ assertEquals("3", ctx.getAttribute("div"));
+ assertEquals("4", ctx.getAttribute("multi"));
+ assertEquals("2", ctx.getAttribute("addDoubleQuotes"));
+ assertEquals("1", ctx.getAttribute("subDoubleQuotes"));
+ assertEquals("3", ctx.getAttribute("divDoubleQuotes"));
+ assertEquals("4", ctx.getAttribute("multiDoubleQuotes"));
+
+//Test a set node that makes use of string concatenation
+/*
+<set>
+ <parameter name='varA' value='`$a + $b`' />
+ <parameter name='varB' value='`$a + &apos;literal&apos; `' />
+ <parameter name='varC' value='`&apos;literal&apos; + $b `' />
+ <parameter name='varD' value='`&apos;too&apos; + &apos;literal&apos;`' />
+ <parameter name='varADoubleQuotes' value="`$a + $b`" />
+ <parameter name='varBDoubleQuotes' value="`$a +'literal' `" />
+ <parameter name='varCDoubleQuotes' value="`'literal' + $b `" />
+ <parameter name='varDDoubleQuotes' value="`'too' + 'literal'`" />
+</set>
+*/
+//the node matching outcome value 2 comes from parsing the block of xml above
+ ctx.setAttribute("a", "cat");
+ ctx.setAttribute("b", "dog");
+ setNodeExecutor.execute(root.getOutcomeValue("2"), ctx);
+ assertEquals("catdog", ctx.getAttribute("varA"));
+ assertEquals("catliteral", ctx.getAttribute("varB"));
+ assertEquals("literaldog", ctx.getAttribute("varC"));
+ assertEquals("tooliteral", ctx.getAttribute("varD"));
+ assertEquals("catdog", ctx.getAttribute("varADoubleQuotes"));
+ assertEquals("catliteral", ctx.getAttribute("varBDoubleQuotes"));
+ assertEquals("literaldog", ctx.getAttribute("varCDoubleQuotes"));
+ assertEquals("tooliteral", ctx.getAttribute("varDDoubleQuotes"));
+
+//Shows how backticks interact with + operator
+/*
+<set>
+ <parameter name='testOne' value='`1 + 1`' />
+ <parameter name='testThree' value='"1" +"1"' />
+ <parameter name='testFour' value='`$portNumber + $slot + $shelf`' />
+ <parameter name='testOneDoubleQuotes' value="`1 + 1`" />
+ <parameter name='testThreeDoubleQuotes' value="'1' +'1'" />
+ <parameter name='testFourDoubleQuotes' value="`$portNumber + $slot + $shelf`" />
+</set>
+*/
+//the node matching outcome value 3 comes from parsing the block of xml above
+ ctx.setAttribute("portNumber", "2");
+ ctx.setAttribute("slot", "3");
+ ctx.setAttribute("shelf", "1");
+
+ setNodeExecutor.execute(root.getOutcomeValue("3"), ctx);
+ assertEquals("2", ctx.getAttribute("testOne"));
+ assertEquals("\"1\" +\"1\"", ctx.getAttribute("testThree"));
+ assertEquals("6", ctx.getAttribute("testFour"));
+ assertEquals("2", ctx.getAttribute("testOneDoubleQuotes"));
+ assertEquals("'1' +'1'", ctx.getAttribute("testThreeDoubleQuotes"));
+ assertEquals("6", ctx.getAttribute("testFourDoubleQuotes"));
+
+ ctx.setAttribute("a", "5");
+ ctx.setAttribute("b", "3");
+
+ // series of switch statements showing and or != > < >= == <=
+ // the XML for the node is commented above the line that evaluates that node, the switch statements are single line
+
+ //<switch test="`'PIZZA' == 'NOTPIZZA' or $a != $b`" />
+ assertEquals("true",switchNodeExecutor.evaluateNodeTest(root.getOutcomeValue("4"), ctx));
+
+ //<switch test="`'PIZZA' == 'PIZZA' and $a != $b`" />
+ assertEquals("true",switchNodeExecutor.evaluateNodeTest(root.getOutcomeValue("5"), ctx));
+
+ //<switch test="`'PIZZA' == 'NOTPIZZA' or $a &gt;= $b`" />
+ assertEquals("true",switchNodeExecutor.evaluateNodeTest(root.getOutcomeValue("6"), ctx));
+
+ //<switch test="`'PIZZA' == 'PIZZA' and $b &lt; $a`" />
+ assertEquals("true",switchNodeExecutor.evaluateNodeTest(root.getOutcomeValue("7"), ctx));
+
+ //<switch test="`'PIZZA' == 'PIZZA'`" />
+ assertEquals("true",switchNodeExecutor.evaluateNodeTest(root.getOutcomeValue("8"), ctx));
+
+ //<switch test="`$a == $b`" />
+ assertEquals("false",switchNodeExecutor.evaluateNodeTest(root.getOutcomeValue("9"), ctx));
+
+ //<switch test="`'PIZZA' == 'NOTPIZZA'`" />
+ assertEquals("false",switchNodeExecutor.evaluateNodeTest(root.getOutcomeValue("10"), ctx));
+
+ //<switch test="`'PIZZA' != 'PIZZA'`" />
+ assertEquals("false",switchNodeExecutor.evaluateNodeTest(root.getOutcomeValue("11"), ctx));
+
+ //<switch test="`'PIZZA' != 'NOTPIZZA'`" />
+ assertEquals("true",switchNodeExecutor.evaluateNodeTest(root.getOutcomeValue("12"), ctx));
+
+ //<switch test='`$a != $b`' />
+ assertEquals("true",switchNodeExecutor.evaluateNodeTest(root.getOutcomeValue("13"), ctx));
+
+ //<switch test='`1 &lt; 2`' />
+ assertEquals("true",switchNodeExecutor.evaluateNodeTest(root.getOutcomeValue("14"), ctx));
+
+ //<switch test='`2 &lt;= 2`' />
+ assertEquals("true",switchNodeExecutor.evaluateNodeTest(root.getOutcomeValue("15"), ctx));
+
+ //<switch test='`3 &gt; 2`' />
+ assertEquals("true",switchNodeExecutor.evaluateNodeTest(root.getOutcomeValue("16"), ctx));
+
+ //<switch test='`2 &gt;= 2`' />
+ assertEquals("true",switchNodeExecutor.evaluateNodeTest(root.getOutcomeValue("17"), ctx));
+
+ // Series of switch statements that show the effect of using backticks
+
+ ctx.setAttribute("literalStartingWithDollarSign", "DONT READ ME!");
+ //<switch test='$literalStartingWithDollarSign'/>
+ assertEquals("$literalStartingWithDollarSign",switchNodeExecutor.evaluateNodeTest(root.getOutcomeValue("18"), ctx));
+
+ ctx.setAttribute("dollarSignFollowedByVariableSurroundedinBackticks", "README");
+ //<switch test='$literalStartingWithDollarSign'/>
+ assertEquals("README",switchNodeExecutor.evaluateNodeTest(root.getOutcomeValue("19"), ctx));
+
+ ctx.setAttribute("a", "2");
+ ctx.setAttribute("b", "2");
+ //<switch test='`$a == $b`' />
+ assertEquals("true",switchNodeExecutor.evaluateNodeTest(root.getOutcomeValue("20"), ctx));
+
+ //<switch test="`$a == $b`" />
+ assertEquals("true",switchNodeExecutor.evaluateNodeTest(root.getOutcomeValue("21"), ctx));
+
+ //<switch test='$a == $b' />
+ assertEquals("$a == $b",switchNodeExecutor.evaluateNodeTest(root.getOutcomeValue("22"), ctx));
+
+ //<switch test="$a == $b" />
+ assertEquals("$a == $b",switchNodeExecutor.evaluateNodeTest(root.getOutcomeValue("23"), ctx));
+ }
+}
diff --git a/core/sli/provider-base/src/test/java/org/onap/ccsdk/sli/core/sli/recording/TestFileRecorder.java b/core/sli/provider-base/src/test/java/org/onap/ccsdk/sli/core/sli/recording/TestFileRecorder.java
new file mode 100644
index 000000000..d0cc83182
--- /dev/null
+++ b/core/sli/provider-base/src/test/java/org/onap/ccsdk/sli/core/sli/recording/TestFileRecorder.java
@@ -0,0 +1,49 @@
+/**
+ *
+ */
+package org.onap.ccsdk.sli.core.sli.recording;
+
+import static org.junit.Assert.fail;
+
+import java.util.HashMap;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+
+/**
+ * @author dt5972
+ *
+ */
+public class TestFileRecorder {
+ private FileRecorder recorder;
+
+ @Before
+ public void setUp() {
+ recorder = new FileRecorder();
+ }
+
+ /**
+ * Test method for
+ * {@link org.onap.ccsdk.sli.core.sli.recording.FileRecorder#record(java.util.Map)}.
+ */
+ @Test
+ public void testRecord() {
+ HashMap<String, String> parms = new HashMap<>();
+ parms.put("file", "/dev/null");
+ parms.put("field1", "hi");
+ try {
+ recorder.record(parms);
+ } catch (SvcLogicException e) {
+ fail("Caught SvcLogicException : " + e.getMessage());
+ }
+ }
+
+ @Test(expected = Exception.class)
+ public void testRecordForEmptyFileName() throws Exception {
+ HashMap<String, String> parms = new HashMap<>();
+ parms.put("field1", "hi");
+ recorder.record(parms);
+ }
+
+}
diff --git a/core/sli/provider-base/src/test/java/org/onap/ccsdk/sli/core/sli/recording/TestSlf4jRecorder.java b/core/sli/provider-base/src/test/java/org/onap/ccsdk/sli/core/sli/recording/TestSlf4jRecorder.java
new file mode 100644
index 000000000..c696f25b5
--- /dev/null
+++ b/core/sli/provider-base/src/test/java/org/onap/ccsdk/sli/core/sli/recording/TestSlf4jRecorder.java
@@ -0,0 +1,33 @@
+/**
+ *
+ */
+package org.onap.ccsdk.sli.core.sli.recording;
+
+import static org.junit.Assert.*;
+import java.util.HashMap;
+import org.junit.Test;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+
+/**
+ * @author dt5972
+ *
+ */
+public class TestSlf4jRecorder {
+
+ /**
+ * Test method for {@link org.onap.ccsdk.sli.core.sli.recording.Slf4jRecorder#record(java.util.Map)}.
+ */
+ @Test
+ public void testRecord() {
+ Slf4jRecorder recorder = new Slf4jRecorder();
+
+ HashMap<String,String> parms = new HashMap<>();
+ parms.put("field1","hi");
+ try {
+ recorder.record(parms);
+ } catch (SvcLogicException e) {
+ fail("Caught SvcLogicException : "+e.getMessage());
+ }
+ }
+
+}
diff --git a/core/sli/provider-base/src/test/resources/breakGraph.xml b/core/sli/provider-base/src/test/resources/breakGraph.xml
new file mode 100644
index 000000000..e2b89e84f
--- /dev/null
+++ b/core/sli/provider-base/src/test/resources/breakGraph.xml
@@ -0,0 +1,26 @@
+<service-logic
+ xmlns='http://www.onap.org/sdnc/svclogic'
+ xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xsi:schemaLocation='http://www.onap.org/sdnc/svclogic ./svclogic.xsd' module='JUNIT' version='1'>
+ <method rpc='BREAK' mode='sync'>
+ <block>
+ <set>
+ <parameter name='a' value='0' />
+ </set>
+ <for index='idx' start='0' end='999' >
+ <record plugin="org.onap.ccsdk.sli.core.sli.recording.Slf4jRecorder">
+ <parameter name="logger" value="message-log" />
+ <parameter name="level" value="error" />
+ <parameter name="field1" value="`$idx`" />
+ </record>
+ <set>
+ <parameter name='a' value='`$a + 1`' />
+ </set>
+ <switch test="`$idx == 2`">
+ <outcome value='true'>
+ <break/>
+ </outcome>
+ </switch>
+ </for>
+ </block>
+ </method>
+</service-logic> \ No newline at end of file
diff --git a/core/sli/provider-base/src/test/resources/clearMultipleArrayValues.xml b/core/sli/provider-base/src/test/resources/clearMultipleArrayValues.xml
new file mode 100644
index 000000000..8f40058f1
--- /dev/null
+++ b/core/sli/provider-base/src/test/resources/clearMultipleArrayValues.xml
@@ -0,0 +1,23 @@
+<service-logic
+ xmlns='http://www.onap.org/sdnc/svclogic'
+ xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xsi:schemaLocation='http://www.onap.org/sdnc/svclogic ./svclogic.xsd' module='TEST-DG' version='1.0.0'>
+ <method rpc='test-dg' mode='sync'>
+ <block>
+ <set>
+ <parameter name='si[0].field1' value='1' />
+ <parameter name='si[1].field2' value='2' />
+ <parameter name='si[2].field3' value='3' />
+ <parameter name='si_length' value='3' />
+ <parameter name='si[0].subarray[0]' value='a' />
+ <parameter name='si[0].subarray[1]' value='b' />
+ <parameter name='si[0].subarray[2]' value='c' />
+ <parameter name='si[0].subarray_length' value='3' />
+ <parameter name='search1' value='6' />
+ <parameter name='simonSays' value='KeepMe!' />
+ </set>
+ <set>
+ <parameter name='si.' value='' />
+ </set>
+ </block>
+ </method>
+</service-logic> \ No newline at end of file
diff --git a/core/sli/provider-base/src/test/resources/clearNestedSubArrayValues.xml b/core/sli/provider-base/src/test/resources/clearNestedSubArrayValues.xml
new file mode 100644
index 000000000..a80b3e56c
--- /dev/null
+++ b/core/sli/provider-base/src/test/resources/clearNestedSubArrayValues.xml
@@ -0,0 +1,27 @@
+<service-logic
+ xmlns='http://www.onap.org/sdnc/svclogic'
+ xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xsi:schemaLocation='http://www.onap.org/sdnc/svclogic ./svclogic.xsd' module='TEST-DG' version='1.0.0'>
+ <method rpc='test-dg' mode='sync'>
+ <block>
+ <set>
+ <parameter name='tmp.si[0].field1' value='1' />
+ <parameter name='tmp.si[1].field2' value='2' />
+ <parameter name='tmp.si[2].field3' value='3' />
+ <parameter name='tmp.si_length' value='3' />
+ <parameter name='tmp.si[0].subarray[0]' value='a' />
+ <parameter name='tmp.si[0].subarray[1]' value='b' />
+ <parameter name='tmp.si[0].subarray[2]' value='c' />
+ <parameter name='tmp.si[0].subarray_length' value='3' />
+ <parameter name='tmp.si[1].subarray[0]' value='x' />
+ <parameter name='tmp.si[1].subarray[1]' value='y' />
+ <parameter name='tmp.si[1].subarray[2]' value='z' />
+ <parameter name='tmp.si[1].subarray_length' value='3' />
+ <parameter name='search1' value='6' />
+ <parameter name='simonSays' value='KeepMe!' />
+ </set>
+ <set>
+ <parameter name='tmp.si[0].subarray.' value='' />
+ </set>
+ </block>
+ </method>
+</service-logic> \ No newline at end of file
diff --git a/core/sli/provider-base/src/test/resources/clearSingleArrayValues.xml b/core/sli/provider-base/src/test/resources/clearSingleArrayValues.xml
new file mode 100644
index 000000000..56781a066
--- /dev/null
+++ b/core/sli/provider-base/src/test/resources/clearSingleArrayValues.xml
@@ -0,0 +1,23 @@
+<service-logic
+ xmlns='http://www.onap.org/sdnc/svclogic'
+ xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xsi:schemaLocation='http://www.onap.org/sdnc/svclogic ./svclogic.xsd' module='TEST-DG' version='1.0.0'>
+ <method rpc='test-dg' mode='sync'>
+ <block>
+ <set>
+ <parameter name='si[0].field1' value='1' />
+ <parameter name='si[1].field2' value='2' />
+ <parameter name='si[2].field3' value='3' />
+ <parameter name='si_length' value='3' />
+ <parameter name='si[0].subarray[0]' value='a' />
+ <parameter name='si[0].subarray[1]' value='b' />
+ <parameter name='si[0].subarray[2]' value='c' />
+ <parameter name='si[0].subarray_length' value='3' />
+ <parameter name='search1' value='6' />
+ <parameter name='simonSays' value='KeepMe!' />
+ </set>
+ <set>
+ <parameter name='si[0].' value='' />
+ </set>
+ </block>
+ </method>
+</service-logic> \ No newline at end of file
diff --git a/core/sli/provider-base/src/test/resources/clearSingleSubArrayValues.xml b/core/sli/provider-base/src/test/resources/clearSingleSubArrayValues.xml
new file mode 100644
index 000000000..22f14f37b
--- /dev/null
+++ b/core/sli/provider-base/src/test/resources/clearSingleSubArrayValues.xml
@@ -0,0 +1,27 @@
+<service-logic
+ xmlns='http://www.onap.org/sdnc/svclogic'
+ xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xsi:schemaLocation='http://www.onap.org/sdnc/svclogic ./svclogic.xsd' module='TEST-DG' version='1.0.0'>
+ <method rpc='test-dg' mode='sync'>
+ <block>
+ <set>
+ <parameter name='tmp.si[0].field1' value='1' />
+ <parameter name='tmp.si[1].field2' value='2' />
+ <parameter name='tmp.si[2].field3' value='3' />
+ <parameter name='tmp.si_length' value='3' />
+ <parameter name='tmp.si[0].subarray[0]' value='a' />
+ <parameter name='tmp.si[0].subarray[1]' value='b' />
+ <parameter name='tmp.si[0].subarray[2]' value='c' />
+ <parameter name='tmp.si[0].subarray_length' value='3' />
+ <parameter name='tmp.si[1].subarray[0]' value='x' />
+ <parameter name='tmp.si[1].subarray[1]' value='y' />
+ <parameter name='tmp.si[1].subarray[2]' value='z' />
+ <parameter name='tmp.si[1].subarray_length' value='3' />
+ <parameter name='search1' value='6' />
+ <parameter name='simonSays' value='KeepMe!' />
+ </set>
+ <set>
+ <parameter name='tmp.si[0].subarray[1]' value='' />
+ </set>
+ </block>
+ </method>
+</service-logic> \ No newline at end of file
diff --git a/core/sli/provider-base/src/test/resources/clearSubArrayValues.xml b/core/sli/provider-base/src/test/resources/clearSubArrayValues.xml
new file mode 100644
index 000000000..cb25f38af
--- /dev/null
+++ b/core/sli/provider-base/src/test/resources/clearSubArrayValues.xml
@@ -0,0 +1,24 @@
+<service-logic
+ xmlns='http://www.onap.org/sdnc/svclogic'
+ xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xsi:schemaLocation='http://www.onap.org/sdnc/svclogic ./svclogic.xsd' module='TEST-DG' version='1.0.0'>
+ <method rpc='test-dg' mode='sync'>
+ <block>
+ <set>
+ <parameter name='si[0].field1' value='1' />
+ <parameter name='si[1].field2' value='2' />
+ <parameter name='si[2].field3' value='3' />
+ <parameter name='si_length' value='3' />
+ <parameter name='si[0].subarray[0]' value='a' />
+ <parameter name='si[0].subarray[1]' value='b' />
+ <parameter name='si[0].subarray[2]' value='c' />
+ <parameter name='si[0].subarray_length' value='3' />
+ <parameter name='search1' value='6' />
+ <parameter name='simonSays' value='KeepMe!' />
+ </set>
+ <set>
+ <parameter name='si[0].subarray.' value='' />
+ <!-- <parameter name='si.subarray.' value='' /> -->
+ </set>
+ </block>
+ </method>
+</service-logic> \ No newline at end of file
diff --git a/core/sli/provider-base/src/test/resources/clearValues.xml b/core/sli/provider-base/src/test/resources/clearValues.xml
new file mode 100644
index 000000000..dc7f5c8a2
--- /dev/null
+++ b/core/sli/provider-base/src/test/resources/clearValues.xml
@@ -0,0 +1,22 @@
+<service-logic
+ xmlns='http://www.onap.org/sdnc/svclogic'
+ xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xsi:schemaLocation='http://www.onap.org/sdnc/svclogic ./svclogic.xsd' module='TEST-DG' version='1.0.0'>
+ <method rpc='test-dg' mode='sync'>
+ <block>
+ <set>
+ <parameter name='si.field1' value='1' />
+ <parameter name='si.field2' value='2' />
+ <parameter name='si.field3' value='3' />
+ <parameter name='si.subarray[0]' value='a' />
+ <parameter name='si.subarray[1]' value='b' />
+ <parameter name='si.subarray[2]' value='c' />
+ <parameter name='si.subarray_length' value='3' />
+ <parameter name='search1' value='6' />
+ <parameter name='simonSays' value='KeepMe!' />
+ </set>
+ <set>
+ <parameter name='si.' value='' />
+ </set>
+ </block>
+ </method>
+</service-logic> \ No newline at end of file
diff --git a/core/sli/provider-base/src/test/resources/copyValues.xml b/core/sli/provider-base/src/test/resources/copyValues.xml
new file mode 100644
index 000000000..f56f7140a
--- /dev/null
+++ b/core/sli/provider-base/src/test/resources/copyValues.xml
@@ -0,0 +1,16 @@
+<service-logic
+ xmlns='http://www.onap.org/sdnc/svclogic'
+ xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xsi:schemaLocation='http://www.onap.org/sdnc/svclogic ./svclogic.xsd' module='TEST-DG' version='1.0.0'>
+ <method rpc='test-dg' mode='sync'>
+ <block>
+ <set>
+ <parameter name='si.field1' value='1' />
+ <parameter name='si.field2' value='2' />
+ <parameter name='si.field3' value='3' />
+ </set>
+ <set>
+ <parameter name='rootTwo.' value='si.' />
+ </set>
+ </block>
+ </method>
+</service-logic> \ No newline at end of file
diff --git a/core/sli/provider-base/src/test/resources/expression.tests b/core/sli/provider-base/src/test/resources/expression.tests
new file mode 100644
index 000000000..848a0e7a4
--- /dev/null
+++ b/core/sli/provider-base/src/test/resources/expression.tests
@@ -0,0 +1,24 @@
+# $uni-circuit-id = abc123
+# $uni-cir-units = 10
+# value = 1
+# $arg1 = 2
+# $network.name = vCE0001.in
+# $network.segment[0].provider-segmentation-id = 1212
+# $network.segment[1].provider-segmentation-id = 1213
+# $availability-zone = mtsnj-esx-az01
+length($uni-circuit-id) > 0 # true
+$uni-cir-units * 1000 * 100 / 100 # 10000
+$uni-cir-units / 1000 # 0
+$uni-cir-units - 100 # -90
+$uni-cir-units + 100 # 110
+(value * 3 - $arg1 > 0) and (length($uni-circuit-id) == 0) # true
+'pg-'+$network.name # pg-vCE0001.in
+$network.segment[0].provider-segmentation-id # 1212
+toUpperCase($network.name) # VCE0001.IN
+toLowerCase($network.name) # vce0001.in
+toUpperCase(substr($availability-zone, 0, 5)) # MTSNJ
+convertBase(1234, 10) # 1234
+convertBase(10, 16, 10) # 16
+convertBase(ZZ, 36, 10) # 1295
+convertBase(10, 10, 36) # a
+(0 - 1) * $arg1 # -1
diff --git a/core/sli/provider-base/src/test/resources/expressions.xml b/core/sli/provider-base/src/test/resources/expressions.xml
new file mode 100755
index 000000000..79118570c
--- /dev/null
+++ b/core/sli/provider-base/src/test/resources/expressions.xml
@@ -0,0 +1,55 @@
+<service-logic xmlns='http://www.onap.org/sdnc/svclogic' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
+ xsi:schemaLocation='http://www.onap.org/sdnc/svclogic ./svclogic.xsd' module='TEST-DG' version='1.0.0'>
+ <method rpc='test-dg' mode='sync'>
+ <block>
+ <set>
+ <parameter name='add' value='`1 + 1`' />
+ <parameter name='sub' value='`2 - 1`' />
+ <parameter name='div' value='`6 / 2`' />
+ <parameter name='multi' value='`2 * 2`' />
+ <parameter name='addDoubleQuotes' value="`1 + 1`" />
+ <parameter name='subDoubleQuotes' value="`2 - 1`" />
+ <parameter name='divDoubleQuotes' value="`6 / 2`" />
+ <parameter name='multiDoubleQuotes' value="`2 * 2`" />
+ </set>
+ <set>
+ <parameter name='varA' value='`$a + $b`' />
+ <parameter name='varB' value='`$a + &apos;literal&apos; `' />
+ <parameter name='varC' value='`&apos;literal&apos; + $b `' />
+ <parameter name='varD' value='`&apos;too&apos; + &apos;literal&apos;`' />
+ <parameter name='varADoubleQuotes' value="`$a + $b`" />
+ <parameter name='varBDoubleQuotes' value="`$a +'literal' `" />
+ <parameter name='varCDoubleQuotes' value="`'literal' + $b `" />
+ <parameter name='varDDoubleQuotes' value="`'too' + 'literal'`" />
+ </set>
+ <set>
+ <parameter name='testOne' value='`1 + 1`' />
+ <parameter name='testThree' value='"1" +"1"' />
+ <parameter name='testFour' value='`$portNumber + $slot + $shelf`' />
+ <parameter name='testOneDoubleQuotes' value="`1 + 1`" />
+ <parameter name='testThreeDoubleQuotes' value="'1' +'1'" />
+ <parameter name='testFourDoubleQuotes' value="`$portNumber + $slot + $shelf`" />
+ </set>
+ <switch test="`'PIZZA' == 'NOTPIZZA' or $a != $b`" />
+ <switch test="`'PIZZA' == 'PIZZA' and $a != $b`" />
+ <switch test="`'PIZZA' == 'NOTPIZZA' or $a &gt;= $b`" />
+ <switch test="`'PIZZA' == 'PIZZA' and $b &lt; $a`" />
+ <switch test="`'PIZZA' == 'PIZZA'`" />
+ <switch test="`$a == $b`" />
+ <switch test="`'PIZZA' == 'NOTPIZZA'`" />
+ <switch test="`'PIZZA' != 'PIZZA'`" />
+ <switch test="`'PIZZA' != 'NOTPIZZA'`" />
+ <switch test='`$a != $b`' />
+ <switch test='`1 &lt; 2`' />
+ <switch test='`2 &lt;= 2`' />
+ <switch test='`3 &gt; 2`' />
+ <switch test='`2 &gt;= 2`' />
+ <switch test='$literalStartingWithDollarSign' />
+ <switch test='`$dollarSignFollowedByVariableSurroundedinBackticks`' />
+ <switch test='`$a == $b`' />
+ <switch test="`$a == $b`" />
+ <switch test='$a == $b' />
+ <switch test="$a == $b" />
+ </block>
+ </method>
+</service-logic> \ No newline at end of file
diff --git a/core/sli/provider-base/src/test/resources/simplelogger.properties b/core/sli/provider-base/src/test/resources/simplelogger.properties
new file mode 100644
index 000000000..07ab67f70
--- /dev/null
+++ b/core/sli/provider-base/src/test/resources/simplelogger.properties
@@ -0,0 +1,22 @@
+###
+# ============LICENSE_START=======================================================
+# ONAP : CCSDK
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights
+# reserved.
+# ================================================================================
+# 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.
+# ============LICENSE_END=========================================================
+###
+
+org.slf4j.simpleLogger.defaultLogLevel=info
diff --git a/core/sli/provider/pom.xml b/core/sli/provider/pom.xml
new file mode 100755
index 000000000..3d5c389c4
--- /dev/null
+++ b/core/sli/provider/pom.xml
@@ -0,0 +1,144 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>binding-parent</artifactId>
+ <version>2.1.0-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sli-provider</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>bundle</packaging>
+
+ <name>ccsdk-sli-core :: sli :: ${project.artifactId}</name>
+ <description>SLI Provider is the OSGi bundle that exposes the service logic interpreter as a service.</description>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>dblib-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sli-model</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sli-common</artifactId>
+ <version>${project.version}</version>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sli-provider-base</artifactId>
+ <version>${project.version}</version>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>commons-lang</groupId>
+ <artifactId>commons-lang</artifactId>
+ <scope>compile</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.core</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-binding-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.mdsal.binding.model.ietf</groupId>
+ <artifactId>rfc6991</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.bgpcep</groupId>
+ <artifactId>bgp-concepts</artifactId>
+ <scope>provided</scope>
+ <optional>true</optional>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-core-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <!-- Testing Dependencies -->
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.derby</groupId>
+ <artifactId>derby</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <DynamicImport-Package>*</DynamicImport-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ <!-- Jacoco / Sonar -->
+ <plugin>
+ <groupId>org.jacoco</groupId>
+ <artifactId>jacoco-maven-plugin</artifactId>
+ <version>${jacoco.version}</version>
+ <executions>
+ <execution>
+ <id>aggregate-report</id>
+ <phase>verify</phase>
+ <goals>
+ <goal>report-aggregate</goal>
+ </goals>
+ <configuration>
+ <dataFileIncludes>
+ target/code-coverage/jacoco-ut.exec,
+ target/code-coverage/jacoco-it.exec,
+ ../provider-base/target/code-coverage/jacoco-ut.exec,
+ ../provider-base/target/code-coverage/jacoco-it.exec
+ </dataFileIncludes>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/core/sli/provider/src/main/java/org/onap/ccsdk/sli/core/sli/provider/MdsalHelper.java b/core/sli/provider/src/main/java/org/onap/ccsdk/sli/core/sli/provider/MdsalHelper.java
new file mode 100755
index 000000000..d3ab6c33a
--- /dev/null
+++ b/core/sli/provider/src/main/java/org/onap/ccsdk/sli/core/sli/provider/MdsalHelper.java
@@ -0,0 +1,1274 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Modifications Copyright (C) 2018 IBM.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.sli.provider;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.io.PrintStream;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Properties;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Dscp;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddressBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefixBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev180329.RouteDistinguisher;
+import org.opendaylight.yang.gen.v1.urn.opendaylight.params.xml.ns.yang.bgp.types.rev180329.RouteDistinguisherBuilder;
+import org.opendaylight.yangtools.yang.binding.Identifier;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class MdsalHelper {
+
+ private static final Logger LOG = LoggerFactory.getLogger(MdsalHelper.class);
+ private static Properties yangMappingProperties = new Properties();
+ private static final String IP_ADDRESS="IpAddress";
+ private static final String IPV4_ADDRESS="Ipv4Address";
+ private static final String IPV6_ADDRESS="Ipv6Address";
+
+ private static final String IP_PREFIX="IpPrefix";
+ private static final String SETTING_PROPERTY="Setting property ";
+ private static final String BUILDER="-builder";
+
+ @Deprecated
+ public static void setProperties(Properties input) {
+ setYangMappingProperties(input);
+ }
+
+ @Deprecated
+ public static void setYangMappingProperties(Properties properties) {
+ for (Object propNameObj : properties.keySet()) {
+ String propName = (String) propNameObj;
+ MdsalHelper.yangMappingProperties.setProperty(propName, properties.getProperty(propName));
+ }
+ }
+
+ @Deprecated
+ public static void loadProperties(String propertiesFile) {
+ File file = new File(propertiesFile);
+ Properties properties = new Properties();
+ if (file.isFile() && file.canRead()) {
+ try (InputStream input = new FileInputStream(file)) {
+ properties.load(input);
+ MdsalHelper.setYangMappingProperties(properties);
+ LOG.info("Loaded properties from " + propertiesFile);
+ } catch (Exception e) {
+ LOG.error("Failed to load properties " + propertiesFile + "\n", e);
+ }
+ } else {
+ LOG.error("Failed to load the properties file " + propertiesFile + "\n");
+ LOG.error("Either isFile or canRead returned false for " + propertiesFile + "\n");
+ }
+ }
+
+ public static Properties toProperties(Properties props, Object fromObj) {
+ return toProperties(props, fromObj, false);
+ }
+
+ public static Properties toProperties(Properties props, Object fromObj, Boolean useLegacyEnumerationMapping) {
+ Class fromClass = null;
+
+ if (fromObj != null) {
+ fromClass = fromObj.getClass();
+ }
+ return toProperties(props, "", fromObj, fromClass, useLegacyEnumerationMapping);
+ }
+
+ public static Properties toProperties(Properties props, String pfx, Object fromObj) {
+ return toProperties(props, pfx, fromObj, false);
+ }
+
+ public static Properties toProperties(Properties props, String pfx, Object fromObj, Boolean useLegacyEnumerationMapping) {
+ Class fromClass = null;
+
+ if (fromObj != null) {
+ fromClass = fromObj.getClass();
+ }
+
+ return toProperties(props, pfx, fromObj, fromClass, useLegacyEnumerationMapping);
+ }
+
+ public static Properties toProperties(Properties props, String pfx, Object fromObj, Class fromClass) {
+ return toProperties(props, pfx, fromObj, fromClass, false);
+ }
+
+ public static Properties toProperties(Properties props, String pfx, Object fromObj, Class fromClass, Boolean useLegacyEnumerationMapping) {
+
+ if (fromObj == null) {
+ return props;
+ }
+ String simpleTypeName = fromObj.getClass().getTypeName();
+ simpleTypeName = simpleTypeName.substring(simpleTypeName.lastIndexOf(".") + 1);
+
+ if (classHasSpecialHandling(simpleTypeName)) {
+ try {
+
+ Method m = fromClass.getMethod(getStringValueMethod(simpleTypeName), null);
+ boolean isAccessible = m.isAccessible();
+ if (!isAccessible) {
+ m.setAccessible(true);
+ }
+ Object retValue = m.invoke(fromObj);
+ if (retValue != null) {
+ String propVal = null;
+ if (IP_ADDRESS.equals(simpleTypeName) || IP_PREFIX.equals(simpleTypeName)
+ || IPV4_ADDRESS.equals(simpleTypeName) || IPV6_ADDRESS.equals(simpleTypeName)) {
+ propVal = (String) retValue;
+ } else if ("Dscp".equals(simpleTypeName)) {
+ propVal = String.valueOf((short) retValue);
+ } else if ("PortNumber".equals(simpleTypeName)) {
+ propVal = String.valueOf((Integer) retValue);
+ }
+ LOG.debug(SETTING_PROPERTY + pfx + " to " + propVal);
+ props.setProperty(pfx, propVal);
+ }
+ } catch (Exception e) {
+ LOG.error("Caught exception trying to convert value returned by " + fromClass.getName()
+ + ".getValue() to Properties entry", e);
+ }
+ } else if (fromObj instanceof List) {
+ List fromList = (List) fromObj;
+
+ for (int i = 0; i < fromList.size(); i++) {
+ toProperties(props, pfx + "[" + i + "]", fromList.get(i), fromClass, useLegacyEnumerationMapping);
+ }
+ props.setProperty(pfx + "_length", Integer.toString(fromList.size()));
+
+ } else if (isYangGenerated(fromClass)) {
+ // Class is yang generated.
+
+ String propNamePfx = null;
+
+ // If called from a list (so prefix ends in ']'), don't
+ // add class name again
+ if (pfx.endsWith("]")) {
+ propNamePfx = pfx;
+ } else {
+ if ((pfx != null) && (pfx.length() > 0)) {
+ propNamePfx = pfx;
+ } else {
+ propNamePfx = toLowerHyphen(fromClass.getSimpleName());
+ }
+
+ if (propNamePfx.endsWith(BUILDER)) {
+ propNamePfx = propNamePfx.substring(0, propNamePfx.length() - BUILDER.length());
+ }
+
+ if (propNamePfx.endsWith("-impl")) {
+ propNamePfx = propNamePfx.substring(0, propNamePfx.length() - "-impl".length());
+ }
+ }
+
+ // Iterate through getter methods to figure out values we need to
+ // save from
+
+ int numGetters = 0;
+ String lastGetterName = null;
+ String propVal = null;
+
+ for (Method m : fromClass.getMethods()) {
+ if (isGetter(m)) {
+
+ numGetters++;
+ lastGetterName = m.getName();
+
+ Class returnType = m.getReturnType();
+ String fieldName;
+ if (m.getName().startsWith("get")) {
+ fieldName = toLowerHyphen(m.getName().substring(3));
+ } else {
+
+ fieldName = toLowerHyphen(m.getName().substring(2));
+ }
+
+ fieldName = fieldName.substring(0, 1).toLowerCase() + fieldName.substring(1);
+
+ // Is the return type a yang generated class?
+ if (isYangGenerated(returnType)) {
+ // Is it an enum?
+ if (returnType.isEnum()) {
+ // Return type is a typedef. Save its value.
+ try {
+ boolean isAccessible = m.isAccessible();
+ if (!isAccessible) {
+ m.setAccessible(true);
+ }
+
+ Object retValue = m.invoke(fromObj);
+
+ if (!isAccessible) {
+ m.setAccessible(isAccessible);
+ }
+ if (retValue != null) {
+ String propName = propNamePfx + "." + fieldName;
+ if (useLegacyEnumerationMapping) {
+ propVal = retValue.toString();
+ props.setProperty(propName, mapEnumeratedValue(fieldName, propVal));
+ } else {
+ Method method = retValue.getClass().getMethod("getName");
+ String yangValue = (String) method.invoke(retValue);
+ props.setProperty(propName, yangValue);
+ }
+
+ }
+ } catch (Exception e) {
+ LOG.error(
+ "Caught exception trying to convert Yang-generated enum returned by "
+ + fromClass.getName() + "." + m.getName() + "() to Properties entry",
+ e);
+ }
+ } else {
+ try {
+ boolean isAccessible = m.isAccessible();
+ if (!isAccessible) {
+ m.setAccessible(true);
+ }
+ Object retValue = m.invoke(fromObj);
+
+ if (retValue instanceof byte[]) {
+ retValue = new String((byte[]) retValue, "UTF-8");
+ }
+ if (!isAccessible) {
+ m.setAccessible(isAccessible);
+ }
+ if (retValue != null) {
+ toProperties(props, propNamePfx + "." + fieldName, retValue, returnType, useLegacyEnumerationMapping);
+ }
+ } catch (Exception e) {
+
+ if (m.getName().equals("getKey")) {
+ LOG.trace("Caught " + e.getClass().getName()
+ + " exception trying to convert results from getKey() - ignoring");
+ } else {
+ LOG.error("Caught exception trying to convert Yang-generated class returned by"
+ + fromClass.getName() + "." + m.getName() + "() to Properties entry", e);
+ }
+ }
+ }
+ } else if (returnType.equals(Class.class)) {
+
+ } else if (List.class.isAssignableFrom(returnType)) {
+
+ // This getter method returns a list.
+ try {
+ boolean isAccessible = m.isAccessible();
+ if (!isAccessible) {
+ m.setAccessible(true);
+ }
+ Object retList = m.invoke(fromObj);
+ if (!isAccessible) {
+ m.setAccessible(isAccessible);
+ }
+ // Figure out what type of elements are stored in
+ // this array.
+ Type paramType = m.getGenericReturnType();
+ Type elementType = ((ParameterizedType) paramType).getActualTypeArguments()[0];
+ toProperties(props, propNamePfx + "." + fieldName, retList, (Class) elementType, useLegacyEnumerationMapping);
+ } catch (Exception e) {
+ LOG.error("Caught exception trying to convert List returned by " + fromClass.getName() + "."
+ + m.getName() + "() to Properties entry", e);
+ }
+
+ } else {
+
+ // Method returns something that is not a List and not
+ // yang-generated.
+ // Save its value
+ try {
+ String propName = propNamePfx + "." + fieldName;
+ boolean isAccessible = m.isAccessible();
+ if (!isAccessible) {
+ m.setAccessible(true);
+ }
+ Object propValObj = m.invoke(fromObj);
+ if (!isAccessible) {
+ m.setAccessible(isAccessible);
+ }
+
+ if (propValObj != null) {
+ if (propValObj instanceof byte[]) {
+ propVal = new String((byte[]) propValObj, "UTF-8");
+ } else {
+ propVal = propValObj.toString();
+ }
+ LOG.debug(SETTING_PROPERTY + propName + " to " + propVal);
+ props.setProperty(propName, propVal);
+
+ }
+ } catch (Exception e) {
+ if (m.getName().equals("getKey")) {
+ LOG.trace("Caught " + e.getClass().getName()
+ + " exception trying to convert results from getKey() - ignoring");
+ } else {
+ LOG.error("Caught exception trying to convert value returned by" + fromClass.getName()
+ + "." + m.getName() + "() to Properties entry", e);
+ }
+ }
+ }
+
+ }
+ }
+
+ // End of method loop. If there was only one getter, named
+ // "getValue", then
+ // set value identified by "prefix" to that one value.
+ if ((numGetters == 1) && ("getValue".equals(lastGetterName))) {
+ props.setProperty(propNamePfx, propVal);
+ }
+ } else {
+ // Class is not yang generated and not a list
+ // It must be an element of a leaf list - set "prefix" to value
+ String fromVal = null;
+ if (fromObj instanceof byte[]) {
+ try {
+ fromVal = new String((byte[]) fromObj, "UTF-8");
+ } catch (Exception e) {
+ LOG.warn("Caught exception trying to convert " + pfx + " from byte[] to String", e);
+ fromVal = fromObj.toString();
+ }
+
+ } else {
+ fromVal = fromObj.toString();
+ }
+ LOG.debug(SETTING_PROPERTY + pfx + " to " + fromVal);
+ props.setProperty(pfx, fromVal);
+ }
+
+ return (props);
+ }
+
+ public static Object toBuilder(Properties props, Object toObj) {
+
+ return (toBuilder(props, "", toObj));
+ }
+
+ public static List toList(Properties props, String pfx, List toObj, Class elemType) {
+
+ int maxIdx = -1;
+ boolean foundValue = false;
+
+ if (props.containsKey(pfx + "_length")) {
+ try {
+ int listLength = Integer.parseInt(props.getProperty(pfx + "_length"));
+
+ if (listLength > 0) {
+ maxIdx = listLength - 1;
+ }
+ } catch (NumberFormatException e) {
+ LOG.info("Invalid input for length ", e);
+ }
+ }
+
+ String arrayKey = pfx + "[";
+ int arrayKeyLength = arrayKey.length();
+ if (maxIdx == -1) {
+ // Figure out array size
+ for (Object pNameObj : props.keySet()) {
+ String key = (String) pNameObj;
+
+ if (key.startsWith(arrayKey)) {
+ String idxStr = key.substring(arrayKeyLength);
+ int endloc = idxStr.indexOf("]");
+ if (endloc != -1) {
+ idxStr = idxStr.substring(0, endloc);
+ }
+ try {
+ int curIdx = Integer.parseInt(idxStr);
+ if (curIdx > maxIdx) {
+ maxIdx = curIdx;
+ }
+ } catch (Exception e) {
+ LOG.error("Illegal subscript in property {}", key, e);
+ }
+
+ }
+ }
+ }
+
+ for (int i = 0; i <= maxIdx; i++) {
+
+ String curBase = pfx + "[" + i + "]";
+
+ if (isYangGenerated(elemType)) {
+
+ if (isIpAddress(elemType)) {
+
+ String curValue = props.getProperty(curBase, "");
+
+ if ((curValue != null) && (curValue.length() > 0)) {
+ toObj.add(IpAddressBuilder.getDefaultInstance(curValue));
+ foundValue = true;
+ }
+ } else if (isIpv4Address(elemType)) {
+ String curValue = props.getProperty(curBase, "");
+
+ if ((curValue != null) && (curValue.length() > 0)) {
+ toObj.add(new Ipv4Address(curValue));
+ foundValue = true;
+ }
+
+ } else if (isIpv6Address(elemType)) {
+ String curValue = props.getProperty(curBase, "");
+
+ if ((curValue != null) && (curValue.length() > 0)) {
+ toObj.add(new Ipv6Address(curValue));
+ foundValue = true;
+ }
+ } else if (isIpPrefix(elemType)) {
+
+ String curValue = props.getProperty(curBase, "");
+
+ if ((curValue != null) && (curValue.length() > 0)) {
+ toObj.add(IpPrefixBuilder.getDefaultInstance(curValue));
+ foundValue = true;
+ }
+ } else if (isPortNumber(elemType)) {
+
+ String curValue = props.getProperty(curBase, "");
+
+ if ((curValue != null) && (curValue.length() > 0)) {
+ toObj.add(PortNumber.getDefaultInstance(curValue));
+ foundValue = true;
+ }
+ } else if (isDscp(elemType)) {
+
+ String curValue = props.getProperty(curBase, "");
+
+ if ((curValue != null) && (curValue.length() > 0)) {
+ toObj.add(Dscp.getDefaultInstance(curValue));
+ foundValue = true;
+ }
+ } else {
+ String builderName = elemType.getName() + "Builder";
+ try {
+ Class builderClass = Class.forName(builderName);
+ Object builderObj = builderClass.newInstance();
+ Method buildMethod = builderClass.getMethod("build");
+ builderObj = toBuilder(props, curBase, builderObj, true);
+ if (builderObj != null) {
+ Object builtObj = buildMethod.invoke(builderObj);
+ toObj.add(builtObj);
+ foundValue = true;
+ }
+
+ } catch (ClassNotFoundException e) {
+ LOG.warn("Could not find builder class {}", builderName, e);
+ } catch (Exception e) {
+ LOG.error("Caught exception trying to populate list from {}", pfx, e);
+ }
+ }
+ } else {
+ // Must be a leaf list
+ String curValue = props.getProperty(curBase, "");
+
+ toObj.add(curValue);
+
+ if ((curValue != null) && (curValue.length() > 0)) {
+ foundValue = true;
+ }
+ }
+
+ }
+
+ if (foundValue) {
+ return (toObj);
+ } else {
+ return (null);
+ }
+
+ }
+
+ public static Object toBuilder(Properties props, String pfx, Object toObj) {
+ return (toBuilder(props, pfx, toObj, false));
+ }
+
+ public static Object toBuilder(Properties props, String pfx, Object toObj, boolean preservePfx) {
+
+ Class toClass = toObj.getClass();
+ boolean foundValue = false;
+
+ Ipv4Address addr;
+
+ if (isYangGenerated(toClass)) {
+ // Class is yang generated.
+ String propNamePfx = null;
+ if (preservePfx) {
+ propNamePfx = pfx;
+ } else {
+
+ if ((pfx != null) && (pfx.length() > 0)) {
+ propNamePfx = pfx + "." + toLowerHyphen(toClass.getSimpleName());
+ } else {
+ propNamePfx = toLowerHyphen(toClass.getSimpleName());
+ }
+
+ if (propNamePfx.endsWith(BUILDER)) {
+ propNamePfx = propNamePfx.substring(0, propNamePfx.length() - BUILDER.length());
+ }
+
+ if (propNamePfx.endsWith("-impl")) {
+ propNamePfx = propNamePfx.substring(0, propNamePfx.length() - "-impl".length());
+ }
+ }
+
+ if (toObj instanceof Identifier) {
+ return (toObj);
+ }
+
+ // Iterate through getter methods to figure out values we need to
+ // set
+
+ for (Method m : toClass.getMethods()) {
+ if (isSetter(m)) {
+ Class paramTypes[] = m.getParameterTypes();
+ Class paramClass = paramTypes[0];
+
+ String fieldName = toLowerHyphen(m.getName().substring(3));
+ fieldName = fieldName.substring(0, 1).toLowerCase() + fieldName.substring(1);
+
+ String propName = propNamePfx + "." + fieldName;
+
+ String paramValue = props.getProperty(propName);
+ if (paramValue == null) {
+
+ } else if ("".equals(paramValue)) {
+ LOG.trace(propName + " was set to the empty string, setting it to null");
+ paramValue = null;
+ } else {
+
+ }
+
+ // Is the return type a yang generated class?
+ if (isYangGenerated(paramClass)) {
+ // Is it an enum?
+ if (paramClass.isEnum()) {
+
+ // Param type is a typedef.
+ if ((paramValue != null) && (paramValue.length() > 0)) {
+ Object paramObj = null;
+
+ try {
+ paramObj = Enum.valueOf(paramClass, toJavaEnum(paramValue));
+ } catch (Exception e) {
+ LOG.error("Caught exception trying to convert field " + propName + " to enum "
+ + paramClass.getName(), e);
+ }
+
+ try {
+ boolean isAccessible = m.isAccessible();
+ if (!isAccessible) {
+ m.setAccessible(true);
+ }
+
+ m.invoke(toObj, paramObj);
+
+ if (!isAccessible) {
+ m.setAccessible(isAccessible);
+ }
+ foundValue = true;
+
+ } catch (Exception e) {
+ LOG.error("Caught exception trying to create Yang-generated enum expected by"
+ + toClass.getName() + "." + m.getName() + "() from Properties entry", e);
+ }
+ }
+ } else {
+
+ String simpleName = paramClass.getSimpleName();
+
+ if (IPV4_ADDRESS.equals(simpleName) || IPV6_ADDRESS.equals(simpleName)
+ || IP_ADDRESS.equals(simpleName)) {
+
+
+ if ((paramValue != null) && (paramValue.length() > 0)) {
+ try {
+ IpAddress ipAddr = IpAddressBuilder.getDefaultInstance(paramValue);
+
+ if (IPV4_ADDRESS.equals(simpleName)) {
+ m.invoke(toObj, ipAddr.getIpv4Address());
+ } else if (IPV6_ADDRESS.equals(simpleName)) {
+ m.invoke(toObj, ipAddr.getIpv6Address());
+
+ } else {
+ m.invoke(toObj, ipAddr);
+ }
+ foundValue = true;
+ } catch (Exception e) {
+ LOG.error("Caught exception calling " + toClass.getName() + "." + m.getName()
+ + "(" + paramValue + ")", e);
+
+ }
+ } else {
+ try {
+ boolean isAccessible = m.isAccessible();
+ if (!isAccessible) {
+ m.setAccessible(true);
+ }
+
+ m.invoke(toObj, paramValue);
+ if (!isAccessible) {
+ m.setAccessible(isAccessible);
+ }
+ foundValue = true;
+
+ } catch (Exception e) {
+ LOG.error("Caught exception trying to call " + toClass.getName() + "."
+ + m.getName() + "() with Properties entry", e);
+ }
+ }
+ } else if (IP_PREFIX.equals(simpleName)) {
+ if ((paramValue != null) && (paramValue.length() > 0)) {
+ try {
+ IpPrefix ipPrefix = IpPrefixBuilder.getDefaultInstance(paramValue);
+ m.invoke(toObj, ipPrefix);
+ foundValue = true;
+ } catch (Exception e) {
+ LOG.error("Caught exception calling " + toClass.getName() + "." + m.getName()
+ + "(" + paramValue + ")", e);
+ }
+ }
+ } else if ("PortNumber".equals(simpleName)) {
+ if ((paramValue != null) && (paramValue.length() > 0)) {
+ try {
+ PortNumber portNumber = PortNumber.getDefaultInstance(paramValue);
+ m.invoke(toObj, portNumber);
+ foundValue = true;
+ } catch (Exception e) {
+ LOG.error("Caught exception calling " + toClass.getName() + "." + m.getName()
+ + "(" + paramValue + ")", e);
+ }
+ }
+ } else if ("Dscp".equals(simpleName)) {
+ if ((paramValue != null) && (paramValue.length() > 0)) {
+ try {
+ Dscp dscp = Dscp.getDefaultInstance(paramValue);
+ m.invoke(toObj, dscp);
+ foundValue = true;
+ } catch (Exception e) {
+ LOG.error("Caught exception calling " + toClass.getName() + "." + m.getName()
+ + "(" + paramValue + ")", e);
+ }
+ }
+ } else if ("RouteDistinguisher".equals(simpleName)) {
+ if ((paramValue != null) && (paramValue.length() > 0)) {
+ try {
+ RouteDistinguisher routeDistinguisher = RouteDistinguisherBuilder.getDefaultInstance(paramValue);
+ m.invoke(toObj, routeDistinguisher);
+ foundValue = true;
+ } catch (Exception e) {
+ LOG.error("Caught exception calling " + toClass.getName() + "." + m.getName()
+ + "(" + paramValue + ")", e);
+ }
+ }
+ }
+ else {
+ // setter expects a yang-generated class. Need
+ // to
+ // create a builder to set it.
+
+ String builderName = paramClass.getName() + "Builder";
+ Class builderClass = null;
+ Object builderObj = null;
+ Object paramObj = null;
+
+ Object constObj = null;
+
+ try {
+ builderClass = Class.forName(builderName);
+ builderObj = builderClass.newInstance();
+ paramObj = toBuilder(props, propNamePfx, builderObj);
+ } catch (ClassNotFoundException e) {
+ LOG.trace("Builder class {} not found catching ClassNotFoundException and trying other methods",
+ builderName);
+ if (paramValue == null) {
+ try {
+ boolean isAccessible = m.isAccessible();
+ if (!isAccessible) {
+ m.setAccessible(true);
+ }
+
+ m.invoke(toObj, new Object[] { null });
+ if (!isAccessible) {
+ m.setAccessible(isAccessible);
+ }
+ foundValue = true;
+
+ } catch (Exception e1) {
+ LOG.error("Caught exception trying to cally" + toClass.getName() + "."
+ + m.getName() + "() with Properties entry", e1);
+ }
+ } else {
+ try {
+ // See if I can find a constructor I
+ // can
+ // use
+ Constructor[] constructors = paramClass.getConstructors();
+ // Is there a String constructor?
+ for (Constructor c : constructors) {
+ Class[] cParms = c.getParameterTypes();
+ if ((cParms != null) && (cParms.length == 1)) {
+ if (String.class.isAssignableFrom(cParms[0])) {
+ constObj = c.newInstance(paramValue);
+ }
+ }
+ }
+
+ if (constObj == null) {
+ // Is there a Long constructor?
+ for (Constructor c : constructors) {
+ Class[] cParms = c.getParameterTypes();
+ if ((cParms != null) && (cParms.length == 1)) {
+ if (Long.class.isAssignableFrom(cParms[0])) {
+ constObj = c.newInstance(Long.parseLong(paramValue));
+ }
+ }
+ }
+
+ }
+
+ if (constObj == null) {
+
+ // Last chance - see if
+ // parameter class has a static
+ // method
+ // getDefaultInstance(String)
+ try {
+ Method gm =
+ paramClass.getMethod("getDefaultInstance", String.class);
+
+ int gmodifier = gm.getModifiers();
+ if (Modifier.isStatic(gmodifier)) {
+ // Invoke static
+ // getDefaultInstance(String)
+ paramObj = gm.invoke(null, paramValue);
+ }
+
+ } catch (Exception gme) {
+ LOG.info("Unable to find static method getDefaultInstance for "
+ + "class {}", paramClass.getSimpleName(), gme);
+ }
+ }
+
+ } catch (Exception e1) {
+ LOG.warn(
+ "Could not find a suitable constructor for " + paramClass.getName(),
+ e1);
+ }
+
+ if (constObj == null) {
+ LOG.warn("Could not find builder class " + builderName
+ + " and could not find a String or Long constructor or static "
+ + "getDefaultInstance(String) - trying just to set passing paramValue");
+
+ }
+ }
+ } catch (Exception e) {
+ LOG.error("Caught exception trying to create builder " + builderName, e);
+ }
+
+ if (paramObj != null && builderClass != null) {
+
+ try {
+ Method buildMethod = builderClass.getMethod("build");
+
+ Object builtObj = buildMethod.invoke(paramObj);
+
+ boolean isAccessible = m.isAccessible();
+ if (!isAccessible) {
+ m.setAccessible(true);
+ }
+
+ m.invoke(toObj, builtObj);
+ if (!isAccessible) {
+ m.setAccessible(isAccessible);
+ }
+ foundValue = true;
+
+ } catch (Exception e) {
+ LOG.error("Caught exception trying to set Yang-generated class expected by"
+ + toClass.getName() + "." + m.getName() + "() from Properties entry",
+ e);
+ }
+ } else {
+ try {
+ boolean isAccessible = m.isAccessible();
+ if (!isAccessible) {
+ m.setAccessible(true);
+ }
+
+ if (constObj != null) {
+ m.invoke(toObj, constObj);
+ } else {
+ m.invoke(toObj, paramValue);
+ }
+ if (!isAccessible) {
+ m.setAccessible(isAccessible);
+ }
+ foundValue = true;
+
+ } catch (Exception e) {
+ LOG.error("Caught exception trying to convert value returned by"
+ + toClass.getName() + "." + m.getName() + "() to Properties entry", e);
+ }
+ }
+ }
+ }
+ } else {
+
+ // Setter's argument is not a yang-generated class. See
+ // if it is a List.
+
+ if (List.class.isAssignableFrom(paramClass)) {
+ // Figure out what type of args are in List and pass
+ // that to toList().
+
+ Type paramType = m.getGenericParameterTypes()[0];
+ Type elementType = ((ParameterizedType) paramType).getActualTypeArguments()[0];
+ Object paramObj = new LinkedList();
+ try {
+ paramObj = toList(props, propName, (List) paramObj, (Class) elementType);
+ } catch (Exception e) {
+ LOG.error("Caught exception trying to create list expected as argument to {}.{}",
+ toClass.getName(), m.getName(), e);
+ }
+
+ if (paramObj != null) {
+ try {
+ boolean isAccessible = m.isAccessible();
+ if (!isAccessible) {
+ m.setAccessible(true);
+ }
+ m.invoke(toObj, paramObj);
+ if (!isAccessible) {
+ m.setAccessible(isAccessible);
+ }
+ foundValue = true;
+
+ } catch (Exception e) {
+ LOG.error("Caught exception trying to convert List returned by" + toClass.getName()
+ + "." + m.getName() + "() to Properties entry", e);
+ }
+ }
+ } else {
+
+ // Setter expects something that is not a List and
+ // not yang-generated. Just pass the parameter value
+ if ((paramValue != null) && (paramValue.length() > 0)) {
+
+ Object constObj = null;
+
+ try {
+ // See if I can find a constructor I can use
+ Constructor[] constructors = paramClass.getConstructors();
+ // Is there a String constructor?
+ for (Constructor c : constructors) {
+ Class[] cParms = c.getParameterTypes();
+ if ((cParms != null) && (cParms.length == 1)) {
+ if (String.class.isAssignableFrom(cParms[0])) {
+ constObj = c.newInstance(paramValue);
+ }
+ }
+ }
+
+ if (constObj == null) {
+ // Is there a Long constructor?
+ for (Constructor c : constructors) {
+ Class[] cParms = c.getParameterTypes();
+ if ((cParms != null) && (cParms.length == 1)) {
+ if (Long.class.isAssignableFrom(cParms[0])) {
+ constObj = c.newInstance(Long.parseLong(paramValue));
+ }
+ }
+ }
+
+ }
+
+ if (constObj != null) {
+ try {
+ m.invoke(toObj, constObj);
+ foundValue = true;
+ } catch (Exception e2) {
+ LOG.error("Caught exception trying to call " + m.getName(), e2);
+ }
+ } else {
+ try {
+ boolean isAccessible = m.isAccessible();
+ if (!isAccessible) {
+ m.setAccessible(true);
+ }
+ m.invoke(toObj, paramValue);
+ if (!isAccessible) {
+ m.setAccessible(isAccessible);
+ }
+ foundValue = true;
+
+ } catch (Exception e) {
+ LOG.error("Caught exception trying to convert value returned by"
+ + toClass.getName() + "." + m.getName() + "() to Properties entry",
+ e);
+ }
+ }
+ } catch (Exception e1) {
+ LOG.warn("Could not find a suitable constructor for " + paramClass.getName(), e1);
+ }
+
+ }
+ }
+ }
+ } // End of section handling "setter" method
+ } // End of loop through Methods
+ } // End of section handling yang-generated class
+
+ if (foundValue) {
+ return (toObj);
+ } else {
+ return (null);
+ }
+ }
+
+ private static boolean classHasSpecialHandling(String simpleName) {
+ if (IP_ADDRESS.equals(simpleName) || IPV4_ADDRESS.equals(simpleName) || IPV6_ADDRESS.equals(simpleName)
+ || IP_PREFIX.equals(simpleName) || "PortNumber".equals(simpleName) || "Dscp".equals(simpleName)) {
+ return true;
+ }
+ return false;
+ }
+
+ private static String getStringValueMethod(String simpleName){
+ if (IP_ADDRESS.equals(simpleName) || IP_PREFIX.equals(simpleName)) {
+ return("stringValue");
+ } else {
+ return("getValue");
+ }
+ }
+
+ public static void printPropertyList(PrintStream pstr, String pfx, Class toClass) {
+ boolean foundValue = false;
+
+ if (isYangGenerated(toClass) && (!Identifier.class.isAssignableFrom(toClass))) {
+ // Class is yang generated.
+ String propNamePfx = null;
+ if (pfx.endsWith("]")) {
+ propNamePfx = pfx;
+ } else {
+
+ if ((pfx != null) && (pfx.length() > 0)) {
+ propNamePfx = pfx + "." + toLowerHyphen(toClass.getSimpleName());
+ } else {
+ propNamePfx = toLowerHyphen(toClass.getSimpleName());
+ }
+
+ if (propNamePfx.endsWith(BUILDER)) {
+ propNamePfx = propNamePfx.substring(0, propNamePfx.length() - BUILDER.length());
+ }
+
+ if (propNamePfx.endsWith("-impl")) {
+ propNamePfx = propNamePfx.substring(0, propNamePfx.length() - "-impl".length());
+ }
+ }
+
+ // Iterate through getter methods to figure out values we need to
+ // set
+
+ for (Method m : toClass.getMethods()) {
+ if (isGetter(m)) {
+ Class returnClass = m.getReturnType();
+
+ String fieldName = toLowerHyphen(m.getName().substring(3));
+ if (fieldName != null) {
+ fieldName = fieldName.substring(0, 1).toLowerCase() + fieldName.substring(1);
+ } else {
+ fieldName = "";
+ }
+ String propName = propNamePfx + "." + fieldName;
+
+ // Is the return type a yang generated class?
+ if (isYangGenerated(returnClass)) {
+ // Is it an enum?
+ if (returnClass.isEnum()) {
+ pstr.print("\n\n * " + propName);
+ } else {
+
+ String simpleName = returnClass.getSimpleName();
+
+ if (IPV4_ADDRESS.equals(simpleName) || IPV6_ADDRESS.equals(simpleName)
+ || IP_ADDRESS.equals(simpleName) || IP_PREFIX.equals(simpleName)
+ || "PortNumber".equals(simpleName) || "Dscp".equals(simpleName)) {
+ pstr.print("\n\n * " + propName);
+ } else {
+ printPropertyList(pstr, propNamePfx, returnClass);
+ }
+
+ }
+ } else {
+
+ // Setter's argument is not a yang-generated class. See
+ // if it is a List.
+
+ if (List.class.isAssignableFrom(returnClass)) {
+ // Figure out what type of args are in List and pass
+ // that to toList().
+
+ Type returnType = m.getGenericReturnType();
+ Type elementType = ((ParameterizedType) returnType).getActualTypeArguments()[0];
+ Class elementClass = (Class) elementType;
+ printPropertyList(pstr,
+ propNamePfx + "." + toLowerHyphen(elementClass.getSimpleName()) + "[]",
+ elementClass);
+
+ } else if (!returnClass.equals(Class.class)) {
+
+ // Setter expects something that is not a List and
+ // not yang-generated. Just pass the parameter value
+ pstr.print("\n\n * " + propName);
+ }
+ }
+ } // End of section handling "setter" method
+ } // End of loop through Methods
+ } // End of section handling yang-generated class
+
+ }
+
+ public static boolean isYangGenerated(Class c) {
+ if (c != null) {
+ return (c.getName().startsWith("org.opendaylight.yang.gen."));
+ }
+ return false;
+ }
+
+ public static boolean isIpPrefix(Class c) {
+
+ if (c == null) {
+ return (false);
+ }
+ if (!isIetfInet(c)) {
+ return (false);
+ }
+ String simpleName = c.getSimpleName();
+ return (IP_PREFIX.equals(simpleName));
+ }
+
+ public static boolean isIpv4Address(Class c) {
+
+ if (c == null) {
+ return (false);
+ }
+ if (!isIetfInet(c)) {
+ return (false);
+ }
+ String simpleName = c.getSimpleName();
+ return (IPV4_ADDRESS.equals(simpleName));
+ }
+
+ public static boolean isIpv6Address(Class c) {
+
+ if (c == null) {
+ return (false);
+ }
+ if (!isIetfInet(c)) {
+ return (false);
+ }
+ String simpleName = c.getSimpleName();
+ return (IPV6_ADDRESS.equals(simpleName));
+ }
+
+ public static boolean isIpAddress(Class c) {
+
+ if (c == null) {
+ return (false);
+ }
+ if (!isIetfInet(c)) {
+ return (false);
+ }
+ String simpleName = c.getSimpleName();
+ return (IP_ADDRESS.equals(simpleName));
+ }
+
+ public static boolean isPortNumber(Class c) {
+
+ if (c == null) {
+ return (false);
+ }
+ if (!isIetfInet(c)) {
+ return (false);
+ }
+
+ String simpleName = c.getSimpleName();
+ return ("PortNumber".equals(simpleName));
+ }
+
+ public static boolean isDscp(Class c) {
+
+ if (c == null) {
+ return (false);
+ }
+ if (!isIetfInet(c)) {
+ return (false);
+ }
+ String simpleName = c.getSimpleName();
+ return ("Dscp".equals(simpleName));
+ }
+
+ public static boolean isIetfInet(Class c) {
+
+ Package p = c.getPackage();
+ if (p != null) {
+ String pkgName = p.getName();
+
+ if ((pkgName != null) && (pkgName.indexOf("yang.ietf.inet.types") > -1)) {
+ return (true);
+ }
+ }
+
+ return (false);
+ }
+
+ public static String toLowerHyphen(String inStr) {
+ if (inStr == null) {
+ return (null);
+ }
+
+ String str = inStr.substring(0, 1).toLowerCase();
+ if (inStr.length() > 1) {
+ str = str + inStr.substring(1);
+ }
+
+ String regex = "([a-z0-9A-Z])(?=[A-Z])";
+ String replacement = "$1-";
+
+ String retval = str.replaceAll(regex, replacement).toLowerCase();
+
+ return (retval);
+ }
+
+ // This is called when mapping the yang value back to a valid java enumeration
+ public static String toJavaEnum(String inStr) {
+ if (inStr == null) {
+ return (null);
+ } else if (inStr.length() == 0) {
+ return (inStr);
+ }
+
+ // This is needed for enums containing under scores
+ inStr = inStr.replaceAll("_", "");
+
+ // This will strip out all periods, which cannot be in a java enum
+ inStr = inStr.replaceAll("\\.", "");
+
+ // This is needed for enums containing spaces
+ inStr = inStr.replaceAll(" ", "");
+
+ String[] terms = inStr.split("-");
+ StringBuffer sbuff = new StringBuffer();
+
+ // appends an _ if the string starts with a digit to make it a valid java enum
+ if (Character.isDigit(inStr.charAt(0))) {
+ sbuff.append('_');
+ }
+ // If the string contains hyphens it will convert the string to upperCamelCase without hyphens
+ for (String term : terms) {
+ sbuff.append(term.substring(0, 1).toUpperCase());
+ if (term.length() > 1) {
+ sbuff.append(term.substring(1));
+ }
+ }
+ return (sbuff.toString());
+
+ }
+
+ public static boolean isGetter(Method m) {
+ if (m == null) {
+ return (false);
+ }
+
+ if (Modifier.isPublic(m.getModifiers()) && (m.getParameterTypes().length == 0)) {
+ if (m.getName().matches("^get[A-Z].*") && !m.getReturnType().equals(void.class)) {
+ if (!"getClass".equals(m.getName())) {
+ return (true);
+ }
+ }
+
+ if (m.getName().matches("^get[A-Z].*") && m.getReturnType().equals(boolean.class)) {
+ return (true);
+ }
+
+ if (m.getName().matches("^is[A-Z].*") && m.getReturnType().equals(Boolean.class)) {
+ return (true);
+ }
+ }
+
+ return (false);
+ }
+
+ public static boolean isSetter(Method m) {
+ if (m == null) {
+ return (false);
+ }
+
+ if (Modifier.isPublic(m.getModifiers()) && (m.getParameterTypes().length == 1)) {
+ if (m.getName().matches("^set[A-Z].*")) {
+ Class[] paramTypes = m.getParameterTypes();
+ if (paramTypes[0].isAssignableFrom(Identifier.class)
+ || Identifier.class.isAssignableFrom(paramTypes[0])) {
+ return (false);
+ } else {
+ return (true);
+ }
+ }
+
+ }
+
+ return (false);
+ }
+
+ @Deprecated
+ public static String getFullPropertiesPath(String propertiesFileName) {
+ String karafHome = System.getProperty("karaf.home","/opt/lsc/controller");
+ return karafHome + "/configuration/" + propertiesFileName;
+ }
+
+ // This is called when mapping a valid java enumeration back to the yang model value
+ @Deprecated
+ public static String mapEnumeratedValue(String propertyName, String propertyValue) {
+ LOG.info("mapEnumeratedValue called with propertyName=" + propertyName + " and value=" + propertyValue);
+ String mappingKey = "yang." + propertyName + "." + propertyValue;
+ if (yangMappingProperties.containsKey(mappingKey)) {
+ return (yangMappingProperties.getProperty(mappingKey));
+ } else {
+ LOG.info("yangMappingProperties did not contain the key " + mappingKey + " returning the original value.");
+ return propertyValue;
+ }
+ }
+
+}
diff --git a/core/sli/provider/src/main/java/org/onap/ccsdk/sli/core/sli/provider/PrintYangToProp.java b/core/sli/provider/src/main/java/org/onap/ccsdk/sli/core/sli/provider/PrintYangToProp.java
new file mode 100644
index 000000000..992ed64d4
--- /dev/null
+++ b/core/sli/provider/src/main/java/org/onap/ccsdk/sli/core/sli/provider/PrintYangToProp.java
@@ -0,0 +1,1355 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Modifications Copyright (C) 2018 IBM.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.sli.provider;
+
+import java.io.PrintStream;
+import java.io.FileDescriptor;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Properties;
+import java.util.Arrays;
+import java.util.ArrayList;
+import java.io.*;
+import org.opendaylight.yangtools.yang.binding.Identifier;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddressBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefixBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Prefix;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import com.google.common.base.Strings;
+
+
+public class PrintYangToProp {
+
+ private static final Logger LOG = LoggerFactory.getLogger(PrintYangToProp.class);
+ public static final String PROPERTIES_FILE="";
+ private static Properties properties;
+ private static final String BUILDER="-builder";
+ private static final String IMPL="-impl";
+ private static final String TO_PROPERTIES_STRING="() to Properties entry";
+ private static final String CAUGHT_EXCEPTION_MSG="Caught exception trying to convert value returned by ";
+ public static Properties prop = new Properties();
+ public static ArrayList<String> propList = new ArrayList<>();
+
+
+ public static Properties toProperties(Properties props, Object fromObj) {
+ Class fromClass = null;
+
+ if (fromObj != null)
+ {
+ fromClass = fromObj.getClass();
+ }
+ return (toProperties(props, "", fromObj, fromClass));
+ }
+
+ public static Properties toProperties(Properties props, String pfx, Object fromObj)
+ {
+ Class fromClass = null;
+
+ if (fromObj != null)
+ {
+ fromClass = fromObj.getClass();
+ }
+
+ return(toProperties(props, pfx, fromObj, fromClass));
+ }
+
+ public static Properties toProperties(Properties props, String pfx,
+ Object fromObj, Class fromClass) {
+
+ if (fromObj == null) {
+ return (props);
+ }
+
+
+ String simpleName = fromClass.getSimpleName();
+
+ if (fromObj instanceof List) {
+
+
+ List fromList = (List) fromObj;
+
+ for (int i = 0; i < fromList.size(); i++) {
+ toProperties(props, pfx + "[" + i + "]", fromList.get(i), fromClass);
+ }
+ props.setProperty(pfx + "_length", "" + fromList.size());
+
+ } else if (isYangGenerated(fromClass)) {
+
+ String propNamePfx = null;
+
+ // If called from a list (so prefix ends in ']'), don't
+ // add class name again
+ if (pfx.endsWith("]")) {
+ propNamePfx = pfx;
+ } else {
+ if ((pfx != null) && (pfx.length() > 0)) {
+ propNamePfx = pfx ;
+ } else {
+ propNamePfx = toLowerHyphen(fromClass.getSimpleName());
+ }
+
+ if (propNamePfx.endsWith(BUILDER)) {
+ propNamePfx = propNamePfx.substring(0, propNamePfx.length()
+ - BUILDER.length());
+ }
+
+ if (propNamePfx.endsWith(IMPL)) {
+ propNamePfx = propNamePfx.substring(0, propNamePfx.length()
+ - IMPL.length());
+ }
+ }
+
+ // Iterate through getter methods to figure out values we need to
+ // save from
+
+ for (Method m : fromClass.getMethods()) {
+
+ if (isGetter(m)) {
+
+ Class returnType = m.getReturnType();
+ String fieldName = toLowerHyphen(m.getName().substring(3));
+ if(m != null && m.getName().matches("^is[A-Z].*")){
+ fieldName = toLowerHyphen(m.getName().substring(2));
+ }
+
+ if(Strings.isNullOrEmpty(fieldName)) fieldName = fieldName.substring(0, 1).toLowerCase()+ fieldName.substring(1);
+
+
+ // Is the return type a yang generated class?
+ if (isYangGenerated(returnType)) {
+
+ // Is it an enum?
+ if (returnType.isEnum()) {
+ // Return type is a typedef. Save its value.
+ try {
+ boolean isAccessible = m.isAccessible();
+ if (!isAccessible) {
+ m.setAccessible(true);
+ }
+
+ Object retValue = m.invoke(fromObj);
+
+ if (!isAccessible) {
+ m.setAccessible(isAccessible);
+ }
+ if (retValue != null) {
+ String propName = propNamePfx + "."
+ + fieldName;
+ String propVal = retValue.toString();
+ String yangProp = "yang." + fieldName + "." + propVal;
+ if ( properties.containsKey(yangProp)) {
+ propVal = properties.getProperty(yangProp);
+ }
+ props.setProperty(propName, propVal);
+ }
+ } catch (Exception e) {
+ LOG.error(
+ "Caught exception trying to convert Yang-generated enum returned by "
+ + fromClass.getName() + "."
+ + m.getName()
+ + TO_PROPERTIES_STRING, e);
+ }
+ } else if (isIpv4Address(returnType)) {
+ // Save its value
+ try {
+ String propName = propNamePfx + "." + fieldName;
+ boolean isAccessible = m.isAccessible();
+ if (!isAccessible) {
+ m.setAccessible(true);
+ }
+ Ipv4Address retValue = (Ipv4Address) m.invoke(fromObj);
+ if (!isAccessible) {
+ m.setAccessible(isAccessible);
+ }
+
+ if (retValue != null) {
+ String propVal = retValue.getValue();
+
+ props.setProperty(propName, propVal);
+
+ }
+ } catch (Exception e) {
+ LOG.error(
+ CAUGHT_EXCEPTION_MSG
+ + fromClass.getName() + "."
+ + m.getName()
+ + TO_PROPERTIES_STRING, e);
+ }
+ } else if (isIpv6Address(returnType)) {
+ // Save its value
+ try {
+ String propName = propNamePfx + "." + fieldName;
+ boolean isAccessible = m.isAccessible();
+ if (!isAccessible) {
+ m.setAccessible(true);
+ }
+ Ipv6Address retValue = (Ipv6Address) m.invoke(fromObj);
+ if (!isAccessible) {
+ m.setAccessible(isAccessible);
+ }
+
+ if (retValue != null) {
+ String propVal = retValue.getValue();
+
+ props.setProperty(propName, propVal);
+
+ }
+ } catch (Exception e) {
+ LOG.error(
+ CAUGHT_EXCEPTION_MSG
+ + fromClass.getName() + "."
+ + m.getName()
+ + TO_PROPERTIES_STRING, e);
+ }
+ } else if (isIpv4Prefix(returnType)) {
+
+ // Save its value
+ try {
+ String propName = propNamePfx + "." + fieldName;
+ boolean isAccessible = m.isAccessible();
+ if (!isAccessible) {
+ m.setAccessible(true);
+ }
+ Ipv4Prefix retValue = (Ipv4Prefix) m.invoke(fromObj);
+ if (!isAccessible) {
+ m.setAccessible(isAccessible);
+ }
+
+ if (retValue != null) {
+ String propVal = retValue.getValue();
+
+ props.setProperty(propName, propVal);
+
+ }
+ } catch (Exception e) {
+ LOG.error(
+ CAUGHT_EXCEPTION_MSG
+ + fromClass.getName() + "."
+ + m.getName()
+ + TO_PROPERTIES_STRING, e);
+ }
+ } else if (isIpv6Prefix(returnType)) {
+ //System.out.println("isIpv6Prefix");
+ // Save its value
+ try {
+ String propName = propNamePfx + "." + fieldName;
+ boolean isAccessible = m.isAccessible();
+ if (!isAccessible) {
+ m.setAccessible(true);
+ }
+ Ipv6Prefix retValue = (Ipv6Prefix) m.invoke(fromObj);
+ if (!isAccessible) {
+ m.setAccessible(isAccessible);
+ }
+
+ if (retValue != null) {
+ String propVal = retValue.getValue().toString();
+ //LOG.debug("Setting property " + propName
+ // + " to " + propVal);
+ props.setProperty(propName, propVal);
+
+ }
+ } catch (Exception e) {
+ LOG.error(
+ CAUGHT_EXCEPTION_MSG
+ + fromClass.getName() + "."
+ + m.getName()
+ + TO_PROPERTIES_STRING, e);
+ }
+ } else {
+ try {
+ boolean isAccessible = m.isAccessible();
+ if (!isAccessible) {
+ m.setAccessible(true);
+ }
+ Object retValue = m.invoke(fromObj);
+ if (!isAccessible) {
+ m.setAccessible(isAccessible);
+ }
+ if (retValue != null) {
+ toProperties(props, propNamePfx + "." + fieldName, retValue, returnType);
+ }
+ } catch (Exception e) {
+ LOG.error(
+ "Caught exception trying to convert Yang-generated class returned by"
+ + fromClass.getName() + "."
+ + m.getName()
+ + TO_PROPERTIES_STRING, e);
+ }
+ }
+ } else if (returnType.equals(Class.class)) {
+
+ //LOG.debug(m.getName()
+ // + " returns a Class object - not interested");
+
+ } else if (List.class.isAssignableFrom(returnType)) {
+
+ // This getter method returns a list.
+ try {
+ boolean isAccessible = m.isAccessible();
+ if (!isAccessible) {
+ m.setAccessible(true);
+ }
+ Object retList = m.invoke(fromObj);
+ if (!isAccessible) {
+ m.setAccessible(isAccessible);
+ }
+ // Figure out what type of elements are stored in this array.
+ Type paramType = m.getGenericReturnType();
+ Type elementType = ((ParameterizedType) paramType)
+ .getActualTypeArguments()[0];
+ toProperties(props, propNamePfx + "." + fieldName,
+ retList, (Class)elementType);
+ } catch (Exception e) {
+ LOG.error(
+ "Caught exception trying to convert List returned by "
+ + fromClass.getName() + "."
+ + m.getName()
+ + TO_PROPERTIES_STRING, e);
+ }
+
+ } else {
+
+ // Method returns something that is not a List and not
+ // yang-generated.
+ // Save its value
+ try {
+ String propName = propNamePfx + "." + fieldName;
+ boolean isAccessible = m.isAccessible();
+ if (!isAccessible) {
+ m.setAccessible(true);
+ }
+ Object propValObj = m.invoke(fromObj);
+ if (!isAccessible) {
+ m.setAccessible(isAccessible);
+ }
+
+ if (propValObj != null) {
+ String propVal = propValObj.toString();
+ //LOG.debug("Setting property " + propName
+ // + " to " + propVal);
+ props.setProperty(propName, propVal);
+
+ }
+ } catch (Exception e) {
+ LOG.error(
+ CAUGHT_EXCEPTION_MSG
+ + fromClass.getName() + "."
+ + m.getName()
+ + TO_PROPERTIES_STRING, e);
+ }
+ }
+
+ }
+ }
+
+ } else {
+ // Class is not yang generated and not a list
+ // Do nothing.
+
+ }
+
+ return (props);
+ }
+
+ public static Object toBuilder(Properties props, Object toObj) {
+
+ return (toBuilder(props, "", toObj));
+ }
+
+ public static List toList(Properties props, String pfx, List toObj,
+ Class elemType) {
+
+ int maxIdx = -1;
+ boolean foundValue = false;
+
+ //LOG.debug("Saving properties to List<" + elemType.getName()
+ // + "> from " + pfx);
+
+ // Figure out array size
+ for (Object pNameObj : props.keySet()) {
+ String key = (String) pNameObj;
+
+ if (key.startsWith(pfx + "[")) {
+ String idxStr = key.substring(pfx.length() + 1);
+ int endloc = idxStr.indexOf("]");
+ if (endloc != -1) {
+ idxStr = idxStr.substring(0, endloc);
+ }
+
+ try {
+ int curIdx = Integer.parseInt(idxStr);
+ if (curIdx > maxIdx) {
+ maxIdx = curIdx;
+ }
+ } catch (Exception e) {
+ LOG.error("Illegal subscript in property " + key);
+ }
+
+ }
+ }
+
+ //LOG.debug(pfx + " has max index of " + maxIdx);
+ for (int i = 0; i <= maxIdx; i++) {
+
+ String curBase = pfx + "[" + i + "]";
+
+ if (isYangGenerated(elemType)) {
+ String builderName = elemType.getName() + "Builder";
+ try {
+ Class builderClass = Class.forName(builderName);
+ Object builderObj = builderClass.newInstance();
+ Method buildMethod = builderClass.getMethod("build");
+ builderObj = toBuilder(props, curBase, builderObj, true);
+ if (builderObj != null) {
+ //LOG.debug("Calling " + builderObj.getClass().getName()
+ // + "." + buildMethod.getName() + "()");
+ Object builtObj = buildMethod.invoke(builderObj);
+ toObj.add(builtObj);
+ foundValue = true;
+ }
+
+ } catch (ClassNotFoundException e) {
+ LOG.warn("Could not find builder class " + builderName, e);
+ } catch (Exception e) {
+ LOG.error("Caught exception trying to populate list from "
+ + pfx);
+ }
+ }
+
+ }
+
+ if (foundValue) {
+ return (toObj);
+ } else {
+ return (null);
+ }
+
+ }
+
+ public static Object toBuilder(Properties props, String pfx, Object toObj) {
+ return(toBuilder(props, pfx, toObj, false));
+ }
+
+ public static Object toBuilder(Properties props, String pfx, Object toObj, boolean preservePfx) {
+ Class toClass = toObj.getClass();
+ boolean foundValue = false;
+
+ //LOG.debug("Saving properties to " + toClass.getName() + " class from "
+ // + pfx);
+
+ Ipv4Address addr;
+
+ if (isYangGenerated(toClass)) {
+ // Class is yang generated.
+ //LOG.debug(toClass.getName() + " is a Yang-generated class");
+
+ String propNamePfx = null;
+ if (preservePfx) {
+ propNamePfx = pfx;
+ } else {
+
+ if ((pfx != null) && (pfx.length() > 0)) {
+ propNamePfx = pfx + "."
+ + toLowerHyphen(toClass.getSimpleName());
+ } else {
+ propNamePfx = toLowerHyphen(toClass.getSimpleName());
+ }
+
+ if (propNamePfx.endsWith(BUILDER)) {
+ propNamePfx = propNamePfx.substring(0, propNamePfx.length()
+ - BUILDER.length());
+ }
+
+ if (propNamePfx.endsWith(IMPL)) {
+ propNamePfx = propNamePfx.substring(0, propNamePfx.length()
+ - IMPL.length());
+ }
+ }
+
+ if (toObj instanceof Identifier) {
+ //LOG.debug(toClass.getName() + " is a Key - skipping");
+ return (toObj);
+ }
+
+ // Iterate through getter methods to figure out values we need to
+ // set
+
+ for (Method m : toClass.getMethods()) {
+ // LOG.debug("Is " + m.getName() + " method a setter?");
+ if (isSetter(m)) {
+ // LOG.debug(m.getName() + " is a setter");
+ Class paramTypes[] = m.getParameterTypes();
+ Class paramClass = paramTypes[0];
+
+ String fieldName = toLowerHyphen(m.getName().substring(3));
+ fieldName = fieldName.substring(0, 1).toLowerCase()
+ + fieldName.substring(1);
+
+ String propName = propNamePfx + "." + fieldName;
+
+ String paramValue = props.getProperty(propName);
+ if (paramValue == null) {
+ //LOG.debug(propName + " is unset");
+ } else {
+ //LOG.debug(propName + " = " + paramValue);
+ }
+
+ // Is the return type a yang generated class?
+ if (isYangGenerated(paramClass)) {
+ // Is it an enum?
+ if (paramClass.isEnum()) {
+
+ //LOG.debug(m.getName() + " expects an Enum");
+ // Param type is a typedef.
+ if (paramValue != null) {
+ Object paramObj = null;
+
+ try {
+ paramObj = Enum.valueOf(paramClass,
+ toUpperCamelCase(paramValue));
+ } catch (Exception e) {
+ LOG.error(
+ "Caught exception trying to convert field "
+ + propName + " to enum "
+ + paramClass.getName(), e);
+ }
+
+ try {
+ boolean isAccessible = m.isAccessible();
+ if (!isAccessible) {
+ m.setAccessible(true);
+ }
+
+ //LOG.debug("Calling "
+ // + toObj.getClass().getName() + "."
+ // + m.getName() + "(" + paramValue
+ // + ")");
+ m.invoke(toObj, paramObj);
+
+ if (!isAccessible) {
+ m.setAccessible(isAccessible);
+ }
+ foundValue = true;
+
+ } catch (Exception e) {
+ LOG.error(
+ "Caught exception trying to create Yang-generated enum expected by"
+ + toClass.getName()
+ + "."
+ + m.getName()
+ + "() from Properties entry",
+ e);
+ }
+ }
+ } else {
+
+ String simpleName = paramClass.getSimpleName();
+ LOG.info("simpleName:" + simpleName);
+
+ if ("Ipv4Address".equals(simpleName)
+ || "Ipv6Address".equals(simpleName) || "Ipv4Prefix".equals(simpleName) || "Ipv6Prefix".equals(simpleName)) {
+
+ if (paramValue != null) {
+ if("Ipv4Address".equals(simpleName) || "Ipv6Address".equals(simpleName)){
+ try {
+ IpAddress ipAddr = IpAddressBuilder
+ .getDefaultInstance(paramValue);
+
+
+ if ("Ipv4Address".equals(simpleName))
+ {
+ m.invoke(toObj, ipAddr.getIpv4Address());
+ }
+ else
+ {
+ m.invoke(toObj, ipAddr.getIpv6Address());
+
+ }
+ foundValue = true;
+ } catch (Exception e) {
+ LOG.error(
+ "Caught exception calling "
+ + toClass.getName() + "."
+ + m.getName() + "("
+ + paramValue + ")", e);
+
+ }
+ }else if("Ipv4Prefix".equals(simpleName)|| "Ipv6Prefix".equals(simpleName)){
+ try {
+ IpPrefix ipPrefix = IpPrefixBuilder
+ .getDefaultInstance(paramValue);
+
+
+ if ("Ipv4Prefix".equals(simpleName))
+ {
+ m.invoke(toObj, ipPrefix.getIpv4Prefix());
+ }
+ else
+ {
+ m.invoke(toObj, ipPrefix.getIpv6Prefix());
+
+ }
+ foundValue = true;
+ } catch (Exception e) {
+ LOG.error(
+ "Caught exception calling "
+ + toClass.getName() + "."
+ + m.getName() + "("
+ + paramValue + ")", e);
+
+ }
+ }
+ }
+
+ } else {
+ // setter expects a yang-generated class. Need
+ // to
+ // create a builder to set it.
+
+ String builderName = paramClass.getName()
+ + "Builder";
+ Class builderClass = null;
+ Object builderObj = null;
+ Object paramObj = null;
+
+ //LOG.debug(m.getName()
+ // + " expects a yang-generated class - looking for builder "
+ // + builderName);
+ try {
+ builderClass = Class.forName(builderName);
+ builderObj = builderClass.newInstance();
+ paramObj = toBuilder(props, propNamePfx,
+ builderObj);
+ } catch (ClassNotFoundException e) {
+ Object constObj = null;
+ try {
+ // See if I can find a constructor I can
+ // use
+ Constructor[] constructors = paramClass
+ .getConstructors();
+ // Is there a String constructor?
+ for (Constructor c : constructors) {
+ Class[] cParms = c
+ .getParameterTypes();
+ if ((cParms != null)
+ && (cParms.length == 1)) {
+ if (String.class
+ .isAssignableFrom(cParms[0])) {
+ constObj = c
+ .newInstance(paramValue);
+ }
+ }
+ }
+
+ if (constObj == null) {
+ // Is there a Long constructor?
+ for (Constructor c : constructors) {
+ Class[] cParms = c
+ .getParameterTypes();
+ if ((cParms != null)
+ && (cParms.length == 1)) {
+ if (Long.class
+ .isAssignableFrom(cParms[0])) {
+ constObj = c
+ .newInstance(Long
+ .parseLong(paramValue));
+ }
+ }
+ }
+
+ }
+
+ if (constObj != null) {
+ try {
+ m.invoke(toObj, constObj);
+ foundValue = true;
+ } catch (Exception e2) {
+ LOG.error(
+ "Caught exception trying to call "
+ + m.getName(),
+ e2);
+ }
+ }
+ } catch (Exception e1) {
+ LOG.warn(
+ "Could not find a suitable constructor for "
+ + paramClass.getName(),
+ e1);
+ }
+
+ if (paramObj == null) {
+ LOG.warn("Could not find builder class "
+ + builderName
+ + " and could not find a String or Long constructor - trying just to set passing paramValue");
+
+ }
+
+ } catch (Exception e) {
+ LOG.error(
+ "Caught exception trying to create builder "
+ + builderName, e);
+ }
+
+ if (paramObj != null) {
+
+ try {
+
+ Method buildMethod = builderClass
+ .getMethod("build");
+ //LOG.debug("Calling "
+ // + paramObj.getClass().getName()
+ // + "." + buildMethod.getName()
+ // + "()");
+ Object builtObj = buildMethod
+ .invoke(paramObj);
+
+ boolean isAccessible = m.isAccessible();
+ if (!isAccessible) {
+ m.setAccessible(true);
+ }
+
+ //LOG.debug("Calling "
+ // + toObj.getClass().getName()
+ // + "." + m.getName() + "()");
+ m.invoke(toObj, builtObj);
+ if (!isAccessible) {
+ m.setAccessible(isAccessible);
+ }
+ foundValue = true;
+
+ } catch (Exception e) {
+ LOG.error(
+ "Caught exception trying to set Yang-generated class expected by"
+ + toClass.getName()
+ + "."
+ + m.getName()
+ + "() from Properties entry",
+ e);
+ }
+ } else {
+ try {
+ boolean isAccessible = m.isAccessible();
+ if (!isAccessible) {
+ m.setAccessible(true);
+ }
+ //LOG.debug("Calling "
+ // + toObj.getClass().getName()
+ // + "." + m.getName() + "("
+ // + paramValue + ")");
+ m.invoke(toObj, paramValue);
+ if (!isAccessible) {
+ m.setAccessible(isAccessible);
+ }
+ foundValue = true;
+
+ } catch (Exception e) {
+ LOG.error(
+ "Caught exception trying to convert value returned by"
+ + toClass.getName()
+ + "."
+ + m.getName()
+ + TO_PROPERTIES_STRING,
+ e);
+ }
+ }
+ }
+ }
+ }else {
+
+ // Setter's argument is not a yang-generated class. See
+ // if it is a List.
+
+ if (List.class.isAssignableFrom(paramClass)) {
+
+ //LOG.debug("Parameter class " + paramClass.getName()
+ // + " is a List");
+
+ // Figure out what type of args are in List and pass
+ // that to toList().
+
+ Type paramType = m.getGenericParameterTypes()[0];
+ Type elementType = ((ParameterizedType) paramType)
+ .getActualTypeArguments()[0];
+ Object paramObj = new LinkedList();
+ try {
+ paramObj = toList(props, propName,
+ (List) paramObj, (Class) elementType);
+ } catch (Exception e) {
+ LOG.error("Caught exception trying to create list expected as argument to "
+ + toClass.getName() + "." + m.getName());
+ }
+
+ if (paramObj != null) {
+ try {
+ boolean isAccessible = m.isAccessible();
+ if (!isAccessible) {
+ m.setAccessible(true);
+ }
+ //LOG.debug("Calling "
+ // + toObj.getClass().getName() + "."
+ // + m.getName() + "(" + paramValue
+ // + ")");
+ m.invoke(toObj, paramObj);
+ if (!isAccessible) {
+ m.setAccessible(isAccessible);
+ }
+ foundValue = true;
+
+ } catch (Exception e) {
+ LOG.error(
+ "Caught exception trying to convert List returned by"
+ + toClass.getName() + "."
+ + m.getName()
+ + TO_PROPERTIES_STRING,
+ e);
+ }
+ }
+ } else {
+
+ // Setter expects something that is not a List and
+ // not yang-generated. Just pass the parameter value
+
+ //LOG.debug("Parameter class "
+ // + paramClass.getName()
+ // + " is not a yang-generated class or a List");
+
+ if (paramValue != null) {
+
+ Object constObj = null;
+
+ try {
+ // See if I can find a constructor I can use
+ Constructor[] constructors = paramClass
+ .getConstructors();
+ // Is there a String constructor?
+ for (Constructor c : constructors) {
+ Class[] cParms = c.getParameterTypes();
+ if ((cParms != null)
+ && (cParms.length == 1)) {
+ if (String.class
+ .isAssignableFrom(cParms[0])) {
+ constObj = c
+ .newInstance(paramValue);
+ }
+ }
+ }
+
+ if (constObj == null) {
+ // Is there a Long constructor?
+ for (Constructor c : constructors) {
+ Class[] cParms = c
+ .getParameterTypes();
+ if ((cParms != null)
+ && (cParms.length == 1)) {
+ if (Long.class
+ .isAssignableFrom(cParms[0])) {
+ constObj = c
+ .newInstance(Long
+ .parseLong(paramValue));
+ }
+ }
+ }
+
+ }
+
+ if (constObj != null) {
+ try {
+ //LOG.debug("Calling "
+ // + toObj.getClass()
+ // .getName() + "."
+ // + m.getName() + "("
+ // + constObj + ")");
+ m.invoke(toObj, constObj);
+ foundValue = true;
+ } catch (Exception e2) {
+ LOG.error(
+ "Caught exception trying to call "
+ + m.getName(), e2);
+ }
+ } else {
+ try {
+ boolean isAccessible = m
+ .isAccessible();
+ if (!isAccessible) {
+ m.setAccessible(true);
+ }
+ //LOG.debug("Calling "
+ // + toObj.getClass()
+ // .getName() + "."
+ // + m.getName() + "("
+ // + paramValue + ")");
+ m.invoke(toObj, paramValue);
+ if (!isAccessible) {
+ m.setAccessible(isAccessible);
+ }
+ foundValue = true;
+
+ } catch (Exception e) {
+ LOG.error(
+ "Caught exception trying to convert value returned by"
+ + toClass.getName()
+ + "."
+ + m.getName()
+ + TO_PROPERTIES_STRING,
+ e);
+ }
+ }
+ } catch (Exception e1) {
+ LOG.warn(
+ "Could not find a suitable constructor for "
+ + paramClass.getName(), e1);
+ }
+
+ /*
+ * try { boolean isAccessible =
+ * m.isAccessible(); if (!isAccessible) {
+ * m.setAccessible(true); } LOG.debug("Calling "
+ * + toObj.getClass().getName() + "." +
+ * m.getName() + "(" + paramValue + ")");
+ * m.invoke(toObj, paramValue); if
+ * (!isAccessible) {
+ * m.setAccessible(isAccessible); } foundValue =
+ * true;
+ *
+ * } catch (Exception e) { LOG.error(
+ * "Caught exception trying to convert value returned by"
+ * + toClass.getName() + "." + m.getName() +
+ * "() to Properties entry", e); }
+ */
+ }
+ }
+ }
+ } // End of section handling "setter" method
+ } // End of loop through Methods
+ } // End of section handling yang-generated class
+
+ if (foundValue) {
+ return (toObj);
+ } else {
+ return (null);
+ }
+ }
+
+ public static Properties getProperties(PrintStream pstr, String pfx,
+ Class toClass) {
+ boolean foundValue = false;
+
+ //LOG.debug("Analyzing " + toClass.getName() + " class : pfx " + pfx);
+
+ if (isYangGenerated(toClass)
+ && (!Identifier.class.isAssignableFrom(toClass))) {
+ // Class is yang generated.
+ //LOG.debug(toClass.getName() + " is a Yang-generated class");
+
+ if (toClass.getName().endsWith("Key")) {
+ if (Identifier.class.isAssignableFrom(toClass)) {
+ //LOG.debug(Identifier.class.getName()
+ // + " is assignable from " + toClass.getName());
+ } else {
+
+ //LOG.debug(Identifier.class.getName()
+ // + " is NOT assignable from " + toClass.getName());
+ }
+ }
+
+ String propNamePfx = null;
+ if (pfx.endsWith("]")) {
+ propNamePfx = pfx;
+ }else if(pfx.indexOf(".CLASS_FOUND") != -1){
+ pfx = pfx.replace(".CLASS_FOUND","");
+ propNamePfx = pfx + "."
+ + toLowerHyphen(toClass.getSimpleName());
+ } else {
+
+ if ((pfx != null) && (pfx.length() > 0)) {
+ propNamePfx = pfx + "."
+ + toLowerHyphen(toClass.getSimpleName());
+ } else {
+ propNamePfx = toLowerHyphen(toClass.getSimpleName());
+ }
+
+ if (propNamePfx.endsWith(BUILDER)) {
+ propNamePfx = propNamePfx.substring(0, propNamePfx.length()
+ - BUILDER.length());
+ }
+
+ if (propNamePfx.endsWith(IMPL)) {
+ propNamePfx = propNamePfx.substring(0, propNamePfx.length()
+ - IMPL.length());
+ }
+ }
+
+ // Iterate through getter methods to figure out values we need to
+ // set
+
+ for (Method m : toClass.getMethods()) {
+ //LOG.debug("Is " + m.getName() + " method a getter?");
+ if (isGetter(m)) {
+ // LOG.debug(m.getName() + " is a getter");
+ Class returnClass = m.getReturnType();
+
+ String fieldName = toLowerHyphen(m.getName().substring(3));
+ if(m != null && m.getName().matches("^is[A-Z].*")){
+ fieldName = toLowerHyphen(m.getName().substring(2));
+ }
+ fieldName = fieldName.substring(0, 1).toLowerCase()
+ + fieldName.substring(1);
+
+ String propName = propNamePfx + "." + fieldName;
+ //System.out.println("****" + propName);
+
+ // Is the return type a yang generated class?
+ if (isYangGenerated(returnClass)) {
+ // Is it an enum?
+ if (returnClass.isEnum()) {
+
+ //LOG.debug(m.getName() + " is an Enum");
+ //pstr.print("\n" + propName);
+ //pstr.print("\n" + propName + ":Enum:" + Arrays.asList(returnClass.getEnumConstants()) + "\n");
+ pstr.print("\"" + propName + ":Enum:" + Arrays.asList(returnClass.getEnumConstants()) + "\",");
+ prop.setProperty(propName,"");
+ propList.add(propName);
+
+ } else {
+
+ String simpleName = returnClass.getSimpleName();
+ //System.out.println("simpleName:" + simpleName);
+
+ if ("Ipv4Address".equals(simpleName) || "Ipv6Address".equals(simpleName) || "IpAddress".equals(simpleName) || "Ipv4Prefix".equals(simpleName) || "Ipv6Prefix".equals(simpleName) || "IpPrefix".equals(simpleName)) {
+ //LOG.debug(m.getName()+" is an "+simpleName);
+ //pstr.print("\n" + propName);
+ //pstr.print("\n" + propName + ":" + simpleName + "\n");
+ pstr.print("\"" + propName + ":" + simpleName + "\",");
+ prop.setProperty(propName,"");
+ propList.add(propName);
+ } else {
+ boolean isString = false;
+ boolean isNumber = false;
+ boolean isBoolean = false;
+ boolean isIdentifier = false;
+ //System.out.println("simpleName:" + simpleName);
+ //System.out.println("propName:" + propName);
+ for(Method mthd : returnClass.getMethods()){
+ String methodName = mthd.getName();
+ //System.out.println("methodName:" + methodName);
+ if(methodName.equals("getValue")){
+ Class retType = mthd.getReturnType();
+ //System.out.println("retType:" + retType);
+ isString = String.class.isAssignableFrom(retType);
+ isNumber = Number.class.isAssignableFrom(retType);
+ isBoolean = Boolean.class.isAssignableFrom(retType);
+ isIdentifier = Identifier.class.isAssignableFrom(retType);
+ //System.out.println("isString:" + isString);
+ //System.out.println("isNumber:" + isNumber);
+ //System.out.println("isNumber:" + isNumber);
+ break;
+ }
+ }
+
+ if(isString){
+ pstr.print("\"" + propName + ":String\",");
+ prop.setProperty(propName,"");
+ propList.add(propName);
+ }else if(isNumber){
+ pstr.print("\"" + propName + ":Number\",");
+ prop.setProperty(propName,"");
+ propList.add(propName);
+ }else if(isBoolean){
+ pstr.print("\"" + propName + ":Boolean\",");
+ prop.setProperty(propName,"");
+ propList.add(propName);
+ }else if(isIdentifier){
+ //System.out.println("isIdentifier");
+ //isIdentifer so skipping
+ continue;
+ }else{
+ /*
+ System.out.println("fieldName:" + fieldName);
+ System.out.println("simpleName:" + simpleName);
+ System.out.println("returnClass:" + returnClass);
+ System.out.println("pstr:" + pstr);
+ System.out.println("propNamePfx:" + propNamePfx);
+ */
+ getProperties(pstr, propNamePfx + ".CLASS_FOUND", returnClass);
+ }
+ }
+
+ }
+ } else {
+
+ // Setter's argument is not a yang-generated class. See
+ // if it is a List.
+
+ if (List.class.isAssignableFrom(returnClass)) {
+
+ //LOG.debug("Parameter class "
+ // + returnClass.getName() + " is a List");
+
+ // Figure out what type of args are in List and pass
+ // that to toList().
+
+ Type returnType = m.getGenericReturnType();
+ Type elementType = ((ParameterizedType) returnType)
+ .getActualTypeArguments()[0];
+ Class elementClass = (Class) elementType;
+ //LOG.debug("Calling printPropertyList on list type ("
+ //+ elementClass.getName()
+ // + "), pfx is ("
+ // + pfx
+ // + "), toClass is ("
+ // + toClass.getName() + ")");
+ //System.out.println("List propNamePfx:" + propNamePfx+ "." + toLowerHyphen(elementClass.getSimpleName()) + "[]");
+ if(String.class.isAssignableFrom(elementClass)){
+ pstr.print("\"" + propName + ":[String,String,...]\",");
+ prop.setProperty(propName,"");
+ propList.add(propName);
+ }else if(Number.class.isAssignableFrom(elementClass)){
+ pstr.print("\"" + propName + ":[Number,Number,...]\",");
+ prop.setProperty(propName,"");
+ propList.add(propName);
+ }else if(Boolean.class.isAssignableFrom(elementClass)){
+ pstr.print("\"" + propName + ":[Boolean,Boolean,...]\",");
+ prop.setProperty(propName,"");
+ propList.add(propName);
+ }else if(Identifier.class.isAssignableFrom(elementClass)){
+ continue;
+ }else{
+ getProperties(
+ pstr,
+ propNamePfx
+ + "."
+ + toLowerHyphen(elementClass
+ .getSimpleName()) + "[]",
+ elementClass);
+ }
+
+ } else if (!returnClass.equals(Class.class)) {
+
+ // Setter expects something that is not a List and
+ // not yang-generated. Just pass the parameter value
+
+ //LOG.debug("Parameter class "
+ // + returnClass.getName()
+ // + " is not a yang-generated class or a List");
+
+ //pstr.print("\n" + propName);
+ String className=returnClass.getName();
+ int nClassNameIndex = className.lastIndexOf('.');
+ String nClassName = className;
+ if(nClassNameIndex != -1){
+ nClassName=className.substring(nClassNameIndex+1);
+ }
+ boolean isString = String.class.isAssignableFrom(returnClass);
+ boolean isNumber = Number.class.isAssignableFrom(returnClass);
+ boolean isBoolean = Boolean.class.isAssignableFrom(returnClass);
+ //pstr.print("\n" + propName +":" + nClassName +"\n");
+ boolean isIdentifier = Identifier.class.isAssignableFrom(returnClass);
+ if(!isIdentifier && !nClassName.equals("[C")){
+ if(isNumber){
+ pstr.print("\"" + propName +":Number\",");
+ }else if(isBoolean){
+ pstr.print("\"" + propName +":Boolean\",");
+ }else{
+ if(nClassName.equals("[B")){
+ pstr.print("\"" + propName +":Binary\",");
+ }else{
+ pstr.print("\"" + propName +":" + nClassName +"\",");
+ }
+ }
+ prop.setProperty(propName,"");
+ propList.add(propName);
+ }
+
+ }
+ }
+ } // End of section handling "setter" method
+ } // End of loop through Methods
+ } // End of section handling yang-generated class
+
+ return prop;
+ }
+
+ public static boolean isYangGenerated(Class c) {
+ if (c == null) {
+ return (false);
+ } else {
+ //System.out.println(c.getName());
+ return (c.getName().startsWith("org.opendaylight.yang.gen."));
+ }
+ }
+
+ public static boolean isIpv4Address(Class c) {
+
+ if (c == null ) {
+ return (false);
+ }
+ String simpleName = c.getSimpleName();
+ return ("Ipv4Address".equals(simpleName)) ;
+ }
+
+ public static boolean isIpv6Address(Class c) {
+
+ if (c == null ) {
+ return (false);
+ }
+ String simpleName = c.getSimpleName();
+ return ("Ipv6Address".equals(simpleName)) ;
+ }
+ public static boolean isIpv4Prefix(Class c) {
+
+ if (c == null ) {
+ return (false);
+ }
+ String simpleName = c.getSimpleName();
+ //System.out.println("simpleName:" + simpleName);
+ return ("Ipv4Prefix".equals(simpleName)) ;
+ }
+
+ public static boolean isIpv6Prefix(Class c) {
+
+ if (c == null ) {
+ return (false);
+ }
+ String simpleName = c.getSimpleName();
+ //System.out.println("simpleName:" + simpleName);
+ return ("Ipv6Prefix".equals(simpleName)) ;
+ }
+
+ public static String toLowerHyphen(String inStr) {
+ if (inStr == null) {
+ return (null);
+ }
+
+ String str = inStr.substring(0, 1).toLowerCase();
+ if (inStr.length() > 1) {
+ str = str + inStr.substring(1);
+ }
+
+ String regex = "([a-z0-9A-Z])(?=[A-Z])";
+ String replacement = "$1-";
+
+ String retval = str.replaceAll(regex, replacement).toLowerCase();
+
+ //LOG.debug("Converting " + inStr + " => " + str + " => " + retval);
+ return (retval);
+ }
+
+ public static String toUpperCamelCase(String inStr) {
+ if (inStr == null) {
+ return (null);
+ }
+
+ String[] terms = inStr.split("-");
+ StringBuffer sbuff = new StringBuffer();
+ // Check if string begins with a digit
+ if (Character.isDigit(inStr.charAt(0))) {
+ sbuff.append('_');
+ }
+ for (String term : terms) {
+ sbuff.append(term.substring(0, 1).toUpperCase());
+ if (term.length() > 1) {
+ sbuff.append(term.substring(1));
+ }
+ }
+ return (sbuff.toString());
+
+ }
+
+ public static boolean isGetter(Method m) {
+ //System.out.println(m);
+ if (m == null) {
+ return (false);
+ }
+
+ if (Modifier.isPublic(m.getModifiers())
+ && (m.getParameterTypes().length == 0)) {
+ if ((m.getName().matches("^is[A-Z].*") || m.getName().matches("^get[A-Z].*"))
+ && m.getReturnType().equals(Boolean.class)) {
+ return (true);
+ }
+ if (m.getName().matches("^get[A-Z].*")
+ && !m.getReturnType().equals(void.class)) {
+ return (true);
+ }
+
+ }
+
+ return (false);
+ }
+
+ public static boolean isSetter(Method m) {
+ if (m == null) {
+ return (false);
+ }
+
+ if (Modifier.isPublic(m.getModifiers())
+ && (m.getParameterTypes().length == 1)) {
+ if (m.getName().matches("^set[A-Z].*")) {
+ Class[] paramTypes = m.getParameterTypes();
+ if (paramTypes[0].isAssignableFrom(Identifier.class)
+ || Identifier.class.isAssignableFrom(paramTypes[0])) {
+ return (false);
+ } else {
+ return (true);
+ }
+ }
+
+ }
+
+ return (false);
+ }
+
+ public static void main(String[] args){
+
+ try(PrintStream ps = new PrintStream(new FileOutputStream(FileDescriptor.out))){
+ PrintYangToProp printYangToProp = new PrintYangToProp();
+ String className = args[0];
+ //ClassLoader classLoader = PrintYangToProp.class.getClassLoader();
+ //Class aClass = classLoader.loadClass(className);
+ Class cl = Class.forName(className);
+ //printPropertyList(ps,"",cl);
+ //JsonObject jsonObj = Json.createObjectBuilder().build();
+ Properties p = getProperties(ps,"",cl);
+ //System.out.println(p);
+
+ }catch(Exception e){
+ e.printStackTrace();
+ }
+ }
+
+
+}
diff --git a/core/sli/provider/src/main/java/org/onap/ccsdk/sli/core/sli/provider/SvcLogicClassResolver.java b/core/sli/provider/src/main/java/org/onap/ccsdk/sli/core/sli/provider/SvcLogicClassResolver.java
new file mode 100644
index 000000000..08e957f1d
--- /dev/null
+++ b/core/sli/provider/src/main/java/org/onap/ccsdk/sli/core/sli/provider/SvcLogicClassResolver.java
@@ -0,0 +1,98 @@
+package org.onap.ccsdk.sli.core.sli.provider;
+
+import java.util.HashMap;
+import org.onap.ccsdk.sli.core.sli.SvcLogicAdaptor;
+import org.onap.ccsdk.sli.core.sli.SvcLogicJavaPlugin;
+import org.onap.ccsdk.sli.core.sli.SvcLogicRecorder;
+import org.onap.ccsdk.sli.core.sli.SvcLogicResource;
+import org.onap.ccsdk.sli.core.sli.provider.base.SvcLogicResolver;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.ServiceReference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class SvcLogicClassResolver implements SvcLogicResolver {
+
+ private static final Logger LOG = LoggerFactory.getLogger(SvcLogicClassResolver.class);
+ private static HashMap<String, SvcLogicAdaptor> adaptorMap = new HashMap<>();
+
+ public void registerAdaptor(SvcLogicAdaptor adaptor) {
+ String name = adaptor.getClass().getName();
+ LOG.info("Registering adaptor " + name);
+ adaptorMap.put(name, adaptor);
+
+ }
+
+ public void unregisterAdaptor(String name) {
+ if (adaptorMap.containsKey(name)) {
+ LOG.info("Unregistering " + name);
+ adaptorMap.remove(name);
+ }
+ }
+
+ private SvcLogicAdaptor getAdaptorInstance(String name) {
+ if (adaptorMap.containsKey(name)) {
+ return adaptorMap.get(name);
+ } else {
+
+ SvcLogicAdaptor adaptor = (SvcLogicAdaptor) resolve(name);
+
+ if (adaptor != null) {
+ registerAdaptor(adaptor);
+ }
+
+ return adaptor;
+ }
+ }
+
+ private Object resolve(String className) {
+
+ Bundle bundle = FrameworkUtil.getBundle(SvcLogicClassResolver.class);
+
+ if (bundle == null) {
+ // Running outside OSGi container (e.g. jUnit). Use Reflection
+ // to resolve class
+ try {
+ return (Class.forName(className).newInstance());
+ } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) {
+
+ LOG.error("Could not resolve class " + className, e);
+ return null;
+ }
+
+ } else {
+ BundleContext bctx = bundle.getBundleContext();
+ ServiceReference sref = bctx.getServiceReference(className);
+ if (sref != null) {
+ return bctx.getService(sref);
+ } else {
+
+ LOG.warn("Could not find service reference object for class " + className);
+ return null;
+ }
+ }
+ }
+
+ @Override
+ public SvcLogicResource getSvcLogicResource(String resourceName) {
+ return (SvcLogicResource) resolve(resourceName);
+ }
+
+ @Override
+ public SvcLogicRecorder getSvcLogicRecorder(String recorderName) {
+ return (SvcLogicRecorder) resolve(recorderName);
+ }
+
+ @Override
+ public SvcLogicJavaPlugin getSvcLogicJavaPlugin(String pluginName) {
+ return (SvcLogicJavaPlugin) resolve(pluginName);
+ }
+
+ @Override
+ public SvcLogicAdaptor getSvcLogicAdaptor(String adaptorName) {
+ return getAdaptorInstance(adaptorName);
+ }
+
+}
diff --git a/core/sli/provider/src/main/java/org/onap/ccsdk/sli/core/sli/provider/SvcLogicPropertiesProviderImpl.java b/core/sli/provider/src/main/java/org/onap/ccsdk/sli/core/sli/provider/SvcLogicPropertiesProviderImpl.java
new file mode 100644
index 000000000..aad7a5a6d
--- /dev/null
+++ b/core/sli/provider/src/main/java/org/onap/ccsdk/sli/core/sli/provider/SvcLogicPropertiesProviderImpl.java
@@ -0,0 +1,189 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * onap
+ * ================================================================================
+ * Copyright (C) 2016 - 2017 ONAP
+ * Modifications Copyright (C) 2018 IBM.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.sli.provider;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Optional;
+import java.util.Properties;
+import java.util.Vector;
+
+import org.onap.ccsdk.sli.core.sli.ConfigurationException;
+import org.onap.ccsdk.sli.core.sli.provider.base.SvcLogicPropertiesProvider;
+import org.onap.ccsdk.sli.core.utils.JREFileResolver;
+import org.onap.ccsdk.sli.core.utils.KarafRootFileResolver;
+import org.onap.ccsdk.sli.core.utils.PropertiesFileResolver;
+import org.onap.ccsdk.sli.core.utils.common.CoreDefaultFileResolver;
+import org.onap.ccsdk.sli.core.utils.common.SdncConfigEnvVarFileResolver;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Responsible for determining the properties file to use and instantiating the
+ * <code>DBResourceManager</code> Service. The priority for properties file
+ * resolution is as follows:
+ *
+ * <ol>
+ * <li>A directory identified by the system environment variable
+ * <code>SDNC_CONFIG_DIR</code></li>
+ * <li>The default directory <code>DEFAULT_DBLIB_PROP_DIR</code></li>
+ * <li>A directory identified by the JRE argument
+ * <code>dblib.properties</code></li>
+ * <li>A <code>dblib.properties</code> file located in the karaf root
+ * directory</li>
+ * </ol>
+ */
+public class SvcLogicPropertiesProviderImpl implements SvcLogicPropertiesProvider {
+
+ private static final Logger log = LoggerFactory.getLogger(SvcLogicPropertiesProviderImpl.class);
+
+ /**
+ * The name of the properties file for database configuration
+ */
+ private static final String SVCLOGIC_PROP_FILE_NAME = "svclogic.properties";
+
+ /**
+ * A prioritized list of strategies for resolving dblib properties files.
+ */
+ private Vector<PropertiesFileResolver> sliPropertiesFileResolvers = new Vector<>();
+
+ /**
+ * The configuration properties for the db connection.
+ */
+ private Properties properties;
+
+ /**
+ * Set up the prioritized list of strategies for resolving dblib properties
+ * files.
+ */
+ public SvcLogicPropertiesProviderImpl() {
+ sliPropertiesFileResolvers
+ .add(new SdncConfigEnvVarFileResolver("Using property file (1) from environment variable"));
+ sliPropertiesFileResolvers.add(new CoreDefaultFileResolver("Using property file (2) from default directory"));
+
+ sliPropertiesFileResolvers.add(
+ new JREFileResolver("Using property file (3) from JRE argument", SvcLogicPropertiesProviderImpl.class));
+ sliPropertiesFileResolvers.add(new KarafRootFileResolver("Using property file (4) from karaf root", this));
+
+ // determines properties file as according to the priority described in the
+ // class header comment
+ final File propertiesFile = determinePropertiesFile(this);
+ if (propertiesFile != null) {
+ try (FileInputStream fileInputStream = new FileInputStream(propertiesFile)) {
+ properties = new Properties();
+ properties.load(fileInputStream);
+ } catch (final IOException e) {
+ log.error("Failed to load properties for file: {}", propertiesFile.toString(),
+ new ConfigurationException("Failed to load properties for file: " + propertiesFile.toString(),
+ e));
+ }
+ } else {
+ // Try to read properties as resource
+
+ InputStream propStr = getClass().getResourceAsStream("/" + SVCLOGIC_PROP_FILE_NAME);
+ if (propStr != null) {
+ properties = new Properties();
+ try {
+ properties.load(propStr);
+ propStr.close();
+ } catch (IOException e) {
+ log.error("IO Exception",e);
+ properties = null;
+ }
+ }
+
+ }
+
+ if (properties == null) {
+ reportFailure("Missing configuration properties resource(3)", new ConfigurationException(
+ "Missing configuration properties resource(3): " + SVCLOGIC_PROP_FILE_NAME));
+ }
+ }
+
+ /**
+ * Extract svclogic config properties.
+ *
+ * @return the svclogic config properties
+ */
+ public Properties getProperties() {
+ return properties;
+ }
+
+ /**
+ * Reports the method chosen for properties resolution to the
+ * <code>Logger</code>.
+ *
+ * @param message
+ * Some user friendly message
+ * @param fileOptional
+ * The file location of the chosen properties file
+ * @return the file location of the chosen properties file
+ */
+ private static File reportSuccess(final String message, final Optional<File> fileOptional) {
+ if (fileOptional.isPresent()) {
+ final File file = fileOptional.get();
+ log.info("{} {}", message, file.getPath());
+ return file;
+ }
+ return null;
+ }
+
+ /**
+ * Reports fatal errors. This is the case in which no properties file could be
+ * found.
+ *
+ * @param message
+ * An appropriate fatal error message
+ * @param configurationException
+ * An exception describing what went wrong during resolution
+ */
+ private static void reportFailure(final String message, final ConfigurationException configurationException) {
+
+ log.error("{}", message, configurationException);
+ }
+
+ /**
+ * Determines the dblib properties file to use based on the following priority:
+ * <ol>
+ * <li>A directory identified by the system environment variable
+ * <code>SDNC_CONFIG_DIR</code></li>
+ * <li>The default directory <code>DEFAULT_DBLIB_PROP_DIR</code></li>
+ * <li>A directory identified by the JRE argument
+ * <code>dblib.properties</code></li>
+ * <li>A <code>dblib.properties</code> file located in the karaf root
+ * directory</li>
+ * </ol>
+ */
+ File determinePropertiesFile(final SvcLogicPropertiesProviderImpl resourceProvider) {
+
+ for (final PropertiesFileResolver sliPropertiesFileResolver : sliPropertiesFileResolvers) {
+ final Optional<File> fileOptional = sliPropertiesFileResolver.resolveFile(SVCLOGIC_PROP_FILE_NAME);
+ if (fileOptional.isPresent()) {
+ return reportSuccess(sliPropertiesFileResolver.getSuccessfulResolutionMessage(), fileOptional);
+ }
+ }
+
+ return null;
+ }
+}
diff --git a/core/sli/provider/src/main/java/org/onap/ccsdk/sli/core/sli/provider/SvcLogicService.java b/core/sli/provider/src/main/java/org/onap/ccsdk/sli/core/sli/provider/SvcLogicService.java
new file mode 100644
index 000000000..a23594ee3
--- /dev/null
+++ b/core/sli/provider/src/main/java/org/onap/ccsdk/sli/core/sli/provider/SvcLogicService.java
@@ -0,0 +1,52 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.sli.provider;
+
+import java.util.Properties;
+
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.core.sli.provider.base.SvcLogicServiceBase;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
+
+public interface SvcLogicService extends SvcLogicServiceBase {
+
+ String NAME = "org.onap.ccsdk.sli.core.sli.provider.SvcLogicService";
+
+ @Deprecated
+ Properties execute(String module, String rpc, String version, String mode, Properties parms) throws SvcLogicException;
+
+ /**
+ * Execute a directed graph
+ *
+ * @param module - module name
+ * @param rpc - rpc name
+ * @param version - version. If null, use active version
+ * @param mode - mode (sync/async)
+ * @param parms - parameters, used to set SvcLogicContext attributes
+ * @param domDataBroker - DOMDataBroker object
+ * @return final values of attributes from SvcLogicContext, as Properties
+ * @throws SvcLogicException
+ */
+ Properties execute(String module, String rpc, String version, String mode, Properties parms, DOMDataBroker domDataBroker) throws SvcLogicException;
+
+
+}
diff --git a/core/sli/provider/src/main/java/org/onap/ccsdk/sli/core/sli/provider/SvcLogicServiceImpl.java b/core/sli/provider/src/main/java/org/onap/ccsdk/sli/core/sli/provider/SvcLogicServiceImpl.java
new file mode 100755
index 000000000..92c2aa49a
--- /dev/null
+++ b/core/sli/provider/src/main/java/org/onap/ccsdk/sli/core/sli/provider/SvcLogicServiceImpl.java
@@ -0,0 +1,90 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Modifications Copyright (C) 2018 IBM.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.sli.provider;
+
+import java.util.Properties;
+import org.onap.ccsdk.sli.core.dblib.DbLibService;
+import org.onap.ccsdk.sli.core.sli.ConfigurationException;
+import org.onap.ccsdk.sli.core.sli.SvcLogicDblibStore;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.core.sli.SvcLogicStore;
+import org.onap.ccsdk.sli.core.sli.SvcLogicStoreFactory;
+import org.onap.ccsdk.sli.core.sli.provider.base.SvcLogicPropertiesProvider;
+import org.onap.ccsdk.sli.core.sli.provider.base.SvcLogicResolver;
+import org.onap.ccsdk.sli.core.sli.provider.base.SvcLogicServiceImplBase;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class SvcLogicServiceImpl extends SvcLogicServiceImplBase implements SvcLogicService {
+
+ private static final Logger LOG = LoggerFactory.getLogger(SvcLogicServiceImpl.class);
+
+ public SvcLogicServiceImpl(SvcLogicPropertiesProvider resourceProvider, SvcLogicResolver resolver)
+ throws SvcLogicException {
+ super(null, resolver);
+ properties = resourceProvider.getProperties();
+ this.store = getStore();
+ }
+
+ public SvcLogicServiceImpl(SvcLogicPropertiesProvider resourceProvider, DbLibService dbSvc,
+ SvcLogicResolver resolver) throws SvcLogicException {
+ super(null, resolver);
+ properties = resourceProvider.getProperties();
+ this.store = new SvcLogicDblibStore(dbSvc);
+ }
+
+ @Override
+ @Deprecated
+ // DomDataBroker is not being used, this should be removed eventually
+ public Properties execute(String module, String rpc, String version, String mode, Properties props,
+ DOMDataBroker domDataBroker) throws SvcLogicException {
+ return (execute(module, rpc, version, mode, props));
+ }
+
+ @Override
+ public SvcLogicStore getStore() throws SvcLogicException {
+ // Create and initialize SvcLogicStore object - used to access
+ // saved service logic.
+ if (store != null) {
+ return store;
+ }
+
+ try {
+ store = SvcLogicStoreFactory.getSvcLogicStore(properties);
+ } catch (Exception e) {
+ throw new ConfigurationException("Could not get service logic store", e);
+
+ }
+
+ try {
+ store.init(properties);
+ } catch (SvcLogicException e) {
+ throw new ConfigurationException("Could not get service logic store", e);
+ }
+
+ return store;
+ }
+
+}
diff --git a/core/sli/provider/src/main/resources/OSGI-INF/blueprint/sli-blueprint.xml b/core/sli/provider/src/main/resources/OSGI-INF/blueprint/sli-blueprint.xml
new file mode 100644
index 000000000..fb3ab9a03
--- /dev/null
+++ b/core/sli/provider/src/main/resources/OSGI-INF/blueprint/sli-blueprint.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+ xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0"
+ odl:use-default-for-reference-types="true">
+
+ <bean id="propProvider" class="org.onap.ccsdk.sli.core.sli.provider.SvcLogicPropertiesProviderImpl" />
+ <reference id="dblibService" interface="org.onap.ccsdk.sli.core.dblib.DbLibService" />
+ <bean id="svcLogicClassResolver" class="org.onap.ccsdk.sli.core.sli.provider.SvcLogicClassResolver" />
+
+ <bean id="svcLogicService" class="org.onap.ccsdk.sli.core.sli.provider.SvcLogicServiceImpl">
+ <argument ref="propProvider" />
+ <argument ref="dblibService" />
+ <argument ref="svcLogicClassResolver" />
+ </bean>
+
+ <service ref="svcLogicService">
+ <interfaces>
+ <value>org.onap.ccsdk.sli.core.sli.provider.SvcLogicService</value>
+ </interfaces>
+ </service>
+
+ <bean id="fileRecorder" class="org.onap.ccsdk.sli.core.sli.recording.FileRecorder" />
+ <!-- Implementation name was chosen over interface name due to the fact that this Service
+ was previously registered using the implementation name rather than the interface name.
+ To ensure backwards compatibility with abstractions polling the Service Registry for the
+ fileRecorder, the implementation name was chosen here. -->
+ <service ref="fileRecorder" interface="org.onap.ccsdk.sli.core.sli.recording.FileRecorder" />
+
+ <bean id="slf4jRecorder" class="org.onap.ccsdk.sli.core.sli.recording.Slf4jRecorder" />
+ <!-- Implementation name was chosen over interface name due to the fact that this Service
+ was previously registered using the implementation name rather than the interface name.
+ To ensure backwards compatibility with abstractions polling the Service Registry for the
+ slf4jRecorder, the implementation name was chosen here. -->
+ <service ref="slf4jRecorder" interface="org.onap.ccsdk.sli.core.sli.recording.Slf4jRecorder" />
+
+</blueprint>
diff --git a/core/sli/provider/src/main/resources/org/opendaylight/blueprint/sli-blueprint.xml b/core/sli/provider/src/main/resources/org/opendaylight/blueprint/sli-blueprint.xml
new file mode 100644
index 000000000..fb3ab9a03
--- /dev/null
+++ b/core/sli/provider/src/main/resources/org/opendaylight/blueprint/sli-blueprint.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+ xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0"
+ odl:use-default-for-reference-types="true">
+
+ <bean id="propProvider" class="org.onap.ccsdk.sli.core.sli.provider.SvcLogicPropertiesProviderImpl" />
+ <reference id="dblibService" interface="org.onap.ccsdk.sli.core.dblib.DbLibService" />
+ <bean id="svcLogicClassResolver" class="org.onap.ccsdk.sli.core.sli.provider.SvcLogicClassResolver" />
+
+ <bean id="svcLogicService" class="org.onap.ccsdk.sli.core.sli.provider.SvcLogicServiceImpl">
+ <argument ref="propProvider" />
+ <argument ref="dblibService" />
+ <argument ref="svcLogicClassResolver" />
+ </bean>
+
+ <service ref="svcLogicService">
+ <interfaces>
+ <value>org.onap.ccsdk.sli.core.sli.provider.SvcLogicService</value>
+ </interfaces>
+ </service>
+
+ <bean id="fileRecorder" class="org.onap.ccsdk.sli.core.sli.recording.FileRecorder" />
+ <!-- Implementation name was chosen over interface name due to the fact that this Service
+ was previously registered using the implementation name rather than the interface name.
+ To ensure backwards compatibility with abstractions polling the Service Registry for the
+ fileRecorder, the implementation name was chosen here. -->
+ <service ref="fileRecorder" interface="org.onap.ccsdk.sli.core.sli.recording.FileRecorder" />
+
+ <bean id="slf4jRecorder" class="org.onap.ccsdk.sli.core.sli.recording.Slf4jRecorder" />
+ <!-- Implementation name was chosen over interface name due to the fact that this Service
+ was previously registered using the implementation name rather than the interface name.
+ To ensure backwards compatibility with abstractions polling the Service Registry for the
+ slf4jRecorder, the implementation name was chosen here. -->
+ <service ref="slf4jRecorder" interface="org.onap.ccsdk.sli.core.sli.recording.Slf4jRecorder" />
+
+</blueprint>
diff --git a/core/sli/provider/src/test/java/org/onap/ccsdk/sli/core/sli/provider/ITCaseSvcLogicGraphExecutor.java b/core/sli/provider/src/test/java/org/onap/ccsdk/sli/core/sli/provider/ITCaseSvcLogicGraphExecutor.java
new file mode 100644
index 000000000..ad439cdb4
--- /dev/null
+++ b/core/sli/provider/src/test/java/org/onap/ccsdk/sli/core/sli/provider/ITCaseSvcLogicGraphExecutor.java
@@ -0,0 +1,265 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.sli.provider;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+
+import java.io.BufferedReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.Properties;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicGraph;
+import org.onap.ccsdk.sli.core.sli.SvcLogicParser;
+import org.onap.ccsdk.sli.core.sli.SvcLogicStore;
+import org.onap.ccsdk.sli.core.sli.SvcLogicStoreFactory;
+import org.onap.ccsdk.sli.core.sli.provider.base.AbstractSvcLogicNodeExecutor;
+import org.onap.ccsdk.sli.core.sli.provider.base.BlockNodeExecutor;
+import org.onap.ccsdk.sli.core.sli.provider.base.BreakNodeExecutor;
+import org.onap.ccsdk.sli.core.sli.provider.base.CallNodeExecutor;
+import org.onap.ccsdk.sli.core.sli.provider.base.ConfigureNodeExecutor;
+import org.onap.ccsdk.sli.core.sli.provider.base.DeleteNodeExecutor;
+import org.onap.ccsdk.sli.core.sli.provider.base.ExecuteNodeExecutor;
+import org.onap.ccsdk.sli.core.sli.provider.base.ExistsNodeExecutor;
+import org.onap.ccsdk.sli.core.sli.provider.base.ForNodeExecutor;
+import org.onap.ccsdk.sli.core.sli.provider.base.GetResourceNodeExecutor;
+import org.onap.ccsdk.sli.core.sli.provider.base.IsAvailableNodeExecutor;
+import org.onap.ccsdk.sli.core.sli.provider.base.NotifyNodeExecutor;
+import org.onap.ccsdk.sli.core.sli.provider.base.RecordNodeExecutor;
+import org.onap.ccsdk.sli.core.sli.provider.base.ReleaseNodeExecutor;
+import org.onap.ccsdk.sli.core.sli.provider.base.ReserveNodeExecutor;
+import org.onap.ccsdk.sli.core.sli.provider.base.ReturnNodeExecutor;
+import org.onap.ccsdk.sli.core.sli.provider.base.SaveNodeExecutor;
+import org.onap.ccsdk.sli.core.sli.provider.base.SetNodeExecutor;
+import org.onap.ccsdk.sli.core.sli.provider.base.SvcLogicPropertiesProvider;
+import org.onap.ccsdk.sli.core.sli.provider.base.SwitchNodeExecutor;
+import org.onap.ccsdk.sli.core.sli.provider.base.UpdateNodeExecutor;
+import org.onap.ccsdk.sli.core.sli.provider.base.WhileNodeExecutor;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ITCaseSvcLogicGraphExecutor {
+
+ private static final Logger LOG = LoggerFactory.getLogger(SvcLogicGraph.class);
+ private static final Map<String, AbstractSvcLogicNodeExecutor> BUILTIN_NODES = new HashMap<String, AbstractSvcLogicNodeExecutor>() {
+ {
+ put("block", new BlockNodeExecutor());
+ put("break", new BreakNodeExecutor());
+ put("call", new CallNodeExecutor());
+ put("configure", new ConfigureNodeExecutor());
+ put("delete", new DeleteNodeExecutor());
+ put("execute", new ExecuteNodeExecutor());
+ put("exists", new ExistsNodeExecutor());
+ put("for", new ForNodeExecutor());
+ put("get-resource", new GetResourceNodeExecutor());
+ put("is-available", new IsAvailableNodeExecutor());
+ put("notify", new NotifyNodeExecutor());
+ put("record", new RecordNodeExecutor());
+ put("release", new ReleaseNodeExecutor());
+ put("reserve", new ReserveNodeExecutor());
+ put("return", new ReturnNodeExecutor());
+ put("save", new SaveNodeExecutor());
+ put("set", new SetNodeExecutor());
+ put("switch", new SwitchNodeExecutor());
+ put("update", new UpdateNodeExecutor());
+ put("while", new WhileNodeExecutor());
+
+ }
+ };
+
+ private static SvcLogicClassResolver svcLogicClassResolver;
+
+ @BeforeClass
+ public static void setUpBeforeClass() throws Exception {
+
+ LOG.info("before class");
+
+ InputStream propStr = ITCaseSvcLogicGraphExecutor.class.getResourceAsStream("/svclogic.properties");
+
+ Properties svcprops = new Properties();
+ svcprops.load(propStr);
+
+ SvcLogicStore store = SvcLogicStoreFactory.getSvcLogicStore(svcprops);
+
+ assertNotNull(store);
+
+ SvcLogicParser parser = new SvcLogicParser();
+
+ SvcLogicPropertiesProvider resourceProvider = new SvcLogicPropertiesProviderImpl();
+ svcLogicClassResolver = new SvcLogicClassResolver();
+ SvcLogicServiceImpl svc = new SvcLogicServiceImpl(resourceProvider, svcLogicClassResolver);
+
+ for (String nodeType : BUILTIN_NODES.keySet()) {
+ svc.registerExecutor(nodeType, BUILTIN_NODES.get(nodeType));
+ }
+
+
+
+
+ }
+
+ @AfterClass
+ public static void tearDownAfterClass() throws Exception {
+ LOG.info("after class");
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ LOG.info("before");
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ LOG.info("after");
+ }
+
+ @Test
+ public void testExecute() {
+
+ try {
+ InputStream testStr = getClass().getResourceAsStream("/executor.tests");
+ BufferedReader testsReader = new BufferedReader(new InputStreamReader(testStr));
+
+ InputStream propStr = getClass().getResourceAsStream("/svclogic.properties");
+
+ Properties svcprops = new Properties();
+ svcprops.load(propStr);
+
+
+
+
+ SvcLogicParser parser = new SvcLogicParser();
+
+ // Loop through executor tests
+ SvcLogicPropertiesProvider resourceProvider = new SvcLogicPropertiesProvider() {
+ @Override
+ public Properties getProperties() {
+ return svcprops;
+ }
+ };
+ SvcLogicServiceImpl svc = new SvcLogicServiceImpl(resourceProvider, svcLogicClassResolver);
+ SvcLogicStore store = svc.getStore();
+ assertNotNull(store);
+ for (String nodeType : BUILTIN_NODES.keySet()) {
+
+
+ svc.registerExecutor(nodeType, BUILTIN_NODES.get(nodeType));
+
+ }
+ String testCaseLine = null;
+ while ((testCaseLine = testsReader.readLine()) != null) {
+
+ String[] testCaseFields = testCaseLine.split(":");
+ String testCaseFile = testCaseFields[0];
+ String testCaseMethod = testCaseFields[1];
+ String testCaseParameters = null;
+
+ if (testCaseFields.length > 2) {
+ testCaseParameters = testCaseFields[2];
+ }
+
+ SvcLogicContext ctx = new SvcLogicContext();
+ if (testCaseParameters != null) {
+ String[] testCaseParameterSettings = testCaseParameters.split(",");
+
+ for (int i = 0; i < testCaseParameterSettings.length; i++) {
+ String[] nameValue = testCaseParameterSettings[i].split("=");
+ if (nameValue != null) {
+ String name = nameValue[0];
+ String value = "";
+ if (nameValue.length > 1) {
+ value = nameValue[1];
+ }
+
+ ctx.setAttribute(name, value);
+ }
+ }
+ }
+
+ testCaseFile = testCaseFile.trim();
+
+ if (testCaseFile.length() > 0) {
+ if (!testCaseFile.startsWith("/")) {
+ testCaseFile = "/" + testCaseFile;
+ }
+ URL testCaseUrl = getClass().getResource(testCaseFile);
+ if (testCaseUrl == null) {
+ fail("Could not resolve test case file " + testCaseFile);
+ }
+
+
+ LinkedList<SvcLogicGraph> graphs = parser.parse(testCaseUrl.getPath());
+
+ assertNotNull(graphs);
+
+ // Load grqphs into db to support call node
+ SvcLogicParser.load(testCaseUrl.getPath(), store);
+ SvcLogicParser.activate("neutron", "canCreateNetwork", "1.0.0", "sync", store);
+ SvcLogicParser.activate("neutron", "switchTester", "1.0.0", "sync", store);
+ SvcLogicParser.activate("neutron", "forRecordTester", "1.0.0", "sync", store);
+ SvcLogicParser.activate("neutron", "whileNodeTester", "1.0.0", "sync", store);
+ SvcLogicParser.activate("neutron", "resourceTester", "1.0.0", "sync", store);
+ SvcLogicParser.activate("neutron", "configureTester", "1.0.0", "sync", store);
+ SvcLogicParser.activate("neutron", "javaPluginTester", "1.0.0", "sync", store);
+ SvcLogicParser.activate("neutron", "allNodesTester", "1.0.0", "sync", store);
+ SvcLogicParser.activate("neutron", "networkCreated", "1.0.0", "sync", store);
+
+ for (SvcLogicGraph graph : graphs) {
+ if (graph.getRpc().equals(testCaseMethod)) {
+ Properties props = ctx.toProperties();
+ LOG.info("SvcLogicContext before executing {}:", testCaseMethod);
+ for (Enumeration e1 = props.propertyNames(); e1.hasMoreElements(); ) {
+ String propName = (String) e1.nextElement();
+ LOG.info(propName + " = " + props.getProperty(propName));
+ }
+
+ svc.execute(graph, ctx);
+
+ props = ctx.toProperties();
+ LOG.info("SvcLogicContext after executing {}:", testCaseMethod);
+ for (Enumeration e2 = props.propertyNames(); e2.hasMoreElements(); ) {
+ String propName = (String) e2.nextElement();
+ LOG.info(propName + " = " + props.getProperty(propName));
+ }
+ }
+ }
+
+ }
+ }
+
+ } catch (Exception e) {
+ LOG.error("Caught exception executing directed graphs", e);
+ fail("Exception executing graphs");
+ }
+ }
+}
diff --git a/core/sli/provider/src/test/java/org/onap/ccsdk/sli/core/sli/provider/MdsalHelperTest.java b/core/sli/provider/src/test/java/org/onap/ccsdk/sli/core/sli/provider/MdsalHelperTest.java
new file mode 100755
index 000000000..93d9931d0
--- /dev/null
+++ b/core/sli/provider/src/test/java/org/onap/ccsdk/sli/core/sli/provider/MdsalHelperTest.java
@@ -0,0 +1,763 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.sli.provider;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.net.Inet6Address;
+import java.util.ArrayList;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.core.sliapi.rev161110.ExecuteGraphInput.Mode;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.core.sliapi.rev161110.ExecuteGraphInputBuilder;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.core.sliapi.rev161110.execute.graph.input.SliParameter;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.core.sliapi.rev161110.execute.graph.input.SliParameterBuilder;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.core.testmodel.rev190723.Builtin.SampleBits;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.core.testmodel.rev190723.Builtin.SampleEnumeration;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.core.testmodel.rev190723.Builtin.SampleUnion;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.core.testmodel.rev190723.Percentage;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.core.testmodel.rev190723.SampleContainer;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.core.testmodel.rev190723.SampleContainerBuilder;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.core.testmodel.rev190723.sample.container.LoginBuilder;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.core.testmodel.rev190723.sample.container.login.CustomerAddresses;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.core.testmodel.rev190723.sample.container.login.CustomerAddressesBuilder;
+import org.opendaylight.yang.gen.v1.test.TestObjectBuilder;
+import org.opendaylight.yang.gen.v1.test.WrapperObj;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.AsNumber;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.DomainName;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Dscp;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.HostBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IetfInetUtil;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddressBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddressNoZoneBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefixBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpVersion;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4AddressNoZone;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Prefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6AddressNoZone;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6FlowLabel;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Prefix;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.PortNumber;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Uri;
+import org.opendaylight.yangtools.yang.common.Empty;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import junit.framework.TestCase;
+
+public class MdsalHelperTest extends TestCase {
+ private static final Logger LOG = LoggerFactory.getLogger(MdsalHelperTest.class);
+ public static final String pathToSdnPropertiesFile = "src/test/resources/l3sdn.properties";
+
+ public void testSdnProperties() {
+
+ MdsalHelperTesterUtil.loadProperties(pathToSdnPropertiesFile);
+ assertEquals("synccomplete", MdsalHelperTesterUtil.mapEnumeratedValue("request-status", "synccomplete"));
+ assertEquals("asynccomplete", MdsalHelperTesterUtil.mapEnumeratedValue("request-status", "asynccomplete"));
+ assertEquals("notifycomplete", MdsalHelperTesterUtil.mapEnumeratedValue("request-status", "notifycomplete"));
+ assertEquals("service-configuration-operation",
+ MdsalHelperTesterUtil.mapEnumeratedValue("rpc-name", "service-configuration-operation"));
+ }
+
+ public void testNegativeSdnProperties() {
+ assertNotSame("synccomplete", MdsalHelperTesterUtil.mapEnumeratedValue("request-status", "Synccomplete"));
+ }
+
+ public void testToProperties() {
+
+ ExecuteGraphInputBuilder execBuilder = new ExecuteGraphInputBuilder();
+ SliParameterBuilder parmBuilder = new SliParameterBuilder();
+ List<SliParameter> params = new LinkedList<SliParameter>();
+
+ parmBuilder.setParameterName("boolean-parm");
+ parmBuilder.setBooleanValue(Boolean.TRUE);
+ params.add(parmBuilder.build());
+
+ parmBuilder.setParameterName("int-parm");
+ parmBuilder.setBooleanValue(null);
+ parmBuilder.setIntValue(1);
+ params.add(parmBuilder.build());
+
+ parmBuilder.setParameterName("str-parm");
+ parmBuilder.setIntValue(null);
+ parmBuilder.setStringValue("hello");
+ params.add(parmBuilder.build());
+
+ parmBuilder.setParameterName("ipaddress4-parm");
+ parmBuilder.setStringValue(null);
+ parmBuilder.setIpaddressValue(IpAddressBuilder.getDefaultInstance("127.0.0.1"));
+ params.add(parmBuilder.build());
+
+ parmBuilder.setParameterName("ipaddress6-parm");
+ parmBuilder.setIpaddressValue(IpAddressBuilder.getDefaultInstance("ef::1"));
+ params.add(parmBuilder.build());
+
+ parmBuilder.setParameterName("ipprefix-parm");
+ parmBuilder.setIpaddressValue(null);
+ parmBuilder.setIpprefixValue(IpPrefixBuilder.getDefaultInstance("10.0.0.0/24"));
+ params.add(parmBuilder.build());
+
+ parmBuilder.setParameterName("portnumber-parm");
+ parmBuilder.setIpprefixValue(null);
+ parmBuilder.setPortNumber(PortNumber.getDefaultInstance("8080"));
+ params.add(parmBuilder.build());
+
+ parmBuilder.setParameterName("dcsp-parm");
+ parmBuilder.setPortNumber(null);
+ parmBuilder.setDscp(Dscp.getDefaultInstance("57"));
+ params.add(parmBuilder.build());
+
+ execBuilder.setMode(Mode.Sync);
+ execBuilder.setModuleName("my-module");
+ execBuilder.setRpcName("do-it-now");
+ execBuilder.setSliParameter(params);
+
+ Properties props = new Properties();
+
+ MdsalHelperTesterUtil.toProperties(props, execBuilder);
+
+ LOG.info("Converted to properties");
+ for (Map.Entry<Object, Object> e : props.entrySet()) {
+ LOG.info(e.getKey().toString() + " = " + e.getValue().toString());
+
+ }
+
+ }
+
+ public void testToBuilder() {
+
+ Properties props = new Properties();
+
+ props.setProperty("execute-graph-input.mode", "Sync");
+ props.setProperty("execute-graph-input.module", "my-module");
+ props.setProperty("execute-graph-input.rpc", "do-it-now");
+ props.setProperty("execute-graph-input.sli-parameter[0].parameter-name", "bool-parm");
+ props.setProperty("execute-graph-input.sli-parameter[0].boolean-value", "true");
+ props.setProperty("execute-graph-input,sli-parameter[1].parameter-name", "int-param");
+ props.setProperty("execute-graph-input.sli-parameter[1].int-value", "1");
+ props.setProperty("execute-graph-input.sli-parameter[2].parameter-name", "str-param");
+ props.setProperty("execute-graph-input.sli-parameter[2].str-value", "hello");
+ props.setProperty("execute-graph-input.sli-parameter[3].parameter-name", "ipv4address-param");
+ props.setProperty("execute-graph-input.sli-parameter[3].ipaddress-value", "127.0.0.1");
+ props.setProperty("execute-graph-input.sli-parameter[4].parameter-name", "ipv6address-param");
+ props.setProperty("execute-graph-input.sli-parameter[4].ipaddress-value", "ef::1");
+ ExecuteGraphInputBuilder execBuilder = new ExecuteGraphInputBuilder();
+
+ MdsalHelperTesterUtil.toBuilder(props, execBuilder);
+
+ }
+
+ public void testToJavaEnum() throws Exception {
+ assertEquals("VENDOR6500MODEL", MdsalHelper.toJavaEnum("VENDOR_6500_MODEL"));
+ assertEquals("_2018HelloWorld", MdsalHelper.toJavaEnum("2018Hello World"));
+ assertEquals("SomethingElse", MdsalHelper.toJavaEnum("Something.Else"));
+ assertEquals("MyTestString", MdsalHelper.toJavaEnum("my-test-string"));
+ }
+
+ // During the default enumeration mapping no properties file is needed, the yang
+ // value is returned
+ // by the java object
+ public void testDefaultEnumerationMapping() throws Exception {
+ Properties props = new Properties();
+ MdsalHelper.toProperties(props, new WrapperObj());
+ assertEquals("4COS", props.getProperty("wrapper-obj.cos-model-type"));
+ }
+
+ // When no properties file exists the default java value will be returned if
+ // legacy enumeration
+ // mapping is enabled
+ public void testLegacyEnumerationMappingNoProperties() throws Exception {
+ Properties props = new Properties();
+ MdsalHelper.toProperties(props, new WrapperObj(), true);
+ assertEquals("_4COS", props.getProperty("wrapper-obj.cos-model-type"));
+ }
+
+ // When a properties file exists & legacy enumeration mapping is enabled the
+ // value from the
+ // properties file should be returned
+ public void testLegacyEnumerationMappingWithProperties() throws Exception {
+ MdsalHelper.loadProperties("src/test/resources/EnumerationMapping.properties");
+ Properties props = new Properties();
+ MdsalHelper.toProperties(props, new WrapperObj(), true);
+ assertEquals("HelloWorld", props.getProperty("wrapper-obj.cos-model-type"));
+ }
+
+ public void testSingleIpAddressToProperties() throws Exception {
+ Properties props = new Properties();
+ String ipAddress = "11.11.11.11";
+ MdsalHelper.toProperties(props, IpAddressBuilder.getDefaultInstance(ipAddress));
+ assertEquals(ipAddress, props.getProperty(""));
+ ipAddress = "cafe::8888";
+ MdsalHelper.toProperties(props, IpAddressBuilder.getDefaultInstance(ipAddress));
+ assertEquals(ipAddress, props.getProperty(""));
+ }
+
+ public void testSingleIpAddressToBuilder() throws Exception {
+ Properties props = new Properties();
+ String ipAddress = "11.11.11.11";
+ props.setProperty("test-object.single-ip", ipAddress);
+ TestObjectBuilder b = new TestObjectBuilder();
+ MdsalHelper.toBuilder(props, b);
+
+ assertEquals(ipAddress, String.valueOf(b.getSingleIp().stringValue()));
+
+ ipAddress = "cafe::8888";
+ props.setProperty("test-object.single-ip", ipAddress);
+ b = new TestObjectBuilder();
+ MdsalHelper.toBuilder(props, b);
+ assertEquals(ipAddress, String.valueOf(b.getSingleIp().stringValue()));
+ }
+
+ public void testIpAddressListToProperties() throws Exception {
+ Properties props = new Properties();
+ String ipAddress = "11.11.11.11";
+ TestObjectBuilder b = new TestObjectBuilder();
+ List<IpAddress> ipAddressList = new ArrayList<IpAddress>();
+ ipAddressList.add(IpAddressBuilder.getDefaultInstance(ipAddress));
+ b.setFloatingIp(ipAddressList);
+ MdsalHelper.toProperties(props, b.build());
+ assertEquals(ipAddress, props.getProperty("test-object.floating-ip[0]"));
+ assertEquals("1", props.getProperty("test-object.floating-ip_length"));
+ }
+
+ public void testIpAddressListToBuilder() throws Exception {
+ Properties props = new Properties();
+ String ipaddress = "11.11.11.12";
+ props.setProperty("test-object.floating-ip_length", "1");
+ props.setProperty("test-object.floating-ip[0]", ipaddress);
+ TestObjectBuilder b = new TestObjectBuilder();
+ MdsalHelper.toBuilder(props, b);
+ assertEquals(ipaddress, String.valueOf(b.getFloatingIp().get(0).stringValue()));
+
+ props = new Properties();
+ ipaddress = "cafe::8888";
+ props.setProperty("test-object.floating-ip_length", "1");
+ props.setProperty("test-object.floating-ip[0]", ipaddress);
+ b = new TestObjectBuilder();
+ MdsalHelper.toBuilder(props, b);
+ assertEquals(ipaddress, String.valueOf(b.getFloatingIp().get(0).stringValue()));
+ }
+
+ public void testSingleIpv4AddressToProperties() throws Exception {
+ Properties props = new Properties();
+ String v4address = "11.11.11.11";
+ MdsalHelper.toProperties(props, IpAddressBuilder.getDefaultInstance(v4address).getIpv4Address());
+ assertEquals(v4address, props.getProperty(""));
+ }
+
+ public void testSingleIpv4AddressToBuilder() throws Exception {
+ Properties props = new Properties();
+ String v4address = "11.11.11.11";
+ props.setProperty("test-object.single-ip-v4", v4address);
+ TestObjectBuilder b = new TestObjectBuilder();
+ MdsalHelper.toBuilder(props, b);
+ assertEquals(v4address, b.getSingleIpV4().getValue());
+ }
+
+ public void testIpv4AddressListToProperties() throws Exception {
+ Properties props = new Properties();
+ String v4address = "11.11.11.11";
+
+ TestObjectBuilder b = new TestObjectBuilder();
+ List<Ipv4Address> v4list = new ArrayList<Ipv4Address>();
+ v4list.add(IpAddressBuilder.getDefaultInstance(v4address).getIpv4Address());
+ b.setFloatingIpV4(v4list);
+ MdsalHelper.toProperties(props, b.build());
+ assertEquals(v4address, props.getProperty("test-object.floating-ip-v4[0]"));
+ assertEquals("1", props.getProperty("test-object.floating-ip-v4_length"));
+ }
+
+ public void testIpv4AddressListToBuilder() throws Exception {
+ Properties props = new Properties();
+ String v4address = "11.11.11.12";
+ props.setProperty("test-object.floating-ip-v4_length", "1");
+ props.setProperty("test-object.floating-ip-v4[0]", v4address);
+ TestObjectBuilder b = new TestObjectBuilder();
+ MdsalHelper.toBuilder(props, b);
+ assertEquals(v4address, b.getFloatingIpV4().get(0).getValue());
+ }
+
+ public void testSingleIpv6AddressToProperties() throws Exception {
+ Properties props = new Properties();
+ String v6address = "cafe::8888";
+ MdsalHelper.toProperties(props, IpAddressBuilder.getDefaultInstance(v6address).getIpv6Address());
+ MdsalHelper.toBuilder(props, IpAddressBuilder.getDefaultInstance("cafe::8887"));
+ assertEquals(v6address, props.getProperty(""));
+ }
+
+ public void testSingleIpv6AddressToBuilder() throws Exception {
+ Properties props = new Properties();
+ String v6address = "cafe::8888";
+ props.setProperty("test-object.single-ip-v6", v6address);
+ TestObjectBuilder b = new TestObjectBuilder();
+ MdsalHelper.toBuilder(props, b);
+ assertEquals(v6address, b.getSingleIpV6().getValue());
+ }
+
+ public void testIpv6AddressListToProperties() throws Exception {
+ Properties props = new Properties();
+ String v6address = "cafe::8888";
+
+ TestObjectBuilder b = new TestObjectBuilder();
+ List<Ipv6Address> v6list = new ArrayList<Ipv6Address>();
+ v6list.add(IpAddressBuilder.getDefaultInstance(v6address).getIpv6Address());
+ b.setFloatingIpV6(v6list);
+ MdsalHelper.toProperties(props, b.build());
+ assertEquals(v6address, props.getProperty("test-object.floating-ip-v6[0]"));
+ assertEquals("1", props.getProperty("test-object.floating-ip-v6_length"));
+ }
+
+ public void testIpv6AddressListToBuilder() throws Exception {
+ Properties props = new Properties();
+ String v6address = "cafe::8888";
+ props.setProperty("test-object.floating-ip-v6_length", "1");
+ props.setProperty("test-object.floating-ip-v6[0]", v6address);
+ TestObjectBuilder b = new TestObjectBuilder();
+ MdsalHelper.toBuilder(props, b);
+ assertEquals(v6address, b.getFloatingIpV6().get(0).getValue());
+ }
+
+ public void testIpPrefix() throws Exception {
+ String ipPrefix = "10.0.0.0/24";
+ Properties props = new Properties();
+ MdsalHelper.toProperties(props, IpPrefixBuilder.getDefaultInstance(ipPrefix));
+ assertEquals(ipPrefix, props.getProperty(""));
+ }
+
+ public void testPortNumber() throws Exception {
+ Properties props = new Properties();
+ String portNumber = "5";
+ MdsalHelper.toProperties(props, PortNumber.getDefaultInstance(portNumber));
+ assertEquals(portNumber, props.getProperty(""));
+ }
+
+ public void testDscp() throws Exception {
+ Properties props = new Properties();
+ String dscp = "1";
+ MdsalHelper.toProperties(props, Dscp.getDefaultInstance(dscp));
+ assertEquals(dscp, props.getProperty(""));
+ }
+
+ public void testIetfInet() throws Exception {
+ Properties props = new Properties();
+ Inet6Address address =
+ IetfInetUtil.INSTANCE.inet6AddressFor(IpAddressBuilder.getDefaultInstance("cafe::8888").getIpv6Address());
+ MdsalHelper.toProperties(props, address);
+ assertEquals("/cafe:0:0:0:0:0:0:8888", props.getProperty(""));
+ }
+
+ public void testAsNumber() throws Exception {
+ String value = "1";
+ Properties props = new Properties();
+ AsNumber num = AsNumber.getDefaultInstance(value);
+ MdsalHelper.toProperties(props, num);
+ assertEquals(value, props.getProperty("as-number"));
+ assertEquals(value, props.getProperty("as-number.value"));
+
+ }
+
+ public void testGetFullPropertiesPath() {
+ String propertiesName = "l3ucpe.properties";
+ String path = MdsalHelper.getFullPropertiesPath(propertiesName);
+ // verify the default works
+ assertEquals("/opt/lsc/controller/configuration/l3ucpe.properties", path);
+ System.setProperty("karaf.home", "/opt/opendaylight/current");
+ path = MdsalHelper.getFullPropertiesPath(propertiesName);
+ // verify the system property is read
+ assertEquals("/opt/opendaylight/current/configuration/l3ucpe.properties", path);
+ }
+
+ public void testToPropertiesWithBinary() throws Exception {
+ SampleContainerBuilder sampleBuilder = new SampleContainerBuilder();
+ Properties props = new Properties();
+ byte arr[] = new byte[] {1, 6, 3};
+ sampleBuilder.setSampleBinary(arr);
+ MdsalHelper.toProperties(props, sampleBuilder);
+ assertNotNull(props.get("sample-container.sample-binary"));
+ }
+
+ public void testToPropertiesWithBits() throws Exception {
+ SampleContainerBuilder sampleBuilder = new SampleContainerBuilder();
+ Boolean fanRunning = true;
+ Boolean hdLed = false;
+ Boolean powerLed = false;
+ SampleBits sampleBits = new SampleBits(fanRunning, hdLed, powerLed);
+ sampleBuilder.setSampleBits(sampleBits);
+ Properties props = new Properties();
+ MdsalHelper.toProperties(props, sampleBuilder);
+ assertEquals(fanRunning.toString(), props.get("sample-container.sample-bits.fan-running"));
+ assertEquals(hdLed.toString(), props.get("sample-container.sample-bits.hd-led"));
+ assertEquals(powerLed.toString(), props.get("sample-container.sample-bits.power-led"));
+ }
+
+ public void testToPropertiesWithBoolean() throws Exception {
+ SampleContainerBuilder sampleBuilder = new SampleContainerBuilder();
+ Boolean myBoolean = true;
+ sampleBuilder.setSampleBoolean(myBoolean);
+ Properties props = new Properties();
+ MdsalHelper.toProperties(props, sampleBuilder);
+ assertEquals(myBoolean.toString(), props.get("sample-container.sample-boolean"));
+ }
+
+ public void testToPropertiesWithDecimal64() throws Exception {
+ SampleContainerBuilder sampleBuilder = new SampleContainerBuilder();
+ BigDecimal myBigDecimal = new BigDecimal(".0000000000000000000000000000001");
+ sampleBuilder.setSampleDecimal64(myBigDecimal);
+ Properties props = new Properties();
+ MdsalHelper.toProperties(props, sampleBuilder);
+ // note toString() value is 1E-31
+ assertEquals(myBigDecimal.toString(), props.get("sample-container.sample-decimal64"));
+ }
+
+ public void testToPropertiesWithEmpty() throws Exception {
+ SampleContainerBuilder sampleBuilder = new SampleContainerBuilder();
+ Empty isEmpty = Empty.getInstance();
+ sampleBuilder.setSampleEmpty(isEmpty);
+ Properties props = new Properties();
+ MdsalHelper.toProperties(props, sampleBuilder);
+ assertEquals(isEmpty.toString(), props.get("sample-container.sample-empty"));
+ }
+
+ public void testToPropertiesWithEnumeration() throws Exception {
+ SampleContainerBuilder sampleBuilder = new SampleContainerBuilder();
+ Properties props = new Properties();
+ SampleEnumeration currentEnum = SampleEnumeration.ShelfSlotPort;
+ sampleBuilder.setSampleEnumeration(currentEnum);
+ MdsalHelper.toProperties(props, sampleBuilder);
+ assertEquals("shelf.slot.port", props.get("sample-container.sample-enumeration"));
+
+ currentEnum = SampleEnumeration.NotAvailable;
+ sampleBuilder.setSampleEnumeration(currentEnum);
+ MdsalHelper.toProperties(props, sampleBuilder);
+ assertEquals("not available", props.get("sample-container.sample-enumeration"));
+
+ currentEnum = SampleEnumeration.CURRENTLYAVAILABLE;
+ sampleBuilder.setSampleEnumeration(currentEnum);
+ MdsalHelper.toProperties(props, sampleBuilder);
+ assertEquals("CURRENTLY_AVAILABLE", props.get("sample-container.sample-enumeration"));
+
+ currentEnum = SampleEnumeration._200OK;
+ sampleBuilder.setSampleEnumeration(currentEnum);
+ MdsalHelper.toProperties(props, sampleBuilder);
+ assertEquals("200OK", props.get("sample-container.sample-enumeration"));
+
+ currentEnum = SampleEnumeration.HyphenSeparatedValue;
+ sampleBuilder.setSampleEnumeration(currentEnum);
+ MdsalHelper.toProperties(props, sampleBuilder);
+ assertEquals("hyphen-separated-value", props.get("sample-container.sample-enumeration"));
+ }
+
+ // TODO test sampleBuilder.setSampleIdentityref(value);
+
+ public void testToPropertiesWithInt8() throws Exception {
+ SampleContainerBuilder sampleBuilder = new SampleContainerBuilder();
+ Byte myByte = new Byte("-128");
+ sampleBuilder.setSampleInt8(myByte);
+ Properties props = new Properties();
+ MdsalHelper.toProperties(props, sampleBuilder);
+ assertEquals(myByte.toString(), props.get("sample-container.sample-int8"));
+ }
+
+ public void testToPropertiesWithInt16() throws Exception {
+ SampleContainerBuilder sampleBuilder = new SampleContainerBuilder();
+ Short myShort = new Short("-32768");
+ sampleBuilder.setSampleInt16(myShort);
+ Properties props = new Properties();
+ MdsalHelper.toProperties(props, sampleBuilder);
+ assertEquals(myShort.toString(), props.get("sample-container.sample-int16"));
+ }
+
+ public void testToPropertiesWithInt32() throws Exception {
+ SampleContainerBuilder sampleBuilder = new SampleContainerBuilder();
+ Integer myInt = new Integer("-32768");
+ sampleBuilder.setSampleInt32(myInt);
+ Properties props = new Properties();
+ MdsalHelper.toProperties(props, sampleBuilder);
+ assertEquals(myInt.toString(), props.get("sample-container.sample-int32"));
+ }
+
+ public void testToPropertiesWithInt64() throws Exception {
+ SampleContainerBuilder sampleBuilder = new SampleContainerBuilder();
+ Long myLong = new Long("-9223372036854775808");
+ sampleBuilder.setSampleInt64(myLong);
+ Properties props = new Properties();
+ MdsalHelper.toProperties(props, sampleBuilder);
+ assertEquals(myLong.toString(), props.get("sample-container.sample-int64"));
+ }
+
+ public void testToPropertiesWithLeafRef() throws Exception {
+ SampleContainerBuilder sampleBuilder = new SampleContainerBuilder();
+ Boolean myBool = false;
+ sampleBuilder.setSampleLeafref(myBool);
+ Properties props = new Properties();
+ MdsalHelper.toProperties(props, sampleBuilder);
+ assertEquals(myBool.toString(), props.get("sample-container.sample-leafref"));
+ }
+
+ public void testToPropertiesWithString() throws Exception {
+ SampleContainerBuilder sampleBuilder = new SampleContainerBuilder();
+ String myString = "Hello World!";
+ sampleBuilder.setSampleString(myString);
+ Properties props = new Properties();
+ MdsalHelper.toProperties(props, sampleBuilder);
+ assertEquals(myString.toString(), props.get("sample-container.sample-string"));
+ }
+
+ public void testToPropertiesWithuInt8() throws Exception {
+ SampleContainerBuilder sampleBuilder = new SampleContainerBuilder();
+ Short myShort = new Short("255");
+ sampleBuilder.setSampleUint8(myShort);
+ Properties props = new Properties();
+ MdsalHelper.toProperties(props, sampleBuilder);
+ assertEquals(myShort.toString(), props.get("sample-container.sample-uint8"));
+ }
+
+ public void testToPropertiesWithuInt16() throws Exception {
+ SampleContainerBuilder sampleBuilder = new SampleContainerBuilder();
+ Integer myInt = new Integer("65535");
+ sampleBuilder.setSampleUint16(myInt);
+ Properties props = new Properties();
+ MdsalHelper.toProperties(props, sampleBuilder);
+ assertEquals(myInt.toString(), props.get("sample-container.sample-uint16"));
+ }
+
+ public void testToPropertiesWithuInt32() throws Exception {
+ SampleContainerBuilder sampleBuilder = new SampleContainerBuilder();
+ Long myLong = new Long("4294967295");
+ sampleBuilder.setSampleUint32(myLong);
+ Properties props = new Properties();
+ MdsalHelper.toProperties(props, sampleBuilder);
+ assertEquals(myLong.toString(), props.get("sample-container.sample-uint32"));
+ }
+
+ public void testToPropertiesWithuInt64() throws Exception {
+ SampleContainerBuilder sampleBuilder = new SampleContainerBuilder();
+ BigInteger myBigInt = new BigInteger("2432902008176640000");
+ sampleBuilder.setSampleUint64(myBigInt);
+ Properties props = new Properties();
+ MdsalHelper.toProperties(props, sampleBuilder);
+ assertEquals(myBigInt.toString(), props.get("sample-container.sample-uint64"));
+ }
+
+ public void testToPropertiesFromBuilderUnion() throws Exception {
+ SampleContainerBuilder sampleBuilder = new SampleContainerBuilder();
+ Properties props = new Properties();
+
+ Integer myInt = new Integer("1");
+ SampleUnion test = new SampleUnion(myInt);
+ sampleBuilder.setSampleUnion(test);
+ MdsalHelper.toProperties(props, sampleBuilder);
+ assertEquals(test.getInt32().toString(), props.get("sample-container.sample-union.int32"));
+
+ test = new SampleUnion(SampleUnion.Enumeration.Unbounded);
+ sampleBuilder.setSampleUnion(test);
+ MdsalHelper.toProperties(props, sampleBuilder);
+ assertEquals("unbounded", props.get("sample-container.sample-union.enumeration"));
+ }
+
+ public void testToPropertiesWithCustomType() throws Exception {
+ SampleContainerBuilder sampleBuilder = new SampleContainerBuilder();
+ Properties props = new Properties();
+
+ Short myShort = new Short("99");
+ Percentage myPercent = new Percentage(myShort);
+ sampleBuilder.setPercentCompleted(myPercent);
+ MdsalHelper.toProperties(props, sampleBuilder);
+ assertEquals(myShort.toString(), props.get("sample-container.percent-completed"));
+ assertEquals(myShort.toString(), props.get("sample-container.percent-completed.value"));
+ }
+
+ public void testToPropertiesWithLeaftList() throws Exception {
+ SampleContainerBuilder sampleBuilder = new SampleContainerBuilder();
+ List<String> nickNames = new ArrayList<String>();
+ sampleBuilder.setCustomerNicknames(nickNames);
+ String nameOne = "coffee";
+ String nameTwo = "java";
+ String nameThree = "mud";
+
+ nickNames.add(nameOne);
+ nickNames.add(nameTwo);
+ nickNames.add(nameThree);
+
+ Properties props = new Properties();
+ MdsalHelper.toProperties(props, sampleBuilder);
+
+ assertEquals(nameOne, props.get("sample-container.customer-nicknames[0]"));
+ assertEquals(nameTwo, props.get("sample-container.customer-nicknames[1]"));
+ assertEquals(nameThree, props.get("sample-container.customer-nicknames[2]"));
+ assertEquals(String.valueOf(nickNames.size()), props.get("sample-container.customer-nicknames_length"));
+ }
+
+ public void testToPropertiesWithComplexContainer() throws Exception {
+ SampleContainerBuilder sampleBuilder = new SampleContainerBuilder();
+ LoginBuilder lb = new LoginBuilder();
+ lb.setMessage("WELCOME!");
+ List<CustomerAddresses> addresses = new ArrayList<CustomerAddresses>();
+ CustomerAddressesBuilder cab = new CustomerAddressesBuilder();
+ cab.setAddressName("home");
+ cab.setState("NJ");
+ cab.setStreetAddress("yellowbrick road");
+
+ CustomerAddresses addressOne = cab.build();
+ addresses.add(addressOne);
+
+ cab.setAddressName("vacation house");
+ cab.setState("FL");
+ cab.setStreetAddress("ocean ave");
+
+ CustomerAddresses addressTwo = cab.build();
+ addresses.add(addressTwo);
+
+ lb.setCustomerAddresses(addresses);
+ sampleBuilder.setLogin(lb.build());
+
+ Properties props = new Properties();
+ MdsalHelper.toProperties(props, sampleBuilder);
+
+ assertEquals("WELCOME!", props.get("sample-container.login.message"));
+ assertEquals("NJ", props.get("sample-container.login.customer-addresses[0].state"));
+ assertEquals("home", props.get("sample-container.login.customer-addresses[0].address-name"));
+ assertEquals("yellowbrick road", props.get("sample-container.login.customer-addresses[0].street-address"));
+ assertEquals("FL", props.get("sample-container.login.customer-addresses[1].state"));
+ assertEquals("vacation house", props.get("sample-container.login.customer-addresses[1].address-name"));
+ assertEquals("ocean ave", props.get("sample-container.login.customer-addresses[1].street-address"));
+ assertEquals("2", props.get("sample-container.login.customer-addresses_length"));
+ }
+
+ public void testToPropertiesIetf() throws Exception {
+ SampleContainerBuilder sampleBuilder = new SampleContainerBuilder();
+ sampleBuilder.setIpVersion(IpVersion.Ipv4);
+ sampleBuilder.setDscp(Dscp.getDefaultInstance("1"));
+ sampleBuilder.setPortNumber(PortNumber.getDefaultInstance("2"));
+ sampleBuilder.setIpv6FlowLabel(Ipv6FlowLabel.getDefaultInstance("3"));
+ sampleBuilder.setAsNumber(AsNumber.getDefaultInstance("4"));
+ sampleBuilder.setIpv6Address(Ipv6Address.getDefaultInstance("fdda:5cc1:23:4::1f"));
+ sampleBuilder.setIpAddressNoZone(IpAddressNoZoneBuilder.getDefaultInstance("fdda:5cc1:23:4::1f"));
+ sampleBuilder.setIpv4Address(Ipv4Address.getDefaultInstance("192.168.1.2"));
+ sampleBuilder.setIpv4AddressNoZone(Ipv4AddressNoZone.getDefaultInstance("192.168.1.3"));
+ sampleBuilder.setIpv6AddressNoZone(Ipv6AddressNoZone.getDefaultInstance("fdda:5cc1:23:4::1f"));
+ sampleBuilder.setIpv4Prefix(Ipv4Prefix.getDefaultInstance("198.51.100.0/24"));
+ sampleBuilder.setIpv6Prefix(Ipv6Prefix.getDefaultInstance("2001:db8:aaaa:1111::100/64"));
+ sampleBuilder.setDomainName(DomainName.getDefaultInstance("onap.org"));
+ sampleBuilder.setHost(HostBuilder.getDefaultInstance("machine.onap.org"));
+ sampleBuilder.setUri(Uri.getDefaultInstance("http://wiki.onap.org:8080"));
+
+ Properties props = new Properties();
+ MdsalHelper.toProperties(props, sampleBuilder);
+
+ assertEquals("4", props.get("sample-container.as-number"));
+ assertEquals("4", props.get("sample-container.as-number.value"));
+ assertEquals("onap.org", props.get("sample-container.domain-name"));
+ assertEquals("onap.org", props.get("sample-container.domain-name.value"));
+ assertEquals("1", props.get("sample-container.dscp"));
+ assertEquals("machine.onap.org", props.get("sample-container.host.domain-name"));
+ assertEquals("machine.onap.org", props.get("sample-container.host.domain-name.value"));
+ assertEquals("fdda:5cc1:23:4::1f", props.get("sample-container.ip-address-no-zone.ipv6-address-no-zone"));
+ assertEquals("fdda:5cc1:23:4::1f", props.get("sample-container.ip-address-no-zone.ipv6-address-no-zone.value"));
+ assertEquals("ipv4", props.get("sample-container.ip-version"));
+ assertEquals("192.168.1.2", props.get("sample-container.ipv4-address"));
+ assertEquals("192.168.1.3", props.get("sample-container.ipv4-address-no-zone"));
+ assertEquals("192.168.1.3", props.get("sample-container.ipv4-address-no-zone.value"));
+ assertEquals("198.51.100.0/24", props.get("sample-container.ipv4-prefix"));
+ assertEquals("198.51.100.0/24", props.get("sample-container.ipv4-prefix.value"));
+ assertEquals("fdda:5cc1:23:4::1f", props.get("sample-container.ipv6-address"));
+ assertEquals("fdda:5cc1:23:4::1f", props.get("sample-container.ipv6-address-no-zone"));
+ assertEquals("fdda:5cc1:23:4::1f", props.get("sample-container.ipv6-address-no-zone.value"));
+ assertEquals("3", props.get("sample-container.ipv6-flow-label"));
+ assertEquals("3", props.get("sample-container.ipv6-flow-label.value"));
+ assertEquals("2001:db8:aaaa:1111::100/64", props.get("sample-container.ipv6-prefix"));
+ assertEquals("2001:db8:aaaa:1111::100/64", props.get("sample-container.ipv6-prefix.value"));
+ assertEquals("2", props.get("sample-container.port-number"));
+ assertEquals("http://wiki.onap.org:8080", props.get("sample-container.uri"));
+ assertEquals("http://wiki.onap.org:8080", props.get("sample-container.uri.value"));
+ }
+
+ public void testIetfToBuilder() throws Exception {
+ Properties props = new Properties();
+ props.put("sample-container.as-number", "4");
+ props.put("sample-container.as-number.value", "4");
+ props.put("sample-container.domain-name", "onap.org");
+ props.put("sample-container.domain-name.value", "onap.org");
+ props.put("sample-container.dscp", "1");
+ props.put("sample-container.host.domain-name", "machine.onap.org");
+ props.put("sample-container.host.domain-name.value", "machine.onap.org");
+ props.put("sample-container.ip-address-no-zone.ipv6-address-no-zone", "fdda:5cc1:23:4::1f");
+ props.put("sample-container.ip-address-no-zone.ipv6-address-no-zone.value", "fdda:5cc1:23:4::1f");
+ props.put("sample-container.ip-version", "ipv4");
+ props.put("sample-container.ipv4-address", "192.168.1.2");
+ props.put("sample-container.ipv4-address-no-zone", "192.168.1.3");
+ props.put("sample-container.ipv4-address-no-zone.value", "192.168.1.3");
+ props.put("sample-container.ipv4-prefix", "198.51.100.0/24");
+ props.put("sample-container.ipv4-prefix.value", "198.51.100.0/24");
+ props.put("sample-container.ipv6-address", "fdda:5cc1:23:4::1f");
+ props.put("sample-container.ipv6-address-no-zone", "fdda:5cc1:23:4::1f");
+ props.put("sample-container.ipv6-address-no-zone.value", "fdda:5cc1:23:4::1f");
+ props.put("sample-container.ipv6-flow-label", "3");
+ props.put("sample-container.ipv6-flow-label.value", "3");
+ props.put("sample-container.ipv6-prefix", "2001:db8:aaaa:1111::100/64");
+ props.put("sample-container.ipv6-prefix.value", "2001:db8:aaaa:1111::100/64");
+ props.put("sample-container.port-number", "2");
+ props.put("sample-container.uri", "http://wiki.onap.org:8080");
+ props.put("sample-container.uri.value", "http://wiki.onap.org:8080");
+ SampleContainerBuilder sampleBuilder = new SampleContainerBuilder();
+
+ MdsalHelper.toBuilder(props, sampleBuilder);
+ SampleContainer result = sampleBuilder.build();
+ assertEquals(AsNumber.getDefaultInstance("4"), result.getAsNumber());
+ assertEquals(DomainName.getDefaultInstance("onap.org"), result.getDomainName());
+ assertEquals(Dscp.getDefaultInstance("1"), result.getDscp());
+ // assertEquals(HostBuilder.getDefaultInstance("machine.onap.org").getDomainName(),
+ // result.getHost().getDomainName());
+ assertEquals(Ipv6AddressNoZone.getDefaultInstance("fdda:5cc1:23:4::1f").getValue(),
+ result.getIpv6AddressNoZone().getValue());
+ assertEquals(IpVersion.Ipv4, result.getIpVersion());
+ assertEquals(Ipv4Address.getDefaultInstance("192.168.1.2"), result.getIpv4Address());
+ assertEquals(Ipv4AddressNoZone.getDefaultInstance("192.168.1.3"), result.getIpv4AddressNoZone());
+ assertEquals(Ipv4Prefix.getDefaultInstance("198.51.100.0/24"), result.getIpv4Prefix());
+ assertEquals(Ipv6Address.getDefaultInstance("fdda:5cc1:23:4::1f"), result.getIpv6Address());
+ assertEquals(IpAddressNoZoneBuilder.getDefaultInstance("fdda:5cc1:23:4::1f").getIpv6AddressNoZone().getValue(),
+ result.getIpv6AddressNoZone().getValue());
+ assertEquals(Ipv6FlowLabel.getDefaultInstance("3"), result.getIpv6FlowLabel());
+ assertEquals(Ipv6Prefix.getDefaultInstance("2001:db8:aaaa:1111::100/64"), result.getIpv6Prefix());
+ assertEquals(PortNumber.getDefaultInstance("2"), result.getPortNumber());
+ assertEquals(Uri.getDefaultInstance("http://wiki.onap.org:8080"), result.getUri());
+ }
+
+ public void testToLowerHyphen() throws Exception {
+ String camelCase = "HelloWorld";
+ String hypenCase = MdsalHelper.toLowerHyphen(camelCase);
+ assertEquals("hello-world", hypenCase);
+
+ camelCase = "L2SwitchInterfaces";
+ hypenCase = MdsalHelper.toLowerHyphen(camelCase);
+ assertEquals("l2-switch-interfaces", hypenCase);
+
+ camelCase = "ABC";
+ hypenCase = MdsalHelper.toLowerHyphen(camelCase);
+ assertEquals("a-b-c", hypenCase);
+ }
+
+}
diff --git a/core/sli/provider/src/test/java/org/onap/ccsdk/sli/core/sli/provider/MdsalHelperTesterUtil.java b/core/sli/provider/src/test/java/org/onap/ccsdk/sli/core/sli/provider/MdsalHelperTesterUtil.java
new file mode 100644
index 000000000..2167b8101
--- /dev/null
+++ b/core/sli/provider/src/test/java/org/onap/ccsdk/sli/core/sli/provider/MdsalHelperTesterUtil.java
@@ -0,0 +1,37 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.sli.provider;
+
+import org.onap.ccsdk.sli.core.sli.provider.MdsalHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class MdsalHelperTesterUtil extends MdsalHelper {
+
+ private static final Logger LOG = LoggerFactory.getLogger(MdsalHelperTesterUtil.class);
+
+ //Normally static init of classes goes here for some weird classloader thing
+ static {
+ String str = "Hello World!";
+ }
+
+}
diff --git a/core/sli/provider/src/test/java/org/onap/ccsdk/sli/core/sli/provider/PrintYangToPropTest.java b/core/sli/provider/src/test/java/org/onap/ccsdk/sli/core/sli/provider/PrintYangToPropTest.java
new file mode 100644
index 000000000..50b7926a0
--- /dev/null
+++ b/core/sli/provider/src/test/java/org/onap/ccsdk/sli/core/sli/provider/PrintYangToPropTest.java
@@ -0,0 +1,142 @@
+/*-
+ 2 * ============LICENSE_START=======================================================
+ 3 * ONAP CCSDK
+ 4 * ================================================================================
+ 5 * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ 6 * reserved.
+ 7 * ================================================================================
+ 8 * Licensed under the Apache License, Version 2.0 (the "License");
+ 9 * you may not use this file except in compliance with the License.
+ 10 * You may obtain a copy of the License at
+ 11 *
+ 12 * http://www.apache.org/licenses/LICENSE-2.0
+ 13 *
+ 14 * Unless required by applicable law or agreed to in writing, software
+ 15 * distributed under the License is distributed on an "AS IS" BASIS,
+ 16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ 17 * See the License for the specific language governing permissions and
+ 18 * limitations under the License.
+ 19 * ============LICENSE_END============================================
+ 20 * ===================================================================
+ 21 *
+ 22 */
+package org.onap.ccsdk.sli.core.sli.provider;
+
+import java.util.Enumeration;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Properties;
+
+import org.junit.Test;
+import org.onap.ccsdk.sli.core.sli.provider.PrintYangToProp;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.core.sliapi.rev161110.ExecuteGraphInput.Mode;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.core.sliapi.rev161110.ExecuteGraphInputBuilder;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.core.sliapi.rev161110.TestResultsBuilder;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.core.sliapi.rev161110.execute.graph.input.SliParameter;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.core.sliapi.rev161110.execute.graph.input.SliParameterBuilder;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.core.sliapi.rev161110.test.results.TestResult;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.core.sliapi.rev161110.test.results.TestResultBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddressBuilder;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpPrefixBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @author dt5972
+ *
+ */
+public class PrintYangToPropTest {
+
+ private static final Logger LOG = LoggerFactory.getLogger(PrintYangToPropTest.class);
+ @Test
+ public void test() {
+
+ Properties props = new Properties();
+
+ // Set up a builder with data
+ ExecuteGraphInputBuilder egBuilder = new ExecuteGraphInputBuilder();
+ egBuilder.setMode(Mode.Sync);
+ egBuilder.setModuleName("my-module");
+ egBuilder.setRpcName("my-rpc");
+
+ List<SliParameter> pList = new LinkedList<>();
+
+ SliParameterBuilder pBuilder = new SliParameterBuilder();
+ pBuilder.setParameterName("string-param");
+ pBuilder.setStringValue("hi");
+ pList.add(pBuilder.build());
+ pBuilder.setParameterName("int-param");
+ pBuilder.setIntValue(1);
+ pBuilder.setStringValue(null);
+ pList.add(pBuilder.build());
+ pBuilder.setParameterName("bool-param");
+ pBuilder.setIntValue(null);
+ pBuilder.setBooleanValue(true);
+ pList.add(pBuilder.build());
+ pBuilder.setParameterName("ipaddress-value1");
+ pBuilder.setBooleanValue(null);
+ pBuilder.setIpaddressValue(IpAddressBuilder.getDefaultInstance("127.0.0.1"));
+ pList.add(pBuilder.build());
+ pBuilder.setParameterName("ipaddress-value1");
+ pBuilder.setIpaddressValue(IpAddressBuilder.getDefaultInstance("::1"));
+ pList.add(pBuilder.build());
+ pBuilder.setParameterName("ipprefix-value1");
+ pBuilder.setIpaddressValue(null);
+ pBuilder.setIpprefixValue(IpPrefixBuilder.getDefaultInstance("192.168.0.0/16"));
+ pList.add(pBuilder.build());
+ pBuilder.setParameterName("ipprefix-value2");
+ pBuilder.setIpprefixValue(IpPrefixBuilder.getDefaultInstance("2001:db8:3c4d::/48"));
+ pList.add(pBuilder.build());
+
+
+
+ egBuilder.setSliParameter(pList);
+
+
+ // Generate properties
+ props = PrintYangToProp.toProperties(props, egBuilder);
+
+ Enumeration propNames = props.propertyNames();
+
+ while (propNames.hasMoreElements()) {
+ String propName = (String) propNames.nextElement();
+ LOG.info("Property {} = {}", propName, props.getProperty(propName));
+ }
+
+ // Generate builder from properties just generated
+ PrintYangToProp.toBuilder(props, pBuilder);
+
+
+ }
+
+ @Test
+ public void testWithList() {
+ TestResultsBuilder resultsBuilder = new TestResultsBuilder();
+ TestResultBuilder resultBuilder = new TestResultBuilder();
+
+ // Set builder with values
+ List<TestResult> resultList = new LinkedList<>();
+ resultBuilder.setTestIdentifier("test1");
+ List<String> results = new LinkedList<>();
+ results.add("pass");
+ resultBuilder.setResults(results);
+ resultList.add(resultBuilder.build());
+ resultsBuilder.setTestResult(resultList);
+
+ // Generate properties
+ Properties props = new Properties();
+ props = PrintYangToProp.toProperties(props, resultsBuilder);
+
+ Enumeration propNames = props.propertyNames();
+
+ while (propNames.hasMoreElements()) {
+ String propName = (String) propNames.nextElement();
+ LOG.info("Property {} = {}", propName, props.getProperty(propName));
+ }
+
+ // Generate builder from properties just generated
+ PrintYangToProp.toBuilder(props, resultsBuilder);
+
+ }
+
+}
diff --git a/core/sli/provider/src/test/java/org/opendaylight/yang/gen/v1/test/CosModelType.java b/core/sli/provider/src/test/java/org/opendaylight/yang/gen/v1/test/CosModelType.java
new file mode 100644
index 000000000..2aaaf8aa3
--- /dev/null
+++ b/core/sli/provider/src/test/java/org/opendaylight/yang/gen/v1/test/CosModelType.java
@@ -0,0 +1,51 @@
+package org.opendaylight.yang.gen.v1.test;
+
+public enum CosModelType {
+ _4COS(0, "4COS"),
+
+ _6COS(1, "6COS")
+ ;
+
+ private static final java.util.Map<java.lang.Integer, CosModelType> VALUE_MAP;
+
+ static {
+ final com.google.common.collect.ImmutableMap.Builder<java.lang.Integer, CosModelType> b = com.google.common.collect.ImmutableMap.builder();
+ for (CosModelType enumItem : CosModelType.values()) {
+ b.put(enumItem.value, enumItem);
+ }
+
+ VALUE_MAP = b.build();
+ }
+
+ private final java.lang.String name;
+ private final int value;
+
+ private CosModelType(int value, java.lang.String name) {
+ this.value = value;
+ this.name = name;
+ }
+
+ /**
+ * Returns the name of the enumeration item as it is specified in the input yang.
+ *
+ * @return the name of the enumeration item as it is specified in the input yang
+ */
+ public java.lang.String getName() {
+ return name;
+ }
+
+ /**
+ * @return integer value
+ */
+ public int getIntValue() {
+ return value;
+ }
+
+ /**
+ * @param valueArg integer value
+ * @return corresponding CosModelType item
+ */
+ public static CosModelType forValue(int valueArg) {
+ return VALUE_MAP.get(valueArg);
+ }
+} \ No newline at end of file
diff --git a/core/sli/provider/src/test/java/org/opendaylight/yang/gen/v1/test/TestObject.java b/core/sli/provider/src/test/java/org/opendaylight/yang/gen/v1/test/TestObject.java
new file mode 100755
index 000000000..eacfc9f63
--- /dev/null
+++ b/core/sli/provider/src/test/java/org/opendaylight/yang/gen/v1/test/TestObject.java
@@ -0,0 +1,17 @@
+package org.opendaylight.yang.gen.v1.test;
+
+import java.util.List;
+
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;
+
+public interface TestObject {
+ List<IpAddress> getFloatingIp();
+ List<Ipv4Address> getFloatingIpV4();
+ List<Ipv6Address> getFloatingIpV6();
+ Ipv4Address getSingleIpV4();
+ Ipv6Address getSingleIpV6();
+ IpAddress getSingleIp();
+
+}
diff --git a/core/sli/provider/src/test/java/org/opendaylight/yang/gen/v1/test/TestObjectBuilder.java b/core/sli/provider/src/test/java/org/opendaylight/yang/gen/v1/test/TestObjectBuilder.java
new file mode 100755
index 000000000..8301a0f05
--- /dev/null
+++ b/core/sli/provider/src/test/java/org/opendaylight/yang/gen/v1/test/TestObjectBuilder.java
@@ -0,0 +1,134 @@
+package org.opendaylight.yang.gen.v1.test;
+
+import java.util.List;
+
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.IpAddress;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv4Address;
+import org.opendaylight.yang.gen.v1.urn.ietf.params.xml.ns.yang.ietf.inet.types.rev130715.Ipv6Address;
+import org.opendaylight.yangtools.concepts.Builder;
+
+public class TestObjectBuilder implements Builder<TestObject> {
+ private List<IpAddress> _floatingIp;
+ private List<Ipv4Address> _floatingIpV4;
+ private List<Ipv6Address> _floatingIpV6;
+ private IpAddress _singleIp;
+ private Ipv4Address _singleIpV4;
+ private Ipv6Address _singleIpV6;
+
+ public List<IpAddress> getFloatingIp() {
+ return _floatingIp;
+ }
+
+ public List<Ipv4Address> getFloatingIpV4() {
+ return _floatingIpV4;
+ }
+
+ public List<Ipv6Address> getFloatingIpV6() {
+ return _floatingIpV6;
+ }
+
+ public Ipv4Address getSingleIpV4() {
+ return _singleIpV4;
+ }
+
+ public Ipv6Address getSingleIpV6() {
+ return _singleIpV6;
+ }
+
+ public IpAddress getSingleIp() {
+ return _singleIp;
+ }
+
+ public TestObjectBuilder setFloatingIp(final List<IpAddress> value) {
+ this._floatingIp = value;
+ return this;
+ }
+
+ public TestObjectBuilder setFloatingIpV4(final List<Ipv4Address> value) {
+ this._floatingIpV4 = value;
+ return this;
+ }
+
+ public TestObjectBuilder setFloatingIpV6(final List<Ipv6Address> value) {
+ this._floatingIpV6 = value;
+ return this;
+ }
+
+ public TestObjectBuilder setSingleIp(final IpAddress value) {
+ this._singleIp = value;
+ return this;
+ }
+
+ public TestObjectBuilder setSingleIpV4(final Ipv4Address value) {
+ this._singleIpV4 = value;
+ return this;
+ }
+
+ public TestObjectBuilder setSingleIpV6(final Ipv6Address value) {
+ this._singleIpV6 = value;
+ return this;
+ }
+
+ public TestObjectBuilder() {
+
+ }
+
+ public TestObject build() {
+ return new TestObjectImpl(this);
+ }
+
+ @Override
+ public String toString() {
+ return "TestObjectBuilder [_floatingIp=" + _floatingIp + ", _floatingIpV4=" + _floatingIpV4 + ", _floatingIpV6="
+ + _floatingIpV6 + ", _singleIp=" + _singleIp + ", _singleIpV4=" + _singleIpV4 + ", _singleIpV6="
+ + _singleIpV6 + "]";
+ }
+
+ private static final class TestObjectImpl implements TestObject {
+ private List<IpAddress> _floatingIp;
+ private List<Ipv4Address> _floatingIpV4;
+ private List<Ipv6Address> _floatingIpV6;
+ private IpAddress _singleIp;
+ private Ipv4Address _singleIpV4;
+ private Ipv6Address _singleIpV6;
+
+ @Override
+ public List<IpAddress> getFloatingIp() {
+ return _floatingIp;
+ }
+
+ @Override
+ public List<Ipv4Address> getFloatingIpV4() {
+ return _floatingIpV4;
+ }
+
+ @Override
+ public List<Ipv6Address> getFloatingIpV6() {
+ return _floatingIpV6;
+ }
+
+ @Override
+ public Ipv4Address getSingleIpV4() {
+ return _singleIpV4;
+ }
+
+ @Override
+ public Ipv6Address getSingleIpV6() {
+ return _singleIpV6;
+ }
+
+ @Override
+ public IpAddress getSingleIp() {
+ return _singleIp;
+ }
+
+ private TestObjectImpl(TestObjectBuilder base) {
+ this._floatingIp = base.getFloatingIp();
+ this._floatingIpV4 = base.getFloatingIpV4();
+ this._floatingIpV6 = base.getFloatingIpV6();
+ this._singleIp = base.getSingleIp();
+ this._singleIpV4 = base.getSingleIpV4();
+ this._singleIpV6 = base.getSingleIpV6();
+ }
+ }
+}
diff --git a/core/sli/provider/src/test/java/org/opendaylight/yang/gen/v1/test/WrapperObj.java b/core/sli/provider/src/test/java/org/opendaylight/yang/gen/v1/test/WrapperObj.java
new file mode 100644
index 000000000..bae0bdb1c
--- /dev/null
+++ b/core/sli/provider/src/test/java/org/opendaylight/yang/gen/v1/test/WrapperObj.java
@@ -0,0 +1,10 @@
+package org.opendaylight.yang.gen.v1.test;
+
+public class WrapperObj {
+
+ CosModelType cosModel = CosModelType._4COS;
+
+ public CosModelType getCosModelType() {
+ return cosModel;
+ }
+}
diff --git a/core/sli/provider/src/test/resources/EnumerationMapping.properties b/core/sli/provider/src/test/resources/EnumerationMapping.properties
new file mode 100644
index 000000000..d0fb29710
--- /dev/null
+++ b/core/sli/provider/src/test/resources/EnumerationMapping.properties
@@ -0,0 +1 @@
+yang.cos-model-type._4COS=HelloWorld \ No newline at end of file
diff --git a/core/sli/provider/src/test/resources/executor.tests b/core/sli/provider/src/test/resources/executor.tests
new file mode 100755
index 000000000..5468c8d60
--- /dev/null
+++ b/core/sli/provider/src/test/resources/executor.tests
@@ -0,0 +1,8 @@
+l3sdn_logic_v10.xml:switchTester:test-value=""
+l3sdn_logic_v10.xml:switchTester:test-value="hi"
+l3sdn_logic_v10.xml:forRecordTester
+l3sdn_logic_v10.xml:whileNodeTester
+l3sdn_logic_v10.xml:resourceTester
+l3sdn_logic_v10.xml:configureTester
+l3sdn_logic_v10.xml:javaPluginTester
+l3sdn_logic_v10.xml:allNodesTester \ No newline at end of file
diff --git a/core/sli/provider/src/test/resources/l3sdn.properties b/core/sli/provider/src/test/resources/l3sdn.properties
new file mode 100644
index 000000000..6f40ebca0
--- /dev/null
+++ b/core/sli/provider/src/test/resources/l3sdn.properties
@@ -0,0 +1,66 @@
+# yang conversion properties
+# used to convert Enum back to the original yang value
+yang.request-status.Synccomplete=synccomplete
+yang.request-status.Asynccomplete=asynccomplete
+yang.request-status.Notifycomplete=notifycomplete
+yang.rpc-name.ServiceConfigurationOperation=service-configuration-operation
+yang.rpc-name.SvcTopologyOperation=svc-topology-operation
+yang.rpc-name.ServiceConfigurationNotification=service-configuration-notification
+yang.rpc-action.Reserve=reserve
+yang.rpc-action.Activate=activate
+yang.rpc-action.Assign=assign
+yang.rpc-action.Turnup=turnup
+yang.rpc-action.Delete=delete
+yang.rpc-action.Changereserve=changereserve
+yang.rpc-action.Changeactivate=changeactivate
+yang.rpc-action.Changedelete=changedelete
+yang.rpc-action.Changeassign=changeassign
+yang.svc-vnf-type.Vce=vce
+yang.vnf-type.Vce=vce
+yang.vnf-status.PendingCreate=pending-create
+yang.vnf-status.Created=created
+yang.vnf-status.Active=active
+yang.vnf-status.PendingDelete=pending-delete
+yang.connection-type.Customer=customer
+yang.connection-type.Internet=internet
+yang.net-status.PendingCreate=pending-create
+yang.net-status.Created=created
+yang.net-status.Active=active
+yang.net-status.PendingDelete=pending-delete
+yang.svc-action.Reserve=reserve
+yang.svc-action.Activate=activate
+yang.svc-action.Assign=assign
+yang.svc-action.Turnup=turnup
+yang.svc-action.Delete=delete
+yang.svc-action.Changereserve=changereserve
+yang.svc-action.Changeactivate=changeactivate
+yang.svc-action.Changedelete=changedelete
+yang.svc-action.Changeassign=changeassign
+yang.service-type.SDNETHERNETINTERNET=SDN-ETHERNET-INTERNET
+yang.internet-evc-speed-value._2=2
+yang.internet-evc-speed-value._4=4
+yang.internet-evc-speed-value._5=5
+yang.internet-evc-speed-value._8=8
+yang.internet-evc-speed-value._10=10
+yang.internet-evc-speed-value._20=20
+yang.internet-evc-speed-value._50=50
+yang.internet-evc-speed-value._100=100
+yang.internet-evc-speed-value._150=150
+yang.internet-evc-speed-value._250=250
+yang.internet-evc-speed-value._400=400
+yang.internet-evc-speed-value._500=500
+yang.internet-evc-speed-value._600=600
+yang.internet-evc-speed-value._1000=1000
+yang.ip-version.Ds=ds
+yang.ip-version.V6=v6
+yang.routing-protocol.None=none
+yang.routing-protocol.Bgp=bgp
+yang.routing-protocol.Ospf=ospf
+yang.routing-protocol.Igrp=igrp
+yang.routing-protocol.Eigrp=eigrp
+yang.routing-protocol.Rip=rip
+yang.routing-protocol.IsIs=is-is
+yang.vr-designation.Primary=primary
+yang.feature-type.FIREWALLLITE=FIREWALL-LITE
+yang.equipment-role.VPLSPE=VPLS-PE
+yang.interface-role.CUSTOMERUPLINK=CUSTOMER-UPLINK
diff --git a/core/sli/provider/src/test/resources/l3sdn_logic_v10.xml b/core/sli/provider/src/test/resources/l3sdn_logic_v10.xml
new file mode 100644
index 000000000..64397236b
--- /dev/null
+++ b/core/sli/provider/src/test/resources/l3sdn_logic_v10.xml
@@ -0,0 +1,227 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- ============LICENSE_START=======================================================
+ ONAP : CCSDK ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. ================================================================================
+ 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. ============LICENSE_END========================================================= -->
+
+
+<service-logic xmlns="http://www.onap.org/sdnc/svclogic"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.onap.org/sdnc/svclogic ./svclogic.xsd"
+ module="neutron" version="1.0.0">
+
+ <method rpc="canCreateNetwork" mode="sync">
+ <return status="success">
+ <parameter name="error-code" value="200" />
+ </return>
+ </method>
+
+ <method rpc="switchTester" mode="sync">
+
+ <switch test="`$test-value`">
+ <outcome value="">
+ <return status="success">
+ <parameter name="visited-outcome" value="empty string" />
+ </return>
+ </outcome>
+ <outcome value="Other">
+ <return status="success">
+ <parameter name="visited-outcome" value="Other" />
+ </return>
+ </outcome>
+ </switch>
+
+
+ </method>
+
+ <method rpc="forRecordTester" mode="sync">
+ <for index="i" start="0" end="1">
+ <record plugin="org.onap.ccsdk.sli.core.sli.provider.DummyRecorder">
+ <parameter name="level" value="INFO"/>
+ <parameter name="field1" value="`forRecordTester message $i`"/>
+ </record>
+ </for>
+ </method>
+
+ <method rpc="whileNodeTester" mode="sync">
+ <block>
+ <set>
+ <parameter name="counter" value="0" />
+
+ </set>
+ <while test="`$counter &lt; 10`">
+ <set>
+ <parameter name="counter" value="`$counter + 1`" />
+ </set>
+
+ <switch test="`$counter > 6`">
+ <outcome value="true">
+ <break />
+ </outcome>
+ </switch>
+ </while>
+ </block>
+
+ </method>
+
+ <method rpc="resourceTester" mode="sync">
+ <block>
+ <set>
+ <parameter name='resource-plugin'
+ value='org.onap.ccsdk.sli.core.sli.provider.DummyResource' />
+ </set>
+
+ <save plugin="`$resource-plugin`" resource="sample" key="sample-key == 'resourceTester.status'">
+ <parameter name="sample-key" value="resourceTester.status"/>
+ <parameter name="sample-value" value="FAILED"/>
+ </save>
+
+ <update plugin="`$resource-plugin`" resource="sample" key="sample-key == 'resourceTester.status'">
+ <parameter name="sample-key" value="resourceTester.status"/>
+ <parameter name="sample-value" value="PASSED"/>
+ </update>
+
+ <get-resource plugin="`$resource-plugin`" resource="sample" key="sample-key == 'resourceTester.status'" pfx="sample"/>
+
+ <exists plugin="`$resource-plugin`" resource="sample" key="sample-key == 'resourceTester.status'"/>
+
+ <is-available plugin="`$resource-plugin`" resource="sample" key="sample-key == 'resourceTester.status'"/>
+
+ <reserve plugin="`$resource-plugin`" resource="sample" key="sample-key == 'resourceTester.status'"/>
+
+ <release plugin="`$resource-plugin`" resource="sample" key="sample-key == 'resourceTester.status'"/>
+
+
+ <reserve plugin="`$resource-plugin`" resource="sample" key="sample-key == 'resourceTester.status'"/>
+
+ <notify plugin="`$resource-plugin`" resource="sample" action="RESERVE"/>
+
+ <delete plugin="`$resource-plugin`" resource="sample" key="sample-key == 'resourceTester.status'"/>
+
+
+
+ </block>
+ </method>
+
+ <method rpc="configureTester" mode="sync">
+ <block>
+ <set>
+ <parameter name='configure-plugin'
+ value='org.onap.ccsdk.sli.core.sli.provider.DummyAdaptor' />
+ </set>
+ <configure adaptor="`$configure-plugin`" key="dummy" activate="true">
+ <parameter name="field1" value="1"/>
+ </configure>
+ <configure adaptor="`$configure-plugin`" key="SUCCESS" activate="true">
+ <parameter name="field1" value="1"/>
+ </configure>
+ <configure adaptor="`$configure-plugin`" key="ALREADY_ACTIVE" activate="true">
+ <parameter name="field1" value="1"/>
+ </configure>
+ <configure adaptor="`$configure-plugin`" key="NOT_FOUND" activate="true">
+ <parameter name="field1" value="1"/>
+ </configure>
+ <configure adaptor="`$configure-plugin`" key="NOT_READY" activate="true">
+ <parameter name="field1" value="1"/>
+ </configure>
+ <configure adaptor="`$configure-plugin`" key="FAILURE" activate="true">
+ <parameter name="field1" value="1"/>
+ </configure>
+ <configure adaptor="`$configure-plugin`" key="dummy" activate="false">
+ <parameter name="field1" value="1"/>
+ </configure>
+ <configure adaptor="`$configure-plugin`" key="SUCCESS" activate="false">
+ <parameter name="field1" value="1"/>
+ </configure>
+ <configure adaptor="`$configure-plugin`" key="ALREADY_ACTIVE" activate="false">
+ <parameter name="field1" value="1"/>
+ </configure>
+ <configure adaptor="`$configure-plugin`" key="NOT_FOUND" activate="false">
+ <parameter name="field1" value="1"/>
+ </configure>
+ <configure adaptor="`$configure-plugin`" key="NOT_READY" activate="false">
+ <parameter name="field1" value="1"/>
+ </configure>
+ <configure adaptor="`$configure-plugin`" key="FAILURE" activate="false">
+ <parameter name="field1" value="1"/>
+ </configure>
+ <configure adaptor="`$configure-plugin`" key="dummy" activate="true">
+ <parameter name="" value=""/>
+ </configure>
+ <configure adaptor="`$configure-plugin`" key="dummy" activate="false">
+ <parameter name="" value=""/>
+ </configure>
+ </block>
+ </method>
+
+
+ <method rpc="javaPluginTester" mode="sync">
+ <block>
+ <set>
+ <parameter name='java-plugin'
+ value='org.onap.ccsdk.sli.core.sli.provider.VoidDummyPlugin' />
+ </set>
+ <execute plugin="`$java-plugin`" method="dummy"/>
+ </block>
+ </method>
+
+ <method rpc="allNodesTester" mode="sync">
+ <block>
+ <set>
+ <parameter name='resource-plugin'
+ value='org.onap.ccsdk.sli.core.sli.provider.DummyResource' />
+ <parameter name='configure-plugin'
+ value='org.onap.ccsdk.sli.core.sli.provider.DummyAdaptor' />
+ <parameter name='java-plugin'
+ value='org.onap.ccsdk.sli.core.sli.provider.VoidDummyPlugin' />
+
+ </set>
+
+ <call rpc="switchTester" mode="sync" />
+
+ <call rpc="forRecordTester" mode="sync"/>
+
+ <call rpc="resourceTester" mode="sync"/>
+
+ <call rpc="configureTester" mode="sync"/>
+
+ <call rpc="javaPluginTester" mode="sync"/>
+
+ <call rpc="whileNodeTester" mode="sync"/>
+
+ </block>
+ </method>
+
+ <method rpc="networkCreated" mode="sync">
+ <switch
+ test="length($network.segment[0].provider-physical-network) >= 5 and substr($network.segment[0].provider-physical-network,0,5) == 'dvspg'">
+ <outcome value="true">
+ <block>
+ <set>
+ <parameter name="$vlanlist"
+ value="$network.segment[0].provider-segmentation-id" />
+ </set>
+ <for index="i" start="1" end="$network.num-segments">
+ <set>
+ <parameter name="$vlanlist"
+ value="eval($vlanlist+','+$network.segment[i].provider-segmentation-id)" />
+ </set>
+ </for>
+
+ </block>
+ </outcome>
+ <outcome value="Other">
+ <return status="success">
+ <parameter name="error-code" value="200" />
+ </return>
+ </outcome>
+ </switch>
+ </method>
+
+</service-logic>
diff --git a/core/sli/provider/src/test/resources/l3vpnyang/ietf-l3vpn-svc-part@2017-09-21.yang b/core/sli/provider/src/test/resources/l3vpnyang/ietf-l3vpn-svc-part@2017-09-21.yang
new file mode 100755
index 000000000..4af080608
--- /dev/null
+++ b/core/sli/provider/src/test/resources/l3vpnyang/ietf-l3vpn-svc-part@2017-09-21.yang
@@ -0,0 +1,68 @@
+module ietf-l3vpn-svc-part {
+
+ namespace "urn:ietf:params:xml:ns:yang:ietf-l3vpn-svc-part";
+
+ prefix l3vpn-svc;
+
+ organization
+ "IETF L3SM Working Group";
+
+ contact
+ "WG List: &lt;mailto:l3sm@ietf.org&gt;
+
+ Editor:
+
+ ";
+
+ description
+ "The YANG module defines a generic service configuration
+ model for Layer 3 VPN common across all of the vendor
+ implementations.";
+
+ revision 2017-09-21 {
+ description
+ "Part of draft-ietf-l3sm-l3vpn-service-yang-11";
+ reference
+ "draft-ietf-l3sm-l3vpn-service-yang-11";
+ }
+
+ /* Typedefs */
+
+ typedef svc-id {
+ type string;
+ description
+ "Defining a type of service component
+ identificators.";
+ }
+
+ /* Main blocks */
+
+ container l3vpn-svc {
+ container vpn-services {
+ list vpn-svc {
+ key vpn-id;
+
+ uses vpn-svc-cfg; /*Not used*/
+
+ description "
+ List of VPN services.";
+ }
+ description
+ "top level container
+ for the VPN services.";
+ }
+ }
+
+ grouping vpn-svc-cfg {
+ leaf vpn-id {
+ type svc-id;
+ description
+ "VPN identifier. Local administration meaning.";
+ }
+ leaf customer-name {
+ type string;
+ description
+ "Name of the customer.";
+ }
+ }
+}
diff --git a/core/sli/provider/src/test/resources/simplelogger.properties b/core/sli/provider/src/test/resources/simplelogger.properties
new file mode 100644
index 000000000..07ab67f70
--- /dev/null
+++ b/core/sli/provider/src/test/resources/simplelogger.properties
@@ -0,0 +1,22 @@
+###
+# ============LICENSE_START=======================================================
+# ONAP : CCSDK
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights
+# reserved.
+# ================================================================================
+# 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.
+# ============LICENSE_END=========================================================
+###
+
+org.slf4j.simpleLogger.defaultLogLevel=info
diff --git a/core/sli/provider/src/test/resources/svclogic.properties b/core/sli/provider/src/test/resources/svclogic.properties
new file mode 100644
index 000000000..426960f76
--- /dev/null
+++ b/core/sli/provider/src/test/resources/svclogic.properties
@@ -0,0 +1,27 @@
+###
+# ============LICENSE_START=======================================================
+# ONAP : CCSDK
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights
+# reserved.
+# ================================================================================
+# 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.
+# ============LICENSE_END=========================================================
+###
+
+org.onap.ccsdk.sli.dbtype = jdbc
+org.onap.ccsdk.sli.jdbc.url=jdbc:derby:memory:sdnctl;create=true
+org.onap.ccsdk.sli.jdbc.driver=org.apache.derby.jdbc.EmbeddedDriver
+org.onap.ccsdk.sli.jdbc.database = sdnctl
+org.onap.ccsdk.sli.jdbc.user = test
+org.onap.ccsdk.sli.jdbc.password = test
diff --git a/core/sliPluginUtils/.gitignore b/core/sliPluginUtils/.gitignore
new file mode 100755
index 000000000..b73caf31e
--- /dev/null
+++ b/core/sliPluginUtils/.gitignore
@@ -0,0 +1,34 @@
+#####standard .git ignore entries#####
+
+## IDE Specific Files ##
+org.eclipse.core.resources.prefs
+.classpath
+.project
+.settings
+.idea
+.externalToolBuilders
+maven-eclipse.xml
+workspace
+
+## Compilation Files ##
+*.class
+**/target
+target
+target-ide
+MANIFEST.MF
+
+## Misc Ignores (OS specific etc) ##
+bin/
+dist
+*~
+*.ipr
+*.iml
+*.iws
+classes
+out/
+.DS_STORE
+.metadata
+
+## Folders which contain auto generated source code ##
+yang-gen-config
+yang-gen-sal
diff --git a/core/sliPluginUtils/.sonar/checkstyle.xml b/core/sliPluginUtils/.sonar/checkstyle.xml
new file mode 100755
index 000000000..3fa231535
--- /dev/null
+++ b/core/sliPluginUtils/.sonar/checkstyle.xml
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE module PUBLIC "-//Puppy Crawl//DTD Check Configuration 1.2//EN" "http://www.puppycrawl.com/dtds/configuration_1_2.dtd"><!-- Generated by Sonar --><module name="Checker"><module name="SuppressionCommentFilter"/><module name="TreeWalker"><module name="FileContentsHolder"/> <module name="ClassFanOutComplexity"><property name="severity" value="warning"/></module><module name="NestedForDepth"><property name="severity" value="warning"/><property name="max" value="1"/></module><module name="ClassDataAbstractionCoupling"><property name="severity" value="warning"/></module></module></module> \ No newline at end of file
diff --git a/core/sliPluginUtils/.sonar/pmd.xml b/core/sliPluginUtils/.sonar/pmd.xml
new file mode 100755
index 000000000..80343b3bd
--- /dev/null
+++ b/core/sliPluginUtils/.sonar/pmd.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ruleset>
+ <rule ref="rulesets/java/naming.xml/BooleanGetMethodName">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/j2ee.xml/StaticEJBFieldShouldBeFinal">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/coupling.xml/CouplingBetweenObjects">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/codesize.xml/TooManyMethods">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/naming.xml/AvoidFieldNameMatchingTypeName">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/basic.xml/DoubleCheckedLocking">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/naming.xml/AvoidFieldNameMatchingMethodName">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/coupling.xml/ExcessiveImports">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/basic.xml/OverrideBothEqualsAndHashcode">
+ <priority>2</priority>
+ </rule>
+ <rule ref="rulesets/java/naming.xml/ShortMethodName">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/basic.xml/BooleanInstantiation">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/codesize.xml/TooManyFields">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/controversial.xml/AvoidUsingNativeCode">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/optimizations.xml/UseStringBufferForStringAppends">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/coupling.xml/LooseCoupling">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/design.xml/NonThreadSafeSingleton">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/j2ee.xml/DoNotUseThreads">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/sunsecure.xml/ArrayIsStoredDirectly">
+ <priority>5</priority>
+ </rule>
+ <rule ref="rulesets/java/sunsecure.xml/MethodReturnsInternalArray">
+ <priority>2</priority>
+ </rule>
+ <rule ref="rulesets/java/design.xml/AssignmentToNonFinalStatic">
+ <priority>3</priority>
+ </rule>
+ <rule ref="rulesets/java/strictexception.xml/AvoidCatchingGenericException">
+ <priority>3</priority>
+ </rule>
+</ruleset>
+
diff --git a/core/sliPluginUtils/installer/pom.xml b/core/sliPluginUtils/installer/pom.xml
new file mode 100755
index 000000000..c133cd05b
--- /dev/null
+++ b/core/sliPluginUtils/installer/pom.xml
@@ -0,0 +1,147 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>odlparent-lite</artifactId>
+ <version>2.1.0-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sliPluginUtils-installer</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>pom</packaging>
+
+ <name>ccsdk-sli-core :: sliPluginUtils :: ${project.artifactId}</name>
+
+ <properties>
+ <application.name>ccsdk-sliPluginUtils</application.name>
+ <features.boot>${application.name}</features.boot>
+ <features.repositories>mvn:org.onap.ccsdk.sli.core/${features.boot}/${project.version}/xml/features</features.repositories>
+ <include.transitive.dependencies>false</include.transitive.dependencies>
+ </properties>
+
+ <dependencyManagement>
+ <dependencies>
+
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sli-common</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sli-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>dblib-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+ <dependencies>
+
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sliPluginUtils-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>maven-repo-zip</id>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ <phase>package</phase>
+ <configuration>
+ <attach>true</attach>
+ <finalName>stage/${application.name}-${project.version}</finalName>
+ <descriptors>
+ <descriptor>src/assembly/assemble_mvnrepo_zip.xml</descriptor>
+ </descriptors>
+ <appendAssemblyId>true</appendAssemblyId>
+ </configuration>
+ </execution>
+ <execution>
+ <id>installer-zip</id>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ <phase>package</phase>
+ <configuration>
+ <attach>true</attach>
+ <finalName>${application.name}-${project.version}-installer</finalName>
+ <descriptors>
+ <descriptor>src/assembly/assemble_installer_zip.xml</descriptor>
+ </descriptors>
+ <appendAssemblyId>false</appendAssemblyId>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>copy-dependencies</id>
+ <goals>
+ <goal>copy-dependencies</goal>
+ </goals>
+ <phase>prepare-package</phase>
+ <configuration>
+ <transitive>false</transitive>
+ <outputDirectory>${project.build.directory}/assembly/system</outputDirectory>
+ <overWriteReleases>false</overWriteReleases>
+ <overWriteSnapshots>true</overWriteSnapshots>
+ <overWriteIfNewer>true</overWriteIfNewer>
+ <useRepositoryLayout>true</useRepositoryLayout>
+ <addParentPoms>false</addParentPoms>
+ <copyPom>false</copyPom>
+ <includeArtifactIds>sliPluginUtils-provider,ccsdk-sliPluginUtils,features-sliPluginUtils</includeArtifactIds>
+ <scope>provided</scope>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <artifactId>maven-resources-plugin</artifactId>
+ <version>2.6</version>
+ <executions>
+ <execution>
+ <id>copy-version</id>
+ <goals>
+ <goal>copy-resources</goal>
+ </goals><!-- here the phase you need -->
+ <phase>validate</phase>
+ <configuration>
+ <outputDirectory>${basedir}/target/stage</outputDirectory>
+ <resources>
+ <resource>
+ <directory>src/main/resources/scripts</directory>
+ <includes>
+ <include>install-feature.sh</include>
+ </includes>
+ <filtering>true</filtering>
+ </resource>
+ </resources>
+ </configuration>
+ </execution>
+
+ </executions>
+ </plugin>
+
+ </plugins>
+ </build>
+</project>
diff --git a/core/sliPluginUtils/installer/src/assembly/assemble_installer_zip.xml b/core/sliPluginUtils/installer/src/assembly/assemble_installer_zip.xml
new file mode 100644
index 000000000..2d3c0606d
--- /dev/null
+++ b/core/sliPluginUtils/installer/src/assembly/assemble_installer_zip.xml
@@ -0,0 +1,59 @@
+<!--
+ ============LICENSE_START=======================================================
+ ONAP : CCSDK
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property. All rights
+ reserved.
+ ================================================================================
+ 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.
+ ============LICENSE_END=========================================================
+ -->
+
+<!-- Defines how we build the .zip file which is our distribution. -->
+
+<assembly
+ xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
+ <id>bin</id>
+ <formats>
+ <format>zip</format>
+ </formats>
+
+ <!-- we want "system" and related files right at the root level
+ as this file is suppose to be unzip on top of a karaf
+ distro. -->
+ <includeBaseDirectory>false</includeBaseDirectory>
+
+ <fileSets>
+ <fileSet>
+ <directory>target/stage/</directory>
+ <outputDirectory>${application.name}</outputDirectory>
+ <fileMode>755</fileMode>
+ <includes>
+ <include>*.sh</include>
+ </includes>
+ </fileSet>
+ <fileSet>
+ <directory>target/stage/</directory>
+ <outputDirectory>${application.name}</outputDirectory>
+ <fileMode>644</fileMode>
+ <excludes>
+ <exclude>*.sh</exclude>
+ </excludes>
+ </fileSet>
+ </fileSets>
+
+
+
+</assembly>
diff --git a/core/sliPluginUtils/installer/src/assembly/assemble_mvnrepo_zip.xml b/core/sliPluginUtils/installer/src/assembly/assemble_mvnrepo_zip.xml
new file mode 100644
index 000000000..63ef515a0
--- /dev/null
+++ b/core/sliPluginUtils/installer/src/assembly/assemble_mvnrepo_zip.xml
@@ -0,0 +1,49 @@
+<!--
+ ============LICENSE_START=======================================================
+ ONAP : CCSDK
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property. All rights
+ reserved.
+ ================================================================================
+ 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.
+ ============LICENSE_END=========================================================
+ -->
+
+<!-- Defines how we build the .zip file which is our distribution. -->
+
+<assembly
+ xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
+ <id>repo</id>
+ <formats>
+ <format>zip</format>
+ </formats>
+
+ <!-- we want "system" and related files right at the root level
+ as this file is suppose to be unzip on top of a karaf
+ distro. -->
+ <includeBaseDirectory>false</includeBaseDirectory>
+
+ <fileSets>
+ <fileSet>
+ <directory>target/assembly/</directory>
+ <outputDirectory>.</outputDirectory>
+ <excludes>
+ </excludes>
+ </fileSet>
+ </fileSets>
+
+
+
+</assembly>
diff --git a/core/sliPluginUtils/installer/src/main/resources/scripts/install-feature.sh b/core/sliPluginUtils/installer/src/main/resources/scripts/install-feature.sh
new file mode 100644
index 000000000..638c73394
--- /dev/null
+++ b/core/sliPluginUtils/installer/src/main/resources/scripts/install-feature.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+
+###
+# ============LICENSE_START=======================================================
+# ONAP : CCSDK
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights
+# reserved.
+# ================================================================================
+# 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.
+# ============LICENSE_END=========================================================
+###
+
+ODL_HOME=${ODL_HOME:-/opt/opendaylight/current}
+ODL_KARAF_CLIENT=${ODL_KARAF_CLIENT:-${ODL_HOME}/bin/client}
+INSTALLERDIR=$(dirname $0)
+
+REPOZIP=${INSTALLERDIR}/${features.boot}-${project.version}.zip
+
+if [ -f ${REPOZIP} ]
+then
+ unzip -nd ${ODL_HOME} ${REPOZIP}
+else
+ echo "ERROR : repo zip ($REPOZIP) not found"
+ exit 1
+fi
+
+${ODL_KARAF_CLIENT} feature:repo-add ${features.repositories}
+${ODL_KARAF_CLIENT} feature:install ${features.boot}
diff --git a/core/sliPluginUtils/pom.xml b/core/sliPluginUtils/pom.xml
new file mode 100755
index 000000000..974e0661c
--- /dev/null
+++ b/core/sliPluginUtils/pom.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>odlparent-lite</artifactId>
+ <version>2.1.0-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sliPluginUtils</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>pom</packaging>
+
+ <name>ccsdk-sli-core :: sliPluginUtils</name>
+ <description>A package of static utility functions to be used when developing SLI plugins</description>
+
+ <modules>
+ <module>provider</module>
+ <module>installer</module>
+ </modules>
+</project>
diff --git a/core/sliPluginUtils/provider/pom.xml b/core/sliPluginUtils/provider/pom.xml
new file mode 100755
index 000000000..086faf39e
--- /dev/null
+++ b/core/sliPluginUtils/provider/pom.xml
@@ -0,0 +1,72 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>binding-parent</artifactId>
+ <version>2.1.0-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sliPluginUtils-provider</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>bundle</packaging>
+
+ <name>ccsdk-sli-core :: sliPluginUtils :: ${project.artifactId}</name>
+ <url>http://maven.apache.org</url>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>dblib-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>sli-common</artifactId>
+ <version>${project.version}</version>
+ <scope>compile</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>jcl-over-slf4j</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-lang3</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.hamcrest</groupId>
+ <artifactId>hamcrest-library</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.google.code.gson</groupId>
+ <artifactId>gson</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-text</artifactId>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/core/sliPluginUtils/provider/src/main/java/org/onap/ccsdk/sli/core/slipluginutils/SliPluginUtils.java b/core/sliPluginUtils/provider/src/main/java/org/onap/ccsdk/sli/core/slipluginutils/SliPluginUtils.java
new file mode 100644
index 000000000..2edb36dc4
--- /dev/null
+++ b/core/sliPluginUtils/provider/src/main/java/org/onap/ccsdk/sli/core/slipluginutils/SliPluginUtils.java
@@ -0,0 +1,1178 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Modifications Copyright (C) 2018 IBM.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.slipluginutils;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.PrintStream;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Objects;
+import java.util.Properties;
+import java.util.Set;
+import java.util.UUID;
+import java.util.stream.Collectors;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.text.StringEscapeUtils;
+import org.onap.ccsdk.sli.core.sli.SvcLogicConstants;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.core.sli.SvcLogicJavaPlugin;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+
+/**
+ * A utility class used to streamline the interface between Java plugins,
+ * the Service Logic Context, and Directed Graphs.
+ * @version 7.0.1
+ * @see org.onap.ccsdk.sli.core.sli.SvcLogicContext
+ */
+public class SliPluginUtils implements SvcLogicJavaPlugin {
+ public enum LogLevel {
+ TRACE, DEBUG, INFO, WARN, ERROR;
+ }
+
+ private static final Logger LOG = LoggerFactory.getLogger(SliPluginUtils.class);
+ private static final String LOG_MSG="extracting list from context memory";
+ private static final String LOG_MSG1="removing elements from list";
+ private static final String LENGTH="_length";
+ public static final String CTX_NULL_VALUE="";
+
+
+ // ========== CONSTRUCTORS ==========
+
+ public SliPluginUtils() {}
+
+ public SliPluginUtils( Properties props ) {}
+
+
+ // ========== CONTEXT MEMORY FUNCTIONS ==========
+
+ /**
+ * Removes 1 or more elements from a list in context memory.
+ * <p>
+ * Values are removed based on either the index in the list, a key-value
+ * pair, or a list of key-value pairs that all must match in the element.
+ * @param parameters
+ * @param ctx Reference to context memory
+ * @throws SvcLogicException All exceptions are wrapped in
+ * SvcLogicException for compatibility with SLI.
+ * @since 7.0.1
+ */
+ public void ctxListRemove( Map<String,String> parameters, SvcLogicContext ctx ) throws SvcLogicException {
+ try{
+ LOG.debug( "ENTERING Execute Node \"ctxListRemove\"" );
+
+ // Validate, Log, & read parameters
+ checkParameters(parameters, new String[]{"list_pfx"}, LOG);
+ logExecuteNodeParameters(parameters, LOG, LogLevel.DEBUG);
+ String list_pfx = parameters.get("list_pfx");
+ String param_index = parameters.get("index");
+ String param_key = parameters.get("key");
+ String param_value = parameters.get("value");
+ String param_keys_length = parameters.get("keys_length");
+
+ // Initialize context memory list mimic
+ SvcLogicContextList list;
+
+ // Process based on input parameters:
+ // index: remove object at specific index
+ // key & value: remove all objects with key-value pair
+ // keys_length: remove all objects that match all key-value pairs
+ // in list
+ if( param_index != null ) {
+ // Parse index
+ LOG.trace("executing remove by index logic");
+ int index;
+ try {
+ index = Integer.parseInt(param_index);
+ }
+ catch( NumberFormatException e ) {
+ throw new IllegalArgumentException("\"index\" parameter is not a number. index = " + param_index, e);
+ }
+
+ // Extract list from context memory & remove object @ index
+ LOG.trace(LOG_MSG);
+ list = SvcLogicContextList.extract(ctx, list_pfx);
+ LOG.trace(LOG_MSG1);
+ list.remove(index);
+ }
+ else if( param_value != null ) {
+ if( param_key == null ) { param_key = ""; }
+
+ // Extract list from context memory & remove objects with
+ // key-value pair
+ LOG.trace("executing remove by key-value pair logic");
+ LOG.trace(LOG_MSG);
+ list = SvcLogicContextList.extract(ctx, list_pfx);
+ LOG.trace(LOG_MSG1);
+ list.remove( param_key, param_value );
+ }
+ else if( param_keys_length != null ) {
+ // Parse keys_length
+ LOG.trace("executing remove by key-value pair list logic");
+ int keys_length;
+ try {
+ keys_length = Integer.parseInt(param_keys_length);
+ }
+ catch( NumberFormatException e ) {
+ throw new IllegalArgumentException("\"keys_length\" parameters is not a number. keys_length = " + param_keys_length, e);
+ }
+
+ // Obtain key-value pairs to check from parameters
+ LOG.trace("reading keys parameter list");
+ HashMap<String,String> keys_values = new HashMap<>();
+ for( int i = 0; i < keys_length; i++ ) {
+ keys_values.put(parameters.get("keys[" + i + "].key"), parameters.get("keys[" + i + "].value"));
+ }
+
+ // Extract list from context memory & remove objects with all
+ // key-value pairs matching
+ LOG.trace(LOG_MSG);
+ list = SvcLogicContextList.extract(ctx, list_pfx);
+ LOG.trace(LOG_MSG1);
+ list.remove(keys_values);
+ }
+ else {
+ throw new IllegalArgumentException("Required parameters missing. Requires one of: index, key & value, or keys_length array");
+ }
+
+ // Remove index from list
+ LOG.trace("writing list back into context memory");
+ list.writeToContext(ctx);
+ }
+ catch( Exception e ) {
+ throw new SvcLogicException( "An error occurred in the ctxListRemove Execute node", e );
+ }
+ finally {
+ LOG.debug( "EXITING Execute Node \"ctxListRemove\"" );
+ }
+ }
+
+ /**
+ * ctxSortList
+ * @param parameters - the set of required parameters must contain list and delimiter.
+ * @param ctx Reference to context memory
+ * @throws SvcLogicException if a required parameter is missing an exception is thrown
+ */
+ public void ctxSortList( Map<String, String> parameters, SvcLogicContext ctx ) throws SvcLogicException {
+ checkParameters(parameters, new String[]{"list","delimiter"}, LOG);
+ ArrayList<SortableCtxListElement> list = new ArrayList<>();
+
+ String[] sort_fields = null;
+ if( parameters.containsKey("sort-fields") ) {
+ sort_fields = parameters.get("sort-fields").split(parameters.get("delimiter"), 0);
+ }
+
+ String ctx_list_str = parameters.get("list");
+ int listSz = getArrayLength(ctx, ctx_list_str);
+
+
+
+ for( int i = 0; i < listSz; i++ ) {
+ list.add( new SortableCtxListElement(ctx, ctx_list_str + '[' + i + ']', sort_fields) );
+ }
+ Collections.sort(list);
+
+ ctxBulkErase(ctx, ctx_list_str);
+ int i = 0;
+ for( SortableCtxListElement list_element : list ) {
+ for( Map.Entry<String,String> entry : list_element.child_elements.entrySet() ) {
+ if( sort_fields == null ) {
+ ctx.setAttribute(ctx_list_str + '[' + i + ']', entry.getValue());
+ }
+ else {
+ ctx.setAttribute(ctx_list_str + '[' + i + "]." + entry.getKey(), entry.getValue());
+ }
+ }
+ i++;
+ }
+ // Reset list length (removed by ctxBulkErase above)
+ ctx.setAttribute(ctx_list_str+LENGTH, Integer.toString(listSz));
+ }
+
+ /**
+ * generates a UUID and writes it to context memory
+ * @param parameters - ctx-destination is a required parameter
+ * @param ctx Reference to context memory
+ * @throws SvcLogicException thrown if a UUID cannot be generated or if ctx-destination is missing or null
+ */
+ public void generateUUID( Map<String, String> parameters, SvcLogicContext ctx ) throws SvcLogicException {
+ checkParameters(parameters, new String[]{"ctx-destination"}, LOG);
+ ctx.setAttribute(parameters.get("ctx-destination"), UUID.randomUUID().toString() );
+ }
+
+ /**
+ * Provides substring functionality to Directed Graphs.
+ * <p>
+ * Calls either String.substring(String beginIndex) or
+ * String.substring(String beginInded, String endIndex) if the end-index
+ * is present or not.
+ * @param parameters HashMap<String,String> of parameters passed by the DG to this function
+ * <table border="1">
+ * <thead><th>parameter</th><th>Mandatory/Optional</th><th>description</th></thead>
+ * <tbody>
+ * <tr><td>string</td><td>Mandatory</td><td>String to perform substring on</td></tr>
+ * <tr><td>result</td><td>Mandatory</td><td>Key in context memory to populate the resulting string in</td></tr>
+ * <tr><td>begin-index</td><td>Mandatory</td><td>Beginning index to pass to Java substring function</td></tr>
+ * <tr><td>end-index</td><td>Optional</td><td>Ending index to pass to Java substring function. If not included, String.substring(begin) will be called.</td></tr>
+ * </tbody>
+ * </table>
+ * @param ctx Reference to context memory
+ * @throws SvcLogicException
+ * @since 8.0.1
+ * @see SliPluginUtils#substring(Map, SvcLogicContext)
+ */
+ @Deprecated
+ public void substring( Map<String, String> parameters, SvcLogicContext ctx ) throws SvcLogicException {
+ try {
+ checkParameters( parameters, new String[]{"string","begin-index","result"}, LOG );
+ final String string = parameters.get("string");
+ final String result = parameters.get("result");
+ final String begin = parameters.get("begin-index");
+ final String end = parameters.get("end-index");
+
+ if( StringUtils.isEmpty(end) ) {
+ ctx.setAttribute( result, string.substring(Integer.parseInt(begin)) );
+ }
+ else {
+ ctx.setAttribute( result, string.substring(Integer.parseInt(begin), Integer.parseInt(end)) );
+ }
+ }
+ catch( Exception e ) {
+ throw new SvcLogicException( "An error occurred while the Directed Graph was performing a substring", e );
+ }
+ }
+
+
+
+ // ========== PUBLIC STATIC UTILITY FUNCTIONS ==========
+
+ /**
+ * Throws an exception and writes an error to the log file if a required
+ * parameters is not found in the parametersMap.
+ * <p>
+ * Use at the beginning of functions that can be called by Directed Graphs
+ * and can take parameters to verify that all parameters have been provided
+ * by the Directed Graph.
+ * @param parametersMap parameters Map passed to this node
+ * @param requiredParams Array of parameters required by the calling function
+ * @param log Reference to Logger to log to
+ * @throws SvcLogicException if a String in the requiredParams array is
+ * not a key in parametersMap.
+ * @since 1.0
+ */
+ public static final void checkParameters(Map<String, String> parametersMap, String[] requiredParams, Logger log) throws SvcLogicException {
+ if( requiredParams == null || requiredParams.length < 1){
+ log.debug("required parameters was empty, exiting early.");
+ return;
+ }
+ if (parametersMap == null || parametersMap.keySet().isEmpty()){
+ String errorMessage = "This method requires the parameters [" + StringUtils.join(requiredParams,",") + "], but no parameters were passed in.";
+ log.error(errorMessage);
+ throw new SvcLogicException(errorMessage);
+ }
+
+ for (String param : requiredParams) {
+ if (!parametersMap.containsKey(param)) {
+ String errorMessage = "Required parameter \"" + param + "\" was not found in parameter list.";
+ log.error(errorMessage);
+ log.error("Total list of required parameters is [" + StringUtils.join(requiredParams, ",") + "].");
+ throw new SvcLogicException(errorMessage);
+ }
+ }
+ }
+
+ /**
+ * Removes all key-value pairs with keys that begin with pfx
+ * @param ctx Reference to context memory
+ * @param pfx Prefix of key-value pairs to remove
+ * @since 1.0
+ */
+ public static final void ctxBulkErase( SvcLogicContext ctx, String pfx ) {
+ ArrayList<String> Keys = new ArrayList<>(ctx.getAttributeKeySet());
+ for( String key : Keys ) {
+ if( key.startsWith( pfx ) ) {
+ ctx.setAttribute( pfx + key.substring(pfx.length()) , null);
+ }
+ }
+ }
+
+ /**
+ * Copies all context memory key-value pairs that start with src_pfx to
+ * the keys that start with dest_pfx + suffix, where suffix is the result
+ * of {@code key.substring(src_pfx.length())}.
+ * <p>
+ * Does NOT guarantee removal of all keys at the destination before
+ * copying, but will overwrite any destination keys that have a
+ * corresponding source key. Use {@link #ctxBulkErase(SvcLogicContext, String) ctxBulkErase}
+ * before copy to erase destination root before copying from source.
+ * @param ctx Reference to context memory.
+ * @param src_pfx Prefix of the keys to copy values from.
+ * @param dest_pfx Prefix of the keys to copy values to.
+ * @since 1.0
+ */
+ public static final void ctxBulkCopy( SvcLogicContext ctx, String src_pfx, String dest_pfx ) {
+ // Remove trailing period from dest_pfx
+ if( dest_pfx.charAt(dest_pfx.length()-1) == '.' ) {
+ dest_pfx = dest_pfx.substring(0,dest_pfx.length()-1);
+ }
+
+ // For each context key that begins with src_pfx, set the value of the
+ // key dest_pfx + the suffix of the key to the key's value
+ ArrayList<String> Keys = new ArrayList<>(ctx.getAttributeKeySet());
+ for( String key : Keys ) {
+ if( key.startsWith(src_pfx) ) {
+ // Get suffix (no leading period)
+ String suffix = key.substring(src_pfx.length());
+ if( suffix.charAt(0) == '.') {
+ suffix = suffix.substring(1);
+ }
+
+ // Set destination's value to key's value
+ ctx.setAttribute(dest_pfx + '.' + suffix, ctx.getAttribute(key));
+ }
+ }
+ }
+
+ /**
+ * Creates and returns a {@code Map<String, String>} that is a subset of
+ * context memory where all keys begin with the prefix.
+ * @param ctx Reference to context memory.
+ * @param prefix Returned map's keys should all begin with this value.
+ * @return A {@code Map<String, String>} containing all the key-value pairs
+ * in ctx whose key begins with prefix.
+ */
+ public static final Map<String, String> ctxGetBeginsWith( SvcLogicContext ctx, String prefix ) {
+ Map<String, String> prefixMap = new HashMap<>();
+
+ for( String key : ctx.getAttributeKeySet() ) {
+ if( key.startsWith(prefix) ) {
+ prefixMap.put( key, ctx.getAttribute(key) );
+ }
+ }
+
+ return prefixMap;
+ }
+
+ /**
+ * Returns true if key's value in context memory is "" or if it doesn't
+ * exist in context memory.
+ * @param ctx Reference to context memory.
+ * @param key Key to search for.
+ * @return true if key's value in context memory is "" or if it doesn't
+ * exist in context memory.
+ * @since 1.0
+ */
+ public static final boolean ctxKeyEmpty( SvcLogicContext ctx, String key ) {
+ String value = ctx.getAttribute(key);
+ return value == null || value.isEmpty();
+ }
+
+ /**
+ * Adds all key-value pairs in the entries Map to context memory.
+ * @param ctx Reference to context memory. Value's {@code toString()}
+ * function is used to add it.
+ * @param entries {@code Map<String, ?>} of key-value pairs to add to
+ * context memory. Value's {@code toString()} function is used to add it.
+ * @return Reference to context memory to be used for function chaining.
+ */
+ public static final SvcLogicContext ctxPutAll( SvcLogicContext ctx, Map<String, ?> entries ) {
+ for( Map.Entry<String, ?> entry : entries.entrySet() ) {
+ ctxSetAttribute( ctx, entry.getKey(), entry.getValue() );
+ //ctx.setAttribute(entry.getKey(), entry.getValue().toString());
+ }
+
+ return ctx;
+ }
+
+ /**
+ * Sets a key in context memory to the output of object's toString(). The
+ * key is deleted from context memory if object is null.
+ * @param ctx Reference to context memory.
+ * @param key Key to set.
+ * @param object Object whose toString() will be the value set
+ */
+ public static final void ctxSetAttribute( SvcLogicContext ctx, String key, Object object ) {
+ if( object == null ) {
+ ctx.setAttribute(key, null);
+ }
+ else {
+ ctx.setAttribute(key, object.toString());
+ }
+ }
+
+ /**
+ * Sets a key in context memory to the output of object's toString().
+ * <p>
+ * The key is deleted from context memory if object is null. The key and
+ * value set in context memory are logged to the Logger at the provided
+ * logLevel level.
+ * @param <O> Any Java object
+ * @param ctx Reference to context memory.
+ * @param key Key to set.
+ * @param obj Object whose toString() will be the value set
+ * @param LOG Logger to log to
+ * @param logLevel level to log at in Logger
+ */
+ public static final <O extends Object> void ctxSetAttribute( SvcLogicContext ctx, String key, O obj, Logger LOG, LogLevel logLevel ) {
+ String value = Objects.toString( obj, null );
+ ctx.setAttribute( key, value );
+ if( logLevelIsEnabled(LOG, logLevel ) ) {
+ if( value == null ) {
+ logMessageAtLevel( LOG, logLevel, "Deleting " + key );
+ }
+ else {
+ logMessageAtLevel( LOG, logLevel, "Setting " + key + " = " + value );
+ }
+ }
+ }
+
+ /**
+ * Utility function used to get an array's length from context memory.
+ * Will return 0 if key doesn't exist in context memory or isn't numeric.
+ * <p>
+ * Use to obtain a context memory array length without having to worry
+ * about throwing a NumberFormatException.
+ * @param ctx Reference to context memory
+ * @param key Key in context memory whose value is the array's length. If
+ * the key doesn't end in "_length", then "_length is appended.
+ * @param log Reference to Logger to log to
+ * @return The array length or 0 if the key is not found in context memory.
+ * @since 1.0
+ */
+ public static final int getArrayLength( SvcLogicContext ctx, String key ) {
+ return getArrayLength(ctx, key, null, null, null);
+ }
+
+ /**
+ * Utility function used to get an array's length from context memory.
+ * Will return 0 if key doesn't exist in context memory or isn't numeric
+ * and print the provided log message to the configured log file.
+ * <p>
+ * Use to obtain a context memory array length without having to worry
+ * about throwing a NumberFormatException.
+ * @param ctx Reference to context memory.
+ * @param key Key in context memory whose value is the array's length. If
+ * the key doesn't end in "_length", then "_length is appended.
+ * @param log Reference to Logger to log to. Doesn't log if null.
+ * @param logLevel Logging level to log the message at if the context
+ * memory key isn't found. Doesn't log if null.
+ * @param log_message Message to log if the context memory key isn't found.
+ * Doesn't log if null.
+ * @return The array length or 0 if the key is not found in context memory.
+ * @since 1.0
+ */
+ public static final int getArrayLength( SvcLogicContext ctx, String key, Logger log, LogLevel logLevel, String log_message ) {
+ String ctxKey = key.endsWith(LENGTH) ? key : key + LENGTH;
+ try {
+ return Integer.parseInt(ctx.getAttribute(ctxKey));
+ }
+ catch( NumberFormatException e ) {
+ if( log != null && logLevel != null && log_message != null ) {
+ switch( logLevel ) {
+ case TRACE:
+ log.trace(log_message);
+ break;
+ case DEBUG:
+ log.debug(log_message);
+ break;
+ case INFO:
+ log.info(log_message);
+ break;
+ case WARN:
+ log.warn(log_message);
+ break;
+ case ERROR:
+ log.error(log_message);
+ break;
+ }
+ }
+ }
+
+ return 0;
+ }
+
+ /**
+ * Prints sorted context memory key-value pairs to the log file at the log
+ * level. Returns immediately if the log level isn't enabled.
+ * <p>
+ * O(n log(n)) time where n = size of context memory
+ * @param ctx Reference to context memory
+ * @param log Reference to Logger to log to
+ * @param logLevel Logging level to log the context memory key-value pairs
+ * at.
+ * @since 1.0
+ */
+ public static final void logContextMemory( SvcLogicContext ctx, Logger log, LogLevel logLevel ) {
+ logLevelIsEnabled( log, logLevel );
+
+ // Print sorted context memory key-value pairs to the log
+ ArrayList<String> keys = new ArrayList<>(ctx.getAttributeKeySet());
+ Collections.sort(keys);
+ for( String key : keys ) {
+ logMessageAtLevel( log, logLevel, key + " = " + ctx.getAttribute(key) );
+ }
+ }
+
+
+
+ // ========== PRIVATE FUNCTIONS ==========
+
+ // TODO: javadoc
+ /**
+ *
+ * @param parameters
+ * @param log
+ * @param loglevel
+ * @since 7.0.1
+ */
+ public static final void logExecuteNodeParameters( Map<String,String> parameters, Logger log, LogLevel loglevel ) {
+ logLevelIsEnabled( log, loglevel );
+
+ for( Map.Entry<String,String> param : parameters.entrySet() ) {
+ logMessageAtLevel( log, loglevel, "PARAM: " + param.getKey() + " = " + param.getValue() );
+ }
+ }
+
+ // TODO: javadoc
+ /**
+ * Returns true if the loglevel is enabled. Otherwise, returns false.
+ * @param log Reference to logger
+ * @param loglevel Log level to check if enabled
+ * @return True if the loglevel is enabled. Otherwise, false
+ * @since 7.0.1
+ */
+ private static final boolean logLevelIsEnabled( Logger log, LogLevel loglevel ) {
+ // Return immediately if logging level isn't enabled
+ switch( loglevel ) {
+ case TRACE:
+ if( log.isTraceEnabled() ) { return true; }
+ return false;
+ case DEBUG:
+ if( log.isDebugEnabled() ) { return true; }
+ return false;
+ case INFO:
+ if( log.isInfoEnabled() ) { return true; }
+ return false;
+ case WARN:
+ if( log.isWarnEnabled() ) { return true; }
+ return false;
+ case ERROR:
+ if( log.isErrorEnabled() ) { return true; }
+ return false;
+ default:
+ throw new IllegalArgumentException("Unknown LogLevel: " + loglevel.toString());
+ }
+ }
+
+ // TODO: javadoc
+ /**
+ *
+ * @param log
+ * @param loglevel
+ * @param msg
+ * @since 7.0.1
+ */
+ private static final void logMessageAtLevel( Logger log, LogLevel loglevel, String msg ) {
+ switch( loglevel ) {
+ case TRACE:
+ log.trace(msg);
+ return;
+ case DEBUG:
+ log.debug(msg);
+ return;
+ case INFO:
+ log.info(msg);
+ return;
+ case WARN:
+ log.warn(msg);
+ return;
+ case ERROR:
+ log.error(msg);
+ return;
+ }
+ }
+
+
+
+ // ========== LOCAL CLASSES ==========
+
+ private class SortableCtxListElement implements Comparable<SortableCtxListElement> {
+ HashMap<String,String> child_elements = new HashMap<>();
+ String[] sort_fields;
+
+ public SortableCtxListElement( SvcLogicContext ctx, String root, String[] sort_fields ) {
+ this.sort_fields = sort_fields;
+
+ for( String key : ctx.getAttributeKeySet() ) {
+ if( key.startsWith(root) ) {
+ if( key.length() == root.length() ) {
+ child_elements.put("", ctx.getAttribute(key));
+ break;
+ }
+ else {
+ child_elements.put(key.substring(root.length()+1), ctx.getAttribute(key));
+ }
+ }
+ }
+ }
+
+ @Override
+ public int compareTo(SortableCtxListElement arg0) {
+ if( sort_fields == null ) {
+ return this.child_elements.get("").compareTo(arg0.child_elements.get(""));
+ }
+
+ for( String field : this.sort_fields ) {
+ int result = this.child_elements.get(field).compareTo(arg0.child_elements.get(field));
+ if( result != 0 ) {
+ return result;
+ }
+ }
+
+ return 0;
+ }
+
+ @Override
+ public boolean equals(Object object) {
+ if (this == object) {
+ return true;
+ }
+ if (!(object instanceof SortableCtxListElement)) {
+ return false;
+ }
+ if (!super.equals(object)) {
+ return false;
+ }
+
+ SortableCtxListElement that = (SortableCtxListElement) object;
+
+ if (child_elements != null ? !child_elements.equals(that.child_elements)
+ : that.child_elements != null) {
+ return false;
+ }
+ // Probably incorrect - comparing Object[] arrays with Arrays.equals
+ if (!Arrays.equals(sort_fields, that.sort_fields)) {
+ return false;
+ }
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int result = super.hashCode();
+ result = 31 * result + (child_elements != null ? child_elements.hashCode() : 0);
+ result = 31 * result + Arrays.hashCode(sort_fields);
+ return result;
+ }
+ }
+
+ /**
+ * Creates a file that contains the content of context memory.
+ * @param parameters - must contain the parameter filename
+ * @param ctx Reference to context memory
+ * @throws SvcLogicException thrown if file cannot be created or if parameters are missing
+ */
+ public static void printContext(Map<String, String> parameters, SvcLogicContext ctx) throws SvcLogicException {
+ if (parameters == null || parameters.isEmpty()) {
+ throw new SvcLogicException("no parameters passed");
+ }
+
+ checkParameters(parameters, new String[]{"filename"}, LOG);
+
+ String fileName = parameters.get("filename");
+
+
+ try (FileOutputStream fstr = new FileOutputStream(new File(fileName));
+ PrintStream pstr = new PrintStream(fstr, true);)
+ {
+ pstr.println("#######################################");
+ for (String attr : ctx.getAttributeKeySet()) {
+ pstr.println(attr + " = " + ctx.getAttribute(attr));
+ }
+ } catch (Exception e) {
+ throw new SvcLogicException("Cannot write context to file " + fileName, e);
+ }
+
+
+ }
+
+ public static void logContextProperties(Map<String, String> parameters, SvcLogicContext ctx)
+ throws SvcLogicException {
+ if (LOG.isTraceEnabled()) {
+ String subpath = parameters.get("subpath");
+ if (subpath != null && !subpath.isEmpty()) {
+ ctx.printProperties(ctx.toProperties(), subpath);
+ } else {
+ ctx.printProperties(ctx.toProperties());
+ }
+ }
+ }
+
+ public static void logContextAttributes(Map<String, String> parameters, SvcLogicContext ctx)
+ throws SvcLogicException {
+ if (LOG.isTraceEnabled()) {
+ String subpath = parameters.get("subpath");
+ if (subpath != null && !subpath.isEmpty()) {
+ ctx.printAttributes(subpath);
+ } else {
+ ctx.printAttributes();
+ }
+ }
+ }
+
+ /**
+ * Checks context memory for a set of required parameters
+ * Every parameter aside from prefix will be treated as mandatory
+ * @param parameters HashMap<String,String> of parameters passed by the DG to this function
+ * <table border="1">
+ * <thead><th>parameter</th><th>Mandatory/Optional</th><th>description</th></thead>
+ * <tbody>
+ * <tr><td>prefix</td><td>Optional</td><td>the prefix will be added to each parameter</td></tr>
+ * </tbody>
+ * </table>
+ * @param ctx Reference to context memory
+ * @throws SvcLogicException
+ * @since 11.0.2
+ */
+ public static void requiredParameters(Map<String, String> parameters, SvcLogicContext ctx) throws SvcLogicException {
+ if (parameters == null || parameters.keySet().isEmpty()) {
+ String errorMessage = "requiredParameters should not be called if the parameters hashmap is null or empty!";
+ LOG.error(errorMessage);
+ throw new SvcLogicException(errorMessage);
+ }
+ String prefixValue = null;
+ String prefix = "prefix";
+ if(parameters.containsKey(prefix)){
+ prefixValue = parameters.get(prefix);
+ parameters.remove(prefix);
+ }
+ checkParameters(prefixValue, ctx.getAttributeKeySet(), parameters.keySet(), LOG);
+ }
+
+ private static void checkParameters(String prefixValue, Set<String> ctx, Set<String> parameters, Logger log) throws SvcLogicException {
+ for (String param : parameters) {
+ if (prefixValue != null) {
+ param = prefixValue + param;
+ }
+ if (!ctx.contains(param)) {
+ String errorMessage = "This method requires the parameters [" + StringUtils.join(parameters, ",")
+ + "], but " + param + " was not passed in.";
+ log.error(errorMessage);
+ throw new SvcLogicException(errorMessage);
+ }
+ }
+ }
+
+ /**
+ * is in a different DG invocation just before/after we call NCS and set the state to InProgress
+ */
+ /**
+ * setTime write the current date time to a string located at outputPath
+ * @param parameters - requires outputPath to not be null
+ * @param ctx Reference to context memory
+ * @throws SvcLogicException if a required parameter is missing an exception is thrown
+ */
+ public static void setTime(Map<String, String> parameters, SvcLogicContext ctx) throws SvcLogicException
+ {
+ checkParameters(parameters, new String[] { "outputPath" }, LOG);
+
+ // Set the DateFormat
+ // "2015-03-16T12:18:35.138Z"
+ SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
+
+ // Parse the date
+ String ctxVariable = parameters.get("outputPath");
+ try {
+ String dateTime = format.format(new Date());
+ ctx.setAttribute(ctxVariable, dateTime);
+ } catch (Exception ex) {
+ throw new SvcLogicException("problem with setTime", ex);
+ }
+ }
+
+ /**
+ * jsonStringToCtx takes a json string stored as a single property in context memory and breaks it into individual properties
+ * @param parameters - requires source, outputPath and isEscaped to not be null.
+ * @param ctx Reference to context memory
+ * @throws SvcLogicException if a required parameter is missing an exception is thrown
+ */
+ public static void jsonStringToCtx(Map<String, String> parameters, SvcLogicContext ctx) throws SvcLogicException
+ {
+ checkParameters(parameters, new String[] { "source","outputPath","isEscaped" }, LOG);
+ try {
+ String source = ctx.getAttribute(parameters.get("source"));
+ if("true".equals(parameters.get("isEscaped"))){
+ source = StringEscapeUtils.unescapeJson(source);
+ }
+ ctx.mergeJson(parameters.get("outputPath"), source);
+ // writeJsonToCtx(source, ctx,parameters.get("outputPath"));
+ } catch (Exception ex) {
+ throw new SvcLogicException("problem with jsonStringToCtx", ex);
+ }
+ }
+
+ protected static void writeJsonToCtx(String resp, SvcLogicContext ctx, String prefix){
+ // Refactored code for this method into SvcLogicContext object. Leaving this
+ // method in place for backward compatibility.
+ ctx.mergeJson(prefix, resp);
+ }
+
+ /**
+ * updateJsonObjectString takes a json object string, and adds or deletes the properties of it
+ * @param parameters - requires source, outputPath and keys to be added or deleted.
+ * The key of parameter starts with "add.", e.g. "add.A", and then "A" and its value will be added
+ * to the JSON object.
+ * The key of parameter starts with "delete.", e.g. "delete.B", and then "B" will be deleted from
+ * the JSON object.
+ * @param ctx Reference to context memory
+ * @throws SvcLogicException if a required parameter is missing an exception is thrown
+ */
+ public static void updateJsonObjectString(Map<String, String> parameters, SvcLogicContext ctx) throws SvcLogicException {
+ checkParameters(parameters, new String[] {"source", "outputPath"}, LOG);
+ try {
+ String source = ctx.getAttribute(parameters.get("source"));
+ JsonParser jp = new JsonParser();
+ JsonElement element = jp.parse(source);
+ if (element.isJsonObject()) {
+ JsonObject jsonObject = element.getAsJsonObject();
+ updateJsonObject(jsonObject, parameters);
+
+ String target = jsonObject.toString();
+ ctx.setAttribute(parameters.get("outputPath"), target);
+ } else {
+ throw new SvcLogicException("just update JSON object string");
+ }
+ } catch (Exception ex) {
+ throw new SvcLogicException("problem with updateJsonObjectString", ex);
+ }
+ }
+
+ protected static void updateJsonObject(JsonObject jsonObject, Map<String, String> parameters) throws SvcLogicException {
+ List<String> deleted_params = parameters.keySet().stream().filter(param -> param.startsWith("delete.")).
+ collect(Collectors.toList());
+ for (String param: deleted_params) {
+ String[] action_key = param.split("\\.", 2);
+ if (action_key.length < 2) {
+ throw new SvcLogicException("error parameter format: " + param + ", must be \"delete.<key>\"");
+ }
+ jsonObject.remove(action_key[1]);
+ }
+
+ List<String> added_params = parameters.keySet().stream().filter(param -> param.startsWith("add.")).
+ collect(Collectors.toList());
+ for (String param: added_params) {
+ String[] action_key = param.split("\\.", 2);
+ if (action_key.length < 2) {
+ throw new SvcLogicException("error parameter format: " + param + ", must be \"add.<key>\"");
+ }
+ jsonObject.addProperty(action_key[1], parameters.get(param));
+ }
+ }
+
+ /**
+ * getAttributeValue takes a ctx memory path as a string, gets the value stored at this path and set this value in context memory at
+ * outputPath
+ * @param parameters - requires source and outputPath
+ * @param ctx Reference to context memory
+ * @throws SvcLogicException if a required parameter is missing an exception is thrown
+ */
+ public static void getAttributeValue(Map<String, String> parameters, SvcLogicContext ctx) throws SvcLogicException {
+ checkParameters(parameters, new String[] { "source", "outputPath" }, LOG);
+ String source = ctx.getAttribute(parameters.get("source"));
+ ctx.setAttribute(parameters.get("outputPath"), source);
+ }
+
+ /**
+ * ctxListContains provides a way to see if a context memory list contains a key value
+ * @param parameters - requires list, keyName, keyValue, outputPath to all not be null.
+ * @param ctx Reference to context memory
+ * @throws SvcLogicException if a required parameter is missing an exception is thrown
+ */
+ public static String ctxListContains(Map<String, String> parameters, SvcLogicContext ctx) throws SvcLogicException {
+ checkParameters(parameters, new String[]{"list", "keyName", "keyValue"}, LOG);
+
+ try {
+ String ctxList = parameters.get("list");
+ ctxList = (ctxList.endsWith(LENGTH)) ? ctxList : ctxList + LENGTH;
+ int listLength = getArrayLength(ctx, ctxList);
+
+ if (listLength == 0) {
+ LOG.debug("List is not in context memory");
+ return "false";
+ } else {
+ Set<String> keys = new HashSet<String>();
+
+ String listPrefix = ctxList.substring(0, ctxList.lastIndexOf("_")) + "[";
+ String listSuffix = "]." + parameters.get("keyName");
+
+ for (int i = 0; i < listLength; i++) {
+ String keyLocation = listPrefix + i + listSuffix;
+ keys.add(ctx.getAttribute(keyLocation));
+ }
+
+ if (keys.contains(parameters.get("keyValue"))) {
+ LOG.debug("List " + parameters.get("list") + " contains " + parameters.get("keyValue"));
+ return "true";
+ } else {
+ LOG.debug("List " + parameters.get("list") + " do not contains " + parameters.get("keyValue"));
+ return "false";
+ }
+ }
+ } catch (Exception ex) {
+ throw new SvcLogicException("ctxListContains failed", ex);
+ }
+ }
+
+ /**
+ * set properties in context memory for a container </br>
+ * parameters with a null or empty key or value are ignored </br>
+ * required parameter root - root + "." + parameters.key
+ * is the key to set the value too value in context memory </br>
+ * optional parameter valueRoot - if set: valueRoot + "." + parameters.value
+ * is the key to get the value from context memory
+ *
+ * @param parameters - root (required), valueRoot (optional), properties names and values to be set
+ * @param ctx Reference to context memory
+ * @return success or failure of operation
+ */
+ public static String setPropertiesForRoot(Map<String, String> parameters, SvcLogicContext ctx) {
+ LOG.debug("Execute Node \"setPropertiesForRoot\"");
+ try {
+ checkParameters(parameters, new String[]{"root"}, LOG);
+ } catch (Exception ex) {
+ return SvcLogicConstants.FAILURE;
+ }
+
+ String root = parameters.get("root");
+
+ if (StringUtils.isEmpty(root)) {
+ return SvcLogicConstants.FAILURE;
+ }
+
+ // set context memory to the the properties passed with root as prefix
+ setParameterValuesToRoot(parameters, ctx, root);
+
+ return SvcLogicConstants.SUCCESS;
+ }
+
+ private static boolean setParameterValuesToRoot(Map<String, String> parameters, SvcLogicContext ctx, String root) {
+ boolean changeFlag = false;
+ String valueRoot = parameters.get("valueRoot");
+
+ for (Map.Entry<String, String> entry : parameters.entrySet()) {
+ // ignore if it's the root parameter
+ if (!entry.getKey().equals("root")) {
+ String keyToBeSet = root + "." + entry.getKey();
+ String valueToBeSet = "";
+
+ if (StringUtils.isEmpty(valueRoot)) {
+ valueToBeSet = entry.getValue();
+ } else {
+ valueToBeSet = ctx.getAttribute(valueRoot + "." + entry.getValue());
+ }
+
+ LOG.debug("Setting context memory: " + keyToBeSet + " = " + valueToBeSet);
+
+ if (!StringUtils.isEmpty(entry.getKey()) && !StringUtils.isEmpty(valueToBeSet)) {
+ ctxSetAttribute(ctx, keyToBeSet, valueToBeSet);
+ changeFlag = true;
+ }
+ }
+ }
+
+ return changeFlag;
+ }
+
+ /**
+ * takes container list and set the properties with the value provided </br>
+ * parameters with a null or empty key or value are ignored </br>
+ * required parameters </br>
+ * prefixKey + "." + parameters.key is the key to set the value too value in context memory </br>
+ * prefixKey + "[index]." + keyName is the key of the entry in the list in context memory </br>
+ * keyValue is the value of the key of the list entry in context memory (must be actual value)</br>
+ * optional parameter valuePrefixKey - if set: valuePrefixKey + "." + parameters.value
+ * is the key to get the value from context memory
+ *
+ * @param parameters </br>
+ * - prefixKey e.g "service-data.universal-cpe-ft.l2-switch-interfaces" </br>
+ * - keyName e.g "name" </br>
+ * - keyValue e.g "WAN1" (must be actual value and not use the prefixKey as root) </br>
+ * - valuePrefixKey (optional) e.g "input.universal-cpe-ft.l2-switch-interfaces[1] </br>
+ * - properties to be set, values for the properties </br>
+ * @param ctx reference to context memory
+ * @return success or failure of operation
+ */
+ public static String setPropertiesForList(Map<String, String> parameters, SvcLogicContext ctx) {
+ LOG.debug("Execute Node \"setPropertiesForList\"");
+ try {
+ checkParameters(parameters, new String[]{"prefixKey", "keyName", "keyValue"}, LOG);
+ } catch (Exception e) {
+ LOG.error("a required parameter is missing");
+ return SvcLogicConstants.FAILURE;
+ }
+
+ String prefixKey = parameters.get("prefixKey");
+ String keyName = parameters.get("keyName");
+ String keyValue = parameters.get("keyValue");
+
+ if (StringUtils.isEmpty(keyName) || StringUtils.isEmpty(keyValue) || StringUtils.isEmpty(prefixKey)) {
+ LOG.error("a required parameters value is empty or null");
+ return SvcLogicConstants.FAILURE;
+ }
+
+ int listLength = getArrayLength(ctx, prefixKey);
+
+ Map<String, String> containParams = new HashMap<>();
+ containParams.put("list", prefixKey);
+ containParams.put("keyName", keyName);
+ containParams.put("keyValue", keyValue);
+
+ String valuePrefixKey = parameters.get("valuePrefixKey");
+
+ try {
+ // create new list in context memory
+ if (listLength == 0) {
+ // since there's no length found make sure there's no current data at prefixKey in context memory
+ Map<String, String> map = ctxGetBeginsWith(ctx, prefixKey);
+
+ if (map.size() == 0) {
+ setNewEntryInList(parameters, ctx, keyName, keyValue, prefixKey, valuePrefixKey, listLength);
+ } else {
+ LOG.error("there was no length for the list parameter set in context memory "
+ + "but " + map.size() + " entries were found in context memory "
+ + "where the key begins with: " + prefixKey);
+
+ return SvcLogicConstants.FAILURE;
+ }
+ } else if (ctxListContains(containParams, ctx) == "false") {
+ setNewEntryInList(parameters, ctx, keyName, keyValue, prefixKey, valuePrefixKey, listLength);
+ } else if (ctxListContains(containParams, ctx) == "true") {
+ // else update the context memory with the properties passed in at the right index level
+ String listPrefix = prefixKey + "[";
+ String listSuffix = "].";
+
+ for (int i = 0; i < listLength; i++) {
+ String listRootWithIndex = listPrefix + i + listSuffix;
+ String listKeyName = listRootWithIndex + keyName;
+ String valueAtListIndexKey = ctx.getAttribute(listKeyName);
+
+ if (valueAtListIndexKey.equals(keyValue)) {
+ setParametersToCtxList(parameters, ctx, listRootWithIndex, valuePrefixKey);
+ }
+ }
+ }
+ } catch (SvcLogicException e) {
+ LOG.error("Call to ctxListContains failed: " + e.getMessage());
+
+ return SvcLogicConstants.FAILURE;
+ }
+
+ return SvcLogicConstants.SUCCESS;
+ }
+
+ private static void setNewEntryInList(Map<String, String> parameters, SvcLogicContext ctx, String keyName,
+ String keyValue, String prefixKey, String valuePrefixKey, int listLength) {
+ String prefixKeyWithIndex = prefixKey + "[" + listLength + "].";
+ String listKeyName = prefixKeyWithIndex + keyName;
+
+ // set list key
+ LOG.debug("Setting context memory, new list entry with key: " + listKeyName + " = " + keyValue);
+ ctxSetAttribute(ctx, listKeyName, keyValue);
+
+ // set the other parameters
+ setParametersToCtxList(parameters, ctx, prefixKeyWithIndex, valuePrefixKey);
+
+ // set length of list
+ String ListLengthKeyName = prefixKey + LENGTH;
+
+ ctxSetAttribute(ctx, prefixKey + LENGTH, listLength + 1);
+ LOG.debug("Updated _length: " + prefixKey + "_length is now " + ctx.getAttribute(ListLengthKeyName));
+ }
+
+ /**
+ * helper function to set the parameter properties for list at the provided prefix key
+ *
+ * @param parameters
+ * @param ctx
+ * @param prefixKey
+ * @return true if any new context memory was added and or modified
+ */
+ private static boolean setParametersToCtxList(Map<String, String> parameters, SvcLogicContext ctx, String prefixKeyWithIndex,
+ String valuePrefixKey) {
+ boolean changeFlag = false;
+
+ for (Map.Entry<String, String> entry : parameters.entrySet()) {
+ if (! (entry.getKey().equals("prefixKey") ||
+ entry.getKey().equals("keyName") ||
+ entry.getKey().equals("keyValue")) ||
+ entry.getKey().equals("valuePrefixKey")) {
+
+ String keyToBeSet = prefixKeyWithIndex + entry.getKey();
+ String valueToBeSet = "";
+
+ if (StringUtils.isEmpty(valuePrefixKey)) {
+ valueToBeSet = entry.getValue();
+ } else {
+ valueToBeSet = ctx.getAttribute(valuePrefixKey + "." + entry.getValue());
+ }
+
+ LOG.debug("Setting context memory: " + keyToBeSet + " = " + valueToBeSet);
+
+ // only set context memory if properties key and value are not empty or null
+ if (!StringUtils.isEmpty(entry.getKey()) && !StringUtils.isEmpty(valueToBeSet)) {
+ ctxSetAttribute(ctx, keyToBeSet, valueToBeSet);
+ changeFlag = true;
+ }
+ }
+ }
+
+ return changeFlag;
+ }
+
+ public static String containsKey(Map<String, String> parameters, SvcLogicContext ctx) throws SvcLogicException {
+ String key = parameters.get("key");
+ Boolean keyFound = ctx.getAttributeKeySet().contains(key);
+ if (keyFound) {
+ return "true";
+ }
+ return "false";
+ }
+
+}
diff --git a/core/sliPluginUtils/provider/src/main/java/org/onap/ccsdk/sli/core/slipluginutils/SliStringUtils.java b/core/sliPluginUtils/provider/src/main/java/org/onap/ccsdk/sli/core/slipluginutils/SliStringUtils.java
new file mode 100644
index 000000000..9e3367d45
--- /dev/null
+++ b/core/sliPluginUtils/provider/src/main/java/org/onap/ccsdk/sli/core/slipluginutils/SliStringUtils.java
@@ -0,0 +1,559 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Modifications Copyright (C) 2018 IBM.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.slipluginutils;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.net.URLEncoder;
+import java.util.Map;
+import java.util.Base64;
+import org.apache.commons.text.StringEscapeUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.core.sli.SvcLogicJavaPlugin;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A SvcLogicJavaPlugin that exposes java.lang.String functions to DirectedGraph
+ */
+public class SliStringUtils implements SvcLogicJavaPlugin {
+ private static final Logger LOG = LoggerFactory.getLogger(SliStringUtils.class);
+ public static final String INPUT_PARAM_KEY = "key";
+ public static final String INPUT_PARAM_SOURCE = "source";
+ public static final String INPUT_PARAM_TARGET = "target";
+ public static final String TRUE_CONSTANT = "true";
+ public static final String FALSE_CONSTANT = "false";
+
+ public SliStringUtils() {}
+
+ /**
+ * Provides split functionality to Directed Graphs.
+ * @param parameters HashMap<String,String> of parameters passed by the DG to this function
+ * <table border="1">
+ * <thead><th>parameter</th><th>Mandatory/Optional</th><th>description</th></thead>
+ * <tbody>
+ * <tr><td>original_string</td><td>Mandatory</td><td>String to perform split on</td></tr>
+ * <tr><td>regex</td><td>Mandatory</td><td>the delimiting regular expression</td></tr>
+ * <tr><td>limit</td><td>Optional</td><td>result threshold. See String.split method for further description. Defaults to 0</td></tr>
+ * <tr><td>ctx_memory_result_key</td><td>Mandatory</td><td>Key in context memory to populate the resulting array of strings under</td></tr>
+ * </tbody>
+ * </table>
+ * @param ctx Reference to context memory
+ * @throws SvcLogicException
+ * @since 11.0.2
+ * @see String#split(String, int)
+ */
+ public void split( Map<String, String> parameters, SvcLogicContext ctx ) throws SvcLogicException {
+ final String original_string = parameters.get("original_string");
+ LOG.trace("original_string = " + original_string);
+ final String regex = parameters.get("regex");
+ LOG.trace("regex = " + regex);
+ final String limit_str = parameters.get("limit");
+ LOG.trace("limit_str = " + limit_str);
+ final String ctx_memory_result_key = parameters.get("ctx_memory_result_key");
+ LOG.trace("ctx_memory_result_key = " + ctx_memory_result_key);
+
+ try {
+ // Validation that parameters are not null
+ SliPluginUtils.checkParameters( parameters, new String[]{"original_string","regex","ctx_memory_result_key"}, LOG );
+
+ // Read limit from context memory. Default to 0 if null/empty
+ int limit = 0;
+ if( StringUtils.isNotEmpty(limit_str) ) {
+ try {
+ limit = Integer.parseInt(limit_str);
+ }
+ catch( NumberFormatException e ) {
+ throw new IllegalArgumentException( "The limit parameter of the SliStringUtils.split() function must be a number, empty string, or null", e );
+ }
+ }
+
+ // Call String.split(regex,limit) on string passed in
+ String[] split_string = original_string.split(regex, limit);
+
+ // Populate context memory with results
+ for( int i = 0; i < split_string.length; i++ ) {
+ SliPluginUtils.ctxSetAttribute(ctx, ctx_memory_result_key + '[' + i + ']', split_string[i], LOG, SliPluginUtils.LogLevel.DEBUG);
+ }
+ SliPluginUtils.ctxSetAttribute(ctx, ctx_memory_result_key + "_length", new Integer(split_string.length), LOG, SliPluginUtils.LogLevel.DEBUG);
+ }
+ catch( Exception e ) {
+ // Have error message print parameters
+ throw new SvcLogicException( "An error occurred during SliStringUtils.split() where original_string = " + quotedOrNULL(regex) +
+ " regex = " + quotedOrNULL(regex) +
+ " limit = " + quotedOrNULL(regex) +
+ " ctx_memory_result_key = " + quotedOrNULL(regex), e );
+ }
+ }
+
+ public static String quotedOrNULL( String str ) {
+ return (str == null) ? "NULL" : '"' + str + '"';
+ }
+
+ /**
+ * exposes equalsIgnoreCase to directed graph
+ * @param parameters HashMap<String,String> of parameters passed by the DG to this function
+ * emits a true or false outcome
+ * <table border="1">
+ * <thead><th>parameter</th><th>Mandatory/Optional</th><th>description</th></thead>
+ * <tbody>
+ * <tr><td>source</td><td>Mandatory</td><td>source string</td></tr>
+ * <tr><td>target</td><td>Mandatory</td><td>target string</td></tr>
+ * </tbody>
+ * </table>
+ * @param ctx Reference to context memory
+ * @throws SvcLogicException
+ * @since 11.0.2
+ */
+ public static String equalsIgnoreCase(Map<String, String> parameters, SvcLogicContext ctx) throws SvcLogicException {
+ SliPluginUtils.checkParameters(parameters, new String[] {INPUT_PARAM_SOURCE, INPUT_PARAM_TARGET}, LOG);
+ if (parameters.get(INPUT_PARAM_SOURCE).equalsIgnoreCase(parameters.get(INPUT_PARAM_TARGET))) {
+ return TRUE_CONSTANT;
+ }
+ return FALSE_CONSTANT;
+ }
+
+ /**
+ * exposes toUpperCase to directed graph
+ * writes an upperCase version of source to outputPath
+ * @param parameters HashMap<String,String> of parameters passed by the DG to this function
+ * <table border="1">
+ * <thead><th>parameter</th><th>Mandatory/Optional</th><th>description</th></thead>
+ * <tbody>
+ * <tr><td>source</td><td>Mandatory</td><td>source string</td></tr>
+ * <tr><td>outputPath</td><td>Mandatory</td><td>the location in context memory the result is written to</td></tr>
+ * </tbody>
+ * </table>
+ * @param ctx Reference to context memory
+ * @throws SvcLogicException
+ * @since 11.0.2
+ */
+ public static void toUpper(Map<String, String> parameters, SvcLogicContext ctx) throws SvcLogicException {
+ SliPluginUtils.checkParameters(parameters, new String[]{INPUT_PARAM_SOURCE,"outputPath"}, LOG);
+ ctx.setAttribute(parameters.get("outputPath"), parameters.get(INPUT_PARAM_SOURCE).toUpperCase());
+ }
+
+ /**
+ * exposes toLowerCase to directed graph
+ * writes a lowerCase version of source to outputPath
+ * @param parameters HashMap<String,String> of parameters passed by the DG to this function
+ * <table border="1">
+ * <thead><th>parameter</th><th>Mandatory/Optional</th><th>description</th></thead>
+ * <tbody>
+ * <tr><td>source</td><td>Mandatory</td><td>source string</td></tr>
+ * <tr><td>outputPath</td><td>Mandatory</td><td>the location in context memory the result is written to</td></tr>
+ * </tbody>
+ * </table>
+ * @param ctx Reference to context memory
+ * @throws SvcLogicException
+ * @since 11.0.2
+ */
+ public static void toLower(Map<String, String> parameters, SvcLogicContext ctx) throws SvcLogicException {
+ SliPluginUtils.checkParameters(parameters, new String[]{INPUT_PARAM_SOURCE,"outputPath"}, LOG);
+ ctx.setAttribute(parameters.get("outputPath"), parameters.get(INPUT_PARAM_SOURCE).toLowerCase());
+ }
+
+ /**
+ * exposes contains to directed graph to test if one string contains another
+ * tests if the source contains the target
+ * @param parameters HashMap<String,String> of parameters passed by the DG to this function
+ * emits a true or false outcome
+ * <table border="1">
+ * <thead><th>parameter</th><th>Mandatory/Optional</th><th>description</th></thead>
+ * <tbody>
+ * <tr><td>source</td><td>Mandatory</td><td>source string</td></tr>
+ * <tr><td>target</td><td>Mandatory</td><td>target string</td></tr>
+ * </tbody>
+ * </table>
+ * @param ctx Reference to context memory
+ * @throws SvcLogicException
+ * @since 11.0.2
+ */
+ public static String contains(Map<String, String> parameters, SvcLogicContext ctx) throws SvcLogicException {
+ SliPluginUtils.checkParameters(parameters, new String[] {INPUT_PARAM_SOURCE, INPUT_PARAM_TARGET}, LOG);
+ if (parameters.get(INPUT_PARAM_SOURCE).contains(parameters.get(INPUT_PARAM_TARGET))) {
+ return TRUE_CONSTANT;
+ }
+ return FALSE_CONSTANT;
+ }
+
+ /**
+ * exposes endsWith to directed graph to test if one string endsWith another string
+ * tests if the source ends with the target
+ * @param parameters HashMap<String,String> of parameters passed by the DG to this function
+ * emits a true or false outcome
+ * <table border="1">
+ * <thead><th>parameter</th><th>Mandatory/Optional</th><th>description</th></thead>
+ * <tbody>
+ * <tr><td>source</td><td>Mandatory</td><td>source string</td></tr>
+ * <tr><td>target</td><td>Mandatory</td><td>target string</td></tr>
+ * </tbody>
+ * </table>
+ * @param ctx Reference to context memory
+ * @throws SvcLogicException
+ * @since 11.0.2
+ */
+ public static String endsWith(Map<String, String> parameters, SvcLogicContext ctx) throws SvcLogicException {
+ SliPluginUtils.checkParameters(parameters, new String[] {INPUT_PARAM_SOURCE, INPUT_PARAM_TARGET}, LOG);
+ if (parameters.get(INPUT_PARAM_SOURCE).endsWith(parameters.get(INPUT_PARAM_TARGET))) {
+ return TRUE_CONSTANT;
+ }
+ return FALSE_CONSTANT;
+ }
+
+ /**
+ * exposes startsWith to directed graph to test if one string endsWith another string
+ * tests if the source ends with the target
+ * @param parameters HashMap<String,String> of parameters passed by the DG to this function
+ * emits a true or false outcome
+ * <table border="1">
+ * <thead><th>parameter</th><th>Mandatory/Optional</th><th>description</th></thead>
+ * <tbody>
+ * <tr><td>source</td><td>Mandatory</td><td>source string</td></tr>
+ * <tr><td>target</td><td>Mandatory</td><td>target string</td></tr>
+ * </tbody>
+ * </table>
+ * @param ctx Reference to context memory
+ * @throws SvcLogicException
+ * @since 11.0.2
+ */
+ public static String startsWith(Map<String, String> parameters, SvcLogicContext ctx) throws SvcLogicException {
+ SliPluginUtils.checkParameters(parameters, new String[] {INPUT_PARAM_SOURCE, INPUT_PARAM_TARGET}, LOG);
+ if (parameters.get(INPUT_PARAM_SOURCE).startsWith(parameters.get(INPUT_PARAM_TARGET))) {
+ return TRUE_CONSTANT;
+ }
+ return FALSE_CONSTANT;
+ }
+
+ /**
+ * exposes trim to directed graph
+ * writes a trimmed version of the string to the outputPath
+ * @param parameters HashMap<String,String> of parameters passed by the DG to this function
+ * <table border="1">
+ * <thead><th>parameter</th><th>Mandatory/Optional</th><th>description</th></thead>
+ * <tbody>
+ * <tr><td>source</td><td>Mandatory</td><td>source string</td></tr>
+ * <tr><td>outputPath</td><td>Mandatory</td><td>the location in context memory the result is written to</td></tr>
+ * </tbody>
+ * </table>
+ * @param ctx Reference to context memory
+ * @throws SvcLogicException
+ * @since 11.0.2
+ */
+ public static void trim(Map<String, String> parameters, SvcLogicContext ctx) throws SvcLogicException {
+ SliPluginUtils.checkParameters(parameters, new String[]{INPUT_PARAM_SOURCE,"outputPath"}, LOG);
+ ctx.setAttribute(parameters.get("outputPath"), parameters.get(INPUT_PARAM_SOURCE).trim());
+ }
+
+ /**
+ * exposes String.length() to directed graph
+ * writes the length of source to outputPath
+ * @param parameters HashMap<String,String> of parameters passed by the DG to this function
+ * <table border="1">
+ * <thead><th>parameter</th><th>Mandatory/Optional</th><th>description</th></thead>
+ * <tbody>
+ * <tr><td>source</td><td>Mandatory</td><td>source string</td></tr>
+ * <tr><td>outputPath</td><td>Mandatory</td><td>the location in context memory the result is written to</td></tr>
+ * </tbody>
+ * </table>
+ * @param ctx Reference to context memory
+ * @throws SvcLogicException
+ * @since 11.0.2
+ */
+ public static void getLength(Map<String, String> parameters, SvcLogicContext ctx) throws SvcLogicException {
+ SliPluginUtils.checkParameters(parameters, new String[]{INPUT_PARAM_SOURCE,"outputPath"}, LOG);
+ ctx.setAttribute(parameters.get("outputPath"), String.valueOf(parameters.get(INPUT_PARAM_SOURCE).length()));
+ }
+
+ /**
+ * exposes replace to directed graph
+ * writes the length of source to outputPath
+ * @param parameters HashMap<String,String> of parameters passed by the DG to this function
+ * <table border="1">
+ * <thead><th>parameter</th><th>Mandatory/Optional</th><th>description</th></thead>
+ * <tbody>
+ * <tr><td>source</td><td>Mandatory</td><td>source string</td></tr>
+ * <tr><td>target</td><td>Mandatory</td><td>The sequence of char values to be replaced</td></tr>
+ * <tr><td>replacement</td><td>Mandatory</td><td>The replacement sequence of char values</td></tr>
+ * <tr><td>outputPath</td><td>Mandatory</td><td>the location in context memory the result is written to</td></tr>
+ * </tbody>
+ * </table>
+ * @param ctx Reference to context memory
+ * @throws SvcLogicException
+ * @since 11.0.2
+ */
+ public static void replace(Map<String, String> parameters, SvcLogicContext ctx) throws SvcLogicException {
+ SliPluginUtils.checkParameters(parameters,
+ new String[] {INPUT_PARAM_SOURCE, "outputPath", INPUT_PARAM_TARGET, "replacement"}, LOG);
+ ctx.setAttribute(parameters.get("outputPath"), (parameters.get(INPUT_PARAM_SOURCE)
+ .replace(parameters.get(INPUT_PARAM_TARGET), parameters.get("replacement"))));
+ }
+
+/**
+ * exposes base64decoding algo
+ * writes the length of source to outputPath
+ * @param parameters HashMap<String,String> of parameters passed by the DG to this function
+ * <table border="1">
+ * <thead><th>parameter</th><th>Mandatory/Optional</th><th>description</th></thead>
+ * <tbody>
+ * <tr><td>encodedValue</td><td>Mandatory</td><td>source string</td></tr>
+ * <tr><td>decodedValue</td><td>Mandatory</td><td>Destination path</td></tr>
+ * </tbody>
+ * </table>
+ * @param ctx Reference to context memory
+ * @throws SvcLogicException
+ * @since 11.0.2
+ */
+ public static void base64DecodingAlgo(Map<String, String> parameters, SvcLogicContext ctx) throws SvcLogicException{
+ try {
+ SliPluginUtils.checkParameters(parameters, new String[]{"encodedValue","decodedValue"}, LOG);
+
+ Base64.Decoder decoder = Base64.getDecoder();
+ byte[] decodedByteArray = decoder.decode(parameters.get("encodedValue"));
+ //Verify the decoded string
+ String decodeVal = new String(decodedByteArray);
+ ctx.setAttribute(parameters.get("decodedValue"), decodeVal);
+ }catch (Exception exc){
+ LOG.error("Exception occure "+exc.getMessage());
+ throw new SvcLogicException(exc.getMessage());
+ }
+ }
+
+
+ /**
+ * exposes replaceAll to directed graph
+ * writes the length of source to outputPath
+ * @param parameters HashMap<String,String> of parameters passed by the DG to this function
+ * <table border="1">
+ * <thead><th>parameter</th><th>Mandatory/Optional</th><th>description</th></thead>
+ * <tbody>
+ * <tr><td>source</td><td>Mandatory</td><td>source string</td></tr>
+ * <tr><td>target</td><td>Mandatory</td><td>This should be a valid regular expression</td></tr>
+ * <tr><td>replacement</td><td>Mandatory</td><td>The replacement sequence of char values</td></tr>
+ * <tr><td>outputPath</td><td>Mandatory</td><td>the location in context memory the result is written to</td></tr>
+ * </tbody>
+ * </table>
+ * @param ctx Reference to context memory
+ * @throws SvcLogicException
+ * @since 11.0.2
+ */
+ public static void replaceAll(Map<String, String> parameters, SvcLogicContext ctx) throws SvcLogicException {
+ SliPluginUtils.checkParameters(parameters,
+ new String[] {INPUT_PARAM_SOURCE, "outputPath", INPUT_PARAM_TARGET, "replacement"}, LOG);
+ ctx.setAttribute(parameters.get("outputPath"), parameters.get(INPUT_PARAM_SOURCE)
+ .replaceAll(parameters.get(INPUT_PARAM_TARGET), parameters.get("replacement")));
+ }
+
+ /**
+ * Provides substring functionality to Directed Graphs.
+ * <p>
+ * Calls either String.substring(String beginIndex) or
+ * String.substring(String beginInded, String endIndex) if the end-index
+ * is present or not.
+ * @param parameters HashMap<String,String> of parameters passed by the DG to this function
+ * <table border="1">
+ * <thead><th>parameter</th><th>Mandatory/Optional</th><th>description</th></thead>
+ * <tbody>
+ * <tr><td>string</td><td>Mandatory</td><td>String to perform substring on</td></tr>
+ * <tr><td>result</td><td>Mandatory</td><td>Key in context memory to populate the resulting string in</td></tr>
+ * <tr><td>begin-index</td><td>Mandatory</td><td>Beginning index to pass to Java substring function</td></tr>
+ * <tr><td>end-index</td><td>Optional</td><td>Ending index to pass to Java substring function. If not included, String.substring(begin) will be called.</td></tr>
+ * </tbody>
+ * </table>
+ * @param ctx Reference to context memory
+ * @throws SvcLogicException
+ * @since 11.0.2
+ */
+ public void substring( Map<String, String> parameters, SvcLogicContext ctx ) throws SvcLogicException {
+ try {
+ SliPluginUtils.checkParameters( parameters, new String[]{"string","begin-index","result"}, LOG );
+ final String string = parameters.get("string");
+ final String result = parameters.get("result");
+ final String begin = parameters.get("begin-index");
+ final String end = parameters.get("end-index");
+ if( StringUtils.isEmpty(end) ) {
+ ctx.setAttribute( result, string.substring(Integer.parseInt(begin)) );
+ }
+ else {
+ ctx.setAttribute( result, string.substring(Integer.parseInt(begin), Integer.parseInt(end)) );
+ }
+ }
+ catch( Exception e ) {
+ throw new SvcLogicException( "An error occurred while the Directed Graph was performing a substring", e );
+ }
+ }
+
+ /**
+ * Provides concat functionality to Directed Graphs.
+ * <p>
+ * Will concat target to source and write the result to outputPath
+ * @param parameters HashMap<String,String> of parameters passed by the DG to this function
+ * <table border="1">
+ * <thead><th>parameter</th><th>Mandatory/Optional</th><th>description</th></thead>
+ * <tbody>
+ * <tr><td>source</td><td>Mandatory</td><td>source string</td></tr>
+ * <tr><td>target</td><td>Mandatory</td><td>The sequence of char values to be replaced</td></tr>
+ * <tr><td>outputPath</td><td>Mandatory</td><td>the location in context memory the result is written to</td></tr>
+ * </tbody>
+ * </table>
+ * @param ctx Reference to context memory
+ * @throws SvcLogicException
+ * @since 11.0.2
+ */
+ public static void concat( Map<String, String> parameters, SvcLogicContext ctx ) throws SvcLogicException {
+ SliPluginUtils.checkParameters(parameters, new String[] {INPUT_PARAM_SOURCE, INPUT_PARAM_TARGET, "outputPath"},
+ LOG);
+ String result = parameters.get(INPUT_PARAM_SOURCE).concat(parameters.get(INPUT_PARAM_TARGET));
+ ctx.setAttribute(parameters.get("outputPath"), result);
+ }
+
+ /**
+ * Provides url encoding functionality to Directed Graphs.
+ * <p>
+ * Will url encode the source and write the result to outputPath
+ * @param parameters HashMap<String,String> of parameters passed by the DG to this function
+ * <table border="1">
+ * <thead><th>parameter</th><th>Mandatory/Optional</th><th>description</th></thead>
+ * <tbody>
+ * <tr><td>source</td><td>Mandatory</td><td>source string</td></tr>
+ * <tr><td>encoding</td><td>Optional</td><td>the name of a supported character encoding, defaulted to UTF-8 if not supplied</td></tr>
+ * <tr><td>outputPath</td><td>Mandatory</td><td>the location in context memory the result is written to</td></tr>
+ * </tbody>
+ * </table>
+ * @param ctx Reference to context memory
+ * @throws SvcLogicException
+ */
+ public static void urlEncode(Map<String, String> parameters, SvcLogicContext ctx) throws SvcLogicException {
+ SliPluginUtils.checkParameters(parameters, new String[] { INPUT_PARAM_SOURCE, "outputPath" }, LOG);
+ String encoding = parameters.get("encoding");
+ if (encoding == null) {
+ encoding = "UTF-8";
+ }
+ try {
+ String result = URLEncoder.encode(parameters.get(INPUT_PARAM_SOURCE), encoding);
+ ctx.setAttribute(parameters.get("outputPath"), result);
+ } catch (UnsupportedEncodingException e) {
+ throw new SvcLogicException("Url encode failed.", e);
+ }
+ }
+
+ public static void urlDecode(Map<String, String> parameters, SvcLogicContext ctx) throws SvcLogicException {
+ SliPluginUtils.checkParameters(parameters, new String[] {INPUT_PARAM_SOURCE, "outputPath"}, LOG);
+ String encoding = parameters.get("encoding");
+ if (encoding == null) {
+ encoding = "UTF-8";
+ }
+ try {
+ String result = URLDecoder.decode(parameters.get(INPUT_PARAM_SOURCE), encoding);
+ ctx.setAttribute(parameters.get("outputPath"), result);
+ } catch (UnsupportedEncodingException e) {
+ throw new SvcLogicException("Url decode failed.", e);
+ }
+ }
+
+ /**
+ * xmlEscapeText() will be used to format input xml with text.
+ *
+ * @param inParams
+ * accepts the instance of {@link Map} holds the input xml in string
+ * format.
+ * @param ctx
+ * accepts the instance of {@link SvcLogicContext} holds the service
+ * logic context.
+ *
+ */
+ public static void xmlEscapeText(Map<String, String> inParams, SvcLogicContext ctx) {
+ String source = inParams.get(INPUT_PARAM_SOURCE);
+ String target = inParams.get(INPUT_PARAM_TARGET);
+ source = StringEscapeUtils.escapeXml10(source);
+ ctx.setAttribute(target, source);
+ }
+
+ /**
+ * unescapeJsonString takes an escaped json string stored as a single property in context memory and unescapes it storing it as a single property
+ * @param parameters - requires source and outputPath to not be null.
+ * @param ctx Reference to context memory
+ * @throws SvcLogicException if a required parameter is missing an exception is thrown
+ */
+ public static void unescapeJsonString(Map<String, String> parameters, SvcLogicContext ctx) throws SvcLogicException {
+ SliPluginUtils.checkParameters(parameters, new String[] { INPUT_PARAM_SOURCE, INPUT_PARAM_TARGET }, LOG);
+ try {
+ String source = parameters.get(INPUT_PARAM_SOURCE);
+ String target = parameters.get(INPUT_PARAM_TARGET);
+ String unescapedJson = StringEscapeUtils.unescapeJson(source);
+ ctx.setAttribute(target, unescapedJson);
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ throw new SvcLogicException("problem with unescapeJsonString", ex);
+ }
+ }
+
+ /**
+ * escapeJsonString takes json stored as a single string in context memory and escapes it storing it as a single property
+ * @param parameters - requires source and outputPath to not be null.
+ * @param ctx Reference to context memory
+ * @throws SvcLogicException if a required parameter is missing an exception is thrown
+ */
+ public static void escapeJsonString(Map<String, String> parameters, SvcLogicContext ctx) throws SvcLogicException {
+ SliPluginUtils.checkParameters(parameters, new String[] { INPUT_PARAM_SOURCE, INPUT_PARAM_TARGET }, LOG);
+ try {
+ String source = parameters.get(INPUT_PARAM_SOURCE);
+ String target = parameters.get(INPUT_PARAM_TARGET);
+ String unescapedJson = StringEscapeUtils.escapeJson(source);
+ ctx.setAttribute(target, unescapedJson);
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ throw new SvcLogicException("problem with escapeJsonString", ex);
+ }
+ }
+
+ public static String isBlank(Map<String, String> parameters, SvcLogicContext ctx) throws SvcLogicException {
+ String ctxLocation = parameters.get(INPUT_PARAM_KEY);
+ String str = ctx.getAttribute(ctxLocation);
+ if (str == null || str.isEmpty() || " ".equals(str)) {
+ return TRUE_CONSTANT;
+ }
+ return FALSE_CONSTANT;
+ }
+
+ public static String isEmpty(Map<String, String> parameters, SvcLogicContext ctx) throws SvcLogicException {
+ String ctxLocation = parameters.get(INPUT_PARAM_KEY);
+ String str = ctx.getAttribute(ctxLocation);
+ if (str == null || str.isEmpty()) {
+ return TRUE_CONSTANT;
+ }
+ return FALSE_CONSTANT;
+ }
+
+ public static String isNull(Map<String, String> parameters, SvcLogicContext ctx) throws SvcLogicException {
+ String ctxLocation = parameters.get(INPUT_PARAM_KEY);
+ String str = ctx.getAttribute(ctxLocation);
+ if (str == null) {
+ return TRUE_CONSTANT;
+ }
+ return FALSE_CONSTANT;
+ }
+}
diff --git a/core/sliPluginUtils/provider/src/main/java/org/onap/ccsdk/sli/core/slipluginutils/SvcLogicContextList.java b/core/sliPluginUtils/provider/src/main/java/org/onap/ccsdk/sli/core/slipluginutils/SvcLogicContextList.java
new file mode 100644
index 000000000..32e1aebdc
--- /dev/null
+++ b/core/sliPluginUtils/provider/src/main/java/org/onap/ccsdk/sli/core/slipluginutils/SvcLogicContextList.java
@@ -0,0 +1,210 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.slipluginutils;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.ListIterator;
+import java.util.Map;
+
+import org.apache.commons.lang3.StringUtils;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+
+/**
+ * A utility class used to manage list manipulation in the context memory.
+ * @see org.onap.ccsdk.sli.core.sli.SvcLogicContext
+ */
+public class SvcLogicContextList {
+ /**
+ * Internal flag indicating if list should be deleted from context memory
+ * when it is copied into the SvcLogicContextList object.
+ */
+ private enum OperType {
+ COPY, EXTRACT
+ }
+
+ // TODO: javadoc
+ protected final String prefix;
+ // TODO: javadoc
+ protected final ArrayList<HashMap<String,String>> list;
+
+
+ // TODO: javadoc
+ public SvcLogicContextList( SvcLogicContext ctx, String list_prefix ) {
+ this(ctx, list_prefix, OperType.COPY);
+ }
+
+ // TODO: javadoc
+ private SvcLogicContextList( SvcLogicContext ctx, String list_prefix, OperType operation ) {
+ this.prefix = list_prefix;
+
+ // Initialize list
+ int capacity = getCtxListLength(ctx, prefix);
+ this.list = new ArrayList<>(capacity);
+ for( int i = 0; i < capacity; i++ ) {
+ this.list.add(i, new HashMap<String,String>());
+ }
+
+ // Populate "elements" in list
+ String prefix_bracket = this.prefix + '[';
+ for (String key : new HashSet<String>(ctx.getAttributeKeySet())) {
+ if( key.startsWith(prefix_bracket) ) {
+ // Extract the index of the list
+ int index = getCtxListIndex(key, this.prefix, capacity);
+
+ // Store the
+ String suffix = key.substring((prefix_bracket + index + ']').length());
+ suffix = suffix.isEmpty() ? suffix : suffix.substring(1);
+ this.list.get(index).put( suffix, ctx.getAttribute(key));
+
+ // If flag to extract set, remove data from context memory as
+ // it is read into this list
+ if( operation == OperType.EXTRACT ) {
+ ctx.setAttribute(key, null);
+ }
+ }
+ }
+
+ // If flag to extract set, remove list _length value from cxt mem
+ if( operation == OperType.EXTRACT ) {
+ ctx.setAttribute(this.prefix + "_length", null);
+ }
+ }
+
+ // TODO: javadoc
+ public static SvcLogicContextList extract( SvcLogicContext ctx, String list_prefix ) {
+ return new SvcLogicContextList(ctx, list_prefix, OperType.EXTRACT);
+ }
+
+
+ // ========== PUBLIC FUNCTIONS ==========
+
+ // TODO: javadoc
+ public HashMap<String,String> get( int index ) {
+ return this.list.get(index);
+ }
+
+ // TODO: javadoc
+ public HashMap<String,String> remove( int index ) {
+ return this.list.remove(index);
+ }
+
+ // TODO: javadoc
+ public void remove( String value ) {
+ remove( "", value );
+ }
+
+ // TODO: javadoc
+ public void remove( String key, String value ) {
+ if( value == null ) {
+ throw new IllegalArgumentException("value cannot be null");
+ }
+
+ ListIterator<HashMap<String,String>> itr = this.list.listIterator();
+ while( itr.hasNext() ) {
+ if( value.equals(itr.next().get(key)) ) {
+ itr.remove();
+ }
+ }
+ }
+
+ // TODO javadoc
+ public void remove( Map<String,String> primary_key ) {
+ ListIterator<HashMap<String,String>> itr = this.list.listIterator();
+ while( itr.hasNext() ) {
+ boolean found = true;
+ HashMap<String,String> list_element = itr.next();
+ for( Map.Entry<String,String> key : primary_key.entrySet() ) {
+ if( !key.getValue().equals(list_element.get(key.getKey())) ) {
+ found = false;
+ break;
+ }
+ }
+
+ if( found ) {
+ itr.remove();
+ }
+ }
+ }
+
+ // TODO: javadoc
+ public int size() {
+ return list.size();
+ }
+
+ // TODO: javadoc
+ public void writeToContext( SvcLogicContext ctx ) {
+ ctx.setAttribute( prefix + "_length", Integer.toString(this.list.size()) );
+
+ for( int i = 0; i < this.list.size(); i++ ) {
+ for( Map.Entry<String,String> entry : this.list.get(i).entrySet() ) {
+ if("".equals(entry.getKey())) {
+ ctx.setAttribute(prefix + '[' + i + ']', entry.getValue());
+ } else {
+ ctx.setAttribute(prefix + '[' + i + "]." + entry.getKey(), entry.getValue());
+ }
+ }
+ }
+ }
+
+
+
+ // ========== PRIVATE STATIC FUNCTIONS ==========
+
+ // TODO: javadoc
+ private static int getCtxListIndex( String key, String prefix, int list_size ) {
+ int index = getCtxListIndex( key, prefix );
+ if( index >= list_size ) {
+ throw new IllegalArgumentException("Context memory list \"" + prefix + "[]\" contains an index >= the size of the list", new ArrayIndexOutOfBoundsException("index \"" + index + "\" is outside the bounds of the context memory list \"" + prefix + "[]. List Length = " + list_size));
+ } else if (index < 0) {
+ throw new IllegalArgumentException("Context memory list \"" + prefix + "[]\" contains a negative index", new NegativeArraySizeException("index \"" + index + "\" of context memory list is negative"));
+ }
+
+ return index;
+ }
+
+ // TODO: javadoc
+ private static int getCtxListIndex( String key, String prefix ) {
+ String ctx_index_str = StringUtils.substringBetween(key.substring(prefix.length()), "[", "]");
+ try {
+ return Integer.parseInt( ctx_index_str );
+ } catch (NumberFormatException e) {
+ throw new IllegalStateException("Could not parse index value \"" + ctx_index_str + "\" in context memory key \"" + key + "\"", e);
+ }
+ }
+
+ // TODO: javadoc
+ private static int getCtxListLength( SvcLogicContext ctx, String prefix ) {
+ String _length_key = prefix + "_length";
+ String _length_val_str = ctx.getAttribute(_length_key);
+ try {
+ return Integer.parseInt(_length_val_str);
+ } catch (NumberFormatException e) {
+ if( _length_val_str == null ) {
+ throw new IllegalStateException( "Could not find list length \"" + _length_key + "\" in context memory." );
+ } else {
+ throw new IllegalStateException( "Could not parse index value \"" + _length_val_str + "\" of context memory list length \"" + _length_key + "\"" , e );
+ }
+ }
+ }
+}
diff --git a/core/sliPluginUtils/provider/src/main/java/org/onap/ccsdk/sli/core/slipluginutils/SvcLogicContextObject.java b/core/sliPluginUtils/provider/src/main/java/org/onap/ccsdk/sli/core/slipluginutils/SvcLogicContextObject.java
new file mode 100644
index 000000000..aa41a5c60
--- /dev/null
+++ b/core/sliPluginUtils/provider/src/main/java/org/onap/ccsdk/sli/core/slipluginutils/SvcLogicContextObject.java
@@ -0,0 +1,28 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.slipluginutils;
+
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+
+public interface SvcLogicContextObject {
+ void writeToContext(SvcLogicContext ctx, String root );
+}
diff --git a/core/sliPluginUtils/provider/src/main/java/org/onap/ccsdk/sli/core/slipluginutils/commondatastructures/YesNo.java b/core/sliPluginUtils/provider/src/main/java/org/onap/ccsdk/sli/core/slipluginutils/commondatastructures/YesNo.java
new file mode 100644
index 000000000..5db752e29
--- /dev/null
+++ b/core/sliPluginUtils/provider/src/main/java/org/onap/ccsdk/sli/core/slipluginutils/commondatastructures/YesNo.java
@@ -0,0 +1,51 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+/**
+ *
+ */
+package org.onap.ccsdk.sli.core.slipluginutils.commondatastructures;
+
+/**
+ * An enum found in many Yang models. It is commonly used as a
+ * substitute for boolean.
+ */
+public enum YesNo {
+ N, Y;
+
+ /**
+ * Method overload for {@link #valueOf(String)} for the char primative
+ */
+ public static YesNo valueOf( final char name ) {
+ return YesNo.valueOf( Character.toString(name) );
+ }
+
+ /**
+ * Method overload for {@link #valueOf(String)} for the Character object
+ */
+ public static YesNo valueOf( final Character name ) {
+ if( name == null ) {
+ return null;
+ }
+
+ return YesNo.valueOf( name.toString() );
+ }
+}
diff --git a/core/sliPluginUtils/provider/src/main/java/org/onap/ccsdk/sli/core/slipluginutils/commondatastructures/package-info.java b/core/sliPluginUtils/provider/src/main/java/org/onap/ccsdk/sli/core/slipluginutils/commondatastructures/package-info.java
new file mode 100644
index 000000000..2aa949b03
--- /dev/null
+++ b/core/sliPluginUtils/provider/src/main/java/org/onap/ccsdk/sli/core/slipluginutils/commondatastructures/package-info.java
@@ -0,0 +1,28 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+/**
+ *
+ */
+/**
+ *
+ */
+package org.onap.ccsdk.sli.core.slipluginutils.commondatastructures;
diff --git a/core/sliPluginUtils/provider/src/main/resources/OSGI-INF/blueprint/slipluginutils-blueprint.xml b/core/sliPluginUtils/provider/src/main/resources/OSGI-INF/blueprint/slipluginutils-blueprint.xml
new file mode 100644
index 000000000..534b92c93
--- /dev/null
+++ b/core/sliPluginUtils/provider/src/main/resources/OSGI-INF/blueprint/slipluginutils-blueprint.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+ xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0"
+ odl:use-default-for-reference-types="true">
+
+ <bean id="sliPluginUtils" class="org.onap.ccsdk.sli.core.slipluginutils.SliPluginUtils" />
+ <service ref="sliPluginUtils"
+ interface="org.onap.ccsdk.sli.core.slipluginutils.SliPluginUtils" />
+
+ <bean id="sliStringUtils" class="org.onap.ccsdk.sli.core.slipluginutils.SliStringUtils" />
+ <service ref="sliStringUtils"
+ interface="org.onap.ccsdk.sli.core.slipluginutils.SliStringUtils" />
+</blueprint>
diff --git a/core/sliPluginUtils/provider/src/main/resources/org/opendaylight/blueprint/slipluginutils-blueprint.xml b/core/sliPluginUtils/provider/src/main/resources/org/opendaylight/blueprint/slipluginutils-blueprint.xml
new file mode 100644
index 000000000..534b92c93
--- /dev/null
+++ b/core/sliPluginUtils/provider/src/main/resources/org/opendaylight/blueprint/slipluginutils-blueprint.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+ xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0"
+ odl:use-default-for-reference-types="true">
+
+ <bean id="sliPluginUtils" class="org.onap.ccsdk.sli.core.slipluginutils.SliPluginUtils" />
+ <service ref="sliPluginUtils"
+ interface="org.onap.ccsdk.sli.core.slipluginutils.SliPluginUtils" />
+
+ <bean id="sliStringUtils" class="org.onap.ccsdk.sli.core.slipluginutils.SliStringUtils" />
+ <service ref="sliStringUtils"
+ interface="org.onap.ccsdk.sli.core.slipluginutils.SliStringUtils" />
+</blueprint>
diff --git a/core/sliPluginUtils/provider/src/test/java/org/onap/ccsdk/sli/core/slipluginutils/SliPluginUtils_StaticFunctionsTest.java b/core/sliPluginUtils/provider/src/test/java/org/onap/ccsdk/sli/core/slipluginutils/SliPluginUtils_StaticFunctionsTest.java
new file mode 100644
index 000000000..42e7ceb94
--- /dev/null
+++ b/core/sliPluginUtils/provider/src/test/java/org/onap/ccsdk/sli/core/slipluginutils/SliPluginUtils_StaticFunctionsTest.java
@@ -0,0 +1,591 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.slipluginutils;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.HashMap;
+import java.util.Map;
+import org.junit.Before;
+import org.junit.Test;
+import org.onap.ccsdk.sli.core.sli.SvcLogicConstants;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.core.slipluginutils.SliPluginUtils.LogLevel;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import com.google.gson.JsonObject;
+
+public class SliPluginUtils_StaticFunctionsTest {
+ private static final Logger LOG = LoggerFactory.getLogger(SliPluginUtils_StaticFunctionsTest.class);
+ SliPluginUtils utils = new SliPluginUtils();
+ private SvcLogicContext ctx;
+ private HashMap<String, String> parameters;
+
+ @Before
+ public void setUp() throws Exception {
+ this.ctx = new SvcLogicContext();
+ parameters = new HashMap<String, String>();
+ }
+
+ // TODO: javadoc
+ @Test
+ public final void testCtxGetBeginsWith() {
+ ctx.setAttribute("service-data.oper-status.order-status", "InProgress");
+ ctx.setAttribute("service-data.service-information.service-instance-id", "my-instance");
+ ctx.setAttribute("service-data.service-information.service-type", "my-service");
+
+ Map<String, String> entries = SliPluginUtils.ctxGetBeginsWith(ctx, "service-data.service-information");
+
+ assertEquals("my-instance", entries.get("service-data.service-information.service-instance-id"));
+ assertEquals("my-service", entries.get("service-data.service-information.service-type"));
+ assertFalse(entries.containsKey("service-data.oper-status.order-status"));
+ }
+
+ // TODO: javadoc
+ @Test
+ public final void testCtxListRemove_index() throws SvcLogicException {
+ LOG.trace("=== testCtxListRemove_index ===");
+ ctx.setAttribute("service-data.vnf-l3[0].vnf-host-name", "vnf-host-name_0");
+ ctx.setAttribute("service-data.vnf-l3[0].device-host-name", "device-host-name_0");
+ ctx.setAttribute("service-data.vnf-l3[1].vnf-host-name", "vnf-host-name_1");
+ ctx.setAttribute("service-data.vnf-l3[1].device-host-name", "device-host-name_1");
+ ctx.setAttribute("service-data.vnf-l3[2].vnf-host-name", "vnf-host-name_2");
+ ctx.setAttribute("service-data.vnf-l3[2].device-host-name", "device-host-name_2");
+ ctx.setAttribute("service-data.vnf-l3_length", "3");
+
+ parameters.put("index", "1");
+ parameters.put("list_pfx", "service-data.vnf-l3");
+
+ utils.ctxListRemove(parameters, ctx);
+ SliPluginUtils.logContextMemory(ctx, LOG, SliPluginUtils.LogLevel.TRACE);
+
+ assertEquals("2", ctx.getAttribute("service-data.vnf-l3_length"));
+ assertEquals("vnf-host-name_0", ctx.getAttribute("service-data.vnf-l3[0].vnf-host-name"));
+ assertEquals("device-host-name_0", ctx.getAttribute("service-data.vnf-l3[0].device-host-name"));
+ assertEquals("vnf-host-name_2", ctx.getAttribute("service-data.vnf-l3[1].vnf-host-name"));
+ assertEquals("device-host-name_2", ctx.getAttribute("service-data.vnf-l3[1].device-host-name"));
+ }
+
+ // TODO: javadoc
+ @Test
+ public final void textCtxListRemove_keyValue() throws SvcLogicException {
+ LOG.trace("=== textCtxListRemove_keyValue ===");
+ ctx.setAttribute("service-data.vnf-l3[0].vnf-host-name", "vnf-host-name_0");
+ ctx.setAttribute("service-data.vnf-l3[0].device-host-name", "device-host-name_0");
+ ctx.setAttribute("service-data.vnf-l3[1].vnf-host-name", "vnf-host-name_1");
+ ctx.setAttribute("service-data.vnf-l3[1].device-host-name", "device-host-name_1");
+ ctx.setAttribute("service-data.vnf-l3[2].vnf-host-name", "vnf-host-name_2");
+ ctx.setAttribute("service-data.vnf-l3[2].device-host-name", "device-host-name_2");
+ // 2nd entry
+ ctx.setAttribute("service-data.vnf-l3[3].vnf-host-name", "vnf-host-name_1");
+ ctx.setAttribute("service-data.vnf-l3[3].device-host-name", "device-host-name_1");
+ ctx.setAttribute("service-data.vnf-l3_length", "4");
+
+ parameters.put("list_pfx", "service-data.vnf-l3");
+ parameters.put("key", "vnf-host-name");
+ parameters.put("value", "vnf-host-name_1");
+
+ utils.ctxListRemove(parameters, ctx);
+ SliPluginUtils.logContextMemory(ctx, LOG, SliPluginUtils.LogLevel.TRACE);
+
+ assertEquals("2", ctx.getAttribute("service-data.vnf-l3_length"));
+ assertEquals("vnf-host-name_0", ctx.getAttribute("service-data.vnf-l3[0].vnf-host-name"));
+ assertEquals("device-host-name_0", ctx.getAttribute("service-data.vnf-l3[0].device-host-name"));
+ assertEquals("vnf-host-name_2", ctx.getAttribute("service-data.vnf-l3[1].vnf-host-name"));
+ assertEquals("device-host-name_2", ctx.getAttribute("service-data.vnf-l3[1].device-host-name"));
+ }
+
+ // TODO: javadoc
+ @Test
+ public final void textCtxListRemove_keyValue_nullkey() throws SvcLogicException {
+ LOG.trace("=== textCtxListRemove_keyValue_nullkey ===");
+ ctx.setAttribute("service-data.vnf-l3[0]", "vnf-host-name_0");
+ ctx.setAttribute("service-data.vnf-l3[1]", "vnf-host-name_1");
+ ctx.setAttribute("service-data.vnf-l3[2]", "vnf-host-name_2");
+ ctx.setAttribute("service-data.vnf-l3_length", "3");
+
+ parameters.put("list_pfx", "service-data.vnf-l3");
+ parameters.put("value", "vnf-host-name_1");
+
+ utils.ctxListRemove(parameters, ctx);
+ SliPluginUtils.logContextMemory(ctx, LOG, SliPluginUtils.LogLevel.TRACE);
+
+ assertEquals("2", ctx.getAttribute("service-data.vnf-l3_length"));
+ assertEquals("vnf-host-name_0", ctx.getAttribute("service-data.vnf-l3[0]"));
+ assertEquals("vnf-host-name_2", ctx.getAttribute("service-data.vnf-l3[1]"));
+ }
+
+ // TODO: javadoc
+ @Test
+ public final void textCtxListRemove_keyValueList() throws SvcLogicException {
+ LOG.trace("=== textCtxListRemove_keyValueList ===");
+ ctx.setAttribute("service-data.vnf-l3[0].vnf-host-name", "vnf-host-name_0");
+ ctx.setAttribute("service-data.vnf-l3[0].device-host-name", "device-host-name_0");
+ ctx.setAttribute("service-data.vnf-l3[1].vnf-host-name", "vnf-host-name_1");
+ ctx.setAttribute("service-data.vnf-l3[1].device-host-name", "device-host-name_1");
+ ctx.setAttribute("service-data.vnf-l3[2].vnf-host-name", "vnf-host-name_2");
+ ctx.setAttribute("service-data.vnf-l3[2].device-host-name", "device-host-name_2");
+ // 2nd entry
+ ctx.setAttribute("service-data.vnf-l3[3].vnf-host-name", "vnf-host-name_1");
+ ctx.setAttribute("service-data.vnf-l3[3].device-host-name", "device-host-name_1");
+ // entries with only 1 of 2 key-value pairs matching
+ ctx.setAttribute("service-data.vnf-l3[4].vnf-host-name", "vnf-host-name_1");
+ ctx.setAttribute("service-data.vnf-l3[4].device-host-name", "device-host-name_4");
+ ctx.setAttribute("service-data.vnf-l3[5].vnf-host-name", "vnf-host-name_5");
+ ctx.setAttribute("service-data.vnf-l3[5].device-host-name", "device-host-name_1");
+ ctx.setAttribute("service-data.vnf-l3_length", "6");
+
+ parameters.put("list_pfx", "service-data.vnf-l3");
+ parameters.put("keys_length", "2");
+ parameters.put("keys[0].key", "vnf-host-name");
+ parameters.put("keys[0].value", "vnf-host-name_1");
+ parameters.put("keys[1].key", "device-host-name");
+ parameters.put("keys[1].value", "device-host-name_1");
+
+ utils.ctxListRemove(parameters, ctx);
+ SliPluginUtils.logContextMemory(ctx, LOG, SliPluginUtils.LogLevel.TRACE);
+
+ assertEquals("4", ctx.getAttribute("service-data.vnf-l3_length"));
+ assertEquals("vnf-host-name_0", ctx.getAttribute("service-data.vnf-l3[0].vnf-host-name"));
+ assertEquals("device-host-name_0", ctx.getAttribute("service-data.vnf-l3[0].device-host-name"));
+ assertEquals("vnf-host-name_2", ctx.getAttribute("service-data.vnf-l3[1].vnf-host-name"));
+ assertEquals("device-host-name_2", ctx.getAttribute("service-data.vnf-l3[1].device-host-name"));
+ assertEquals("vnf-host-name_1", ctx.getAttribute("service-data.vnf-l3[2].vnf-host-name"));
+ assertEquals("device-host-name_4", ctx.getAttribute("service-data.vnf-l3[2].device-host-name"));
+ assertEquals("vnf-host-name_5", ctx.getAttribute("service-data.vnf-l3[3].vnf-host-name"));
+ assertEquals("device-host-name_1", ctx.getAttribute("service-data.vnf-l3[3].device-host-name"));
+ }
+
+ // TODO: javadoc
+ @Test(expected = SvcLogicException.class)
+ public final void testCtxListRemove_nullListLength() throws SvcLogicException {
+ LOG.trace("=== testCtxListRemove_nullListLength ===");
+ ctx.setAttribute("service-data.vnf-l3[0].vnf-host-name", "vnf-host-name_0");
+ ctx.setAttribute("service-data.vnf-l3[0].device-host-name", "device-host-name_0");
+ ctx.setAttribute("service-data.vnf-l3[1].vnf-host-name", "vnf-host-name_1");
+ ctx.setAttribute("service-data.vnf-l3[1].device-host-name", "device-host-name_1");
+ ctx.setAttribute("service-data.vnf-l3[2].vnf-host-name", "vnf-host-name_2");
+ ctx.setAttribute("service-data.vnf-l3[2].device-host-name", "device-host-name_2");
+
+ parameters.put("index", "1");
+ parameters.put("list_pfx", "service-data.vnf-l3");
+
+ utils.ctxListRemove(parameters, ctx);
+ }
+
+ // TODO: javadoc
+ @Test
+ public final void testCtxPutAll() {
+ HashMap<String, Object> entries = new HashMap<String, Object>();
+ entries.put("service-data.oper-status.order-status", "InProgress");
+ entries.put("service-data.service-information.service-instance-id", "my-instance");
+ entries.put("service-data.request-information.order-number", 1234);
+ entries.put("service-data.request-information.request-id", null);
+
+ SliPluginUtils.ctxPutAll(ctx, entries);
+
+ assertEquals("InProgress", ctx.getAttribute("service-data.oper-status.order-status"));
+ assertEquals("my-instance", ctx.getAttribute("service-data.service-information.service-instance-id"));
+ assertEquals("1234", ctx.getAttribute("service-data.request-information.order-number"));
+ assertFalse(ctx.getAttributeKeySet().contains("service-data.request-information.request-id"));
+ }
+
+ // TODO: javadoc
+ @Test
+ public final void testCtxSetAttribute_LOG() {
+ LOG.debug("=== testCtxSetAttribute_LOG ===");
+ Integer i = new Integer(3);
+ SliPluginUtils.ctxSetAttribute(ctx, "test", i, LOG, SliPluginUtils.LogLevel.TRACE);
+ }
+
+ @Test
+ public void setTime() throws SvcLogicException {
+ String outputPath = "output";
+ parameters.put("outputPath", outputPath);
+ SliPluginUtils.setTime(parameters, ctx);
+ assertNotNull(ctx.getAttribute(outputPath));
+ }
+
+ @Test
+ public void containsKey() throws Exception {
+ ctx = new SvcLogicContext();
+ parameters.put(SliStringUtils.INPUT_PARAM_KEY, "key_does_not_exist");
+ String result = SliPluginUtils.containsKey(parameters, ctx);
+ assertEquals(SliStringUtils.FALSE_CONSTANT, result);
+
+ ctx.setAttribute("a", null);
+ parameters.put(SliStringUtils.INPUT_PARAM_KEY, "a");
+ result = SliPluginUtils.containsKey(parameters, ctx);
+ assertEquals(SliStringUtils.FALSE_CONSTANT, result);
+
+ ctx.setAttribute("a", "hellworld");
+ parameters.put(SliStringUtils.INPUT_PARAM_KEY, "a");
+ result = SliPluginUtils.containsKey(parameters, ctx);
+ assertEquals(SliStringUtils.TRUE_CONSTANT, result);
+ }
+
+ @Test
+ public void testGetAttributeValue() throws Exception {
+ parameters.put("outputPath", "testPath");
+ parameters.put("source", "testSource");
+ SliPluginUtils.getAttributeValue(parameters, ctx);
+ assertNull(ctx.getAttribute(parameters.get("outputPath")));
+ }
+
+ @Test
+ public void testCtxListContains() throws Exception {
+ parameters.put("list", "10_length");
+ parameters.put("keyName", "testName");
+ parameters.put("keyValue", "testValue");
+ ctx.setAttribute("10_length", "10");
+ assertEquals("false", SliPluginUtils.ctxListContains(parameters, ctx));
+
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void testPrintContextForEmptyParameters() throws SvcLogicException {
+ SliPluginUtils.printContext(parameters, ctx);
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void testPrintContextForNullParameters() throws SvcLogicException {
+ SliPluginUtils.printContext(null, ctx);
+ }
+
+ @Test
+ public void testPrintContext() throws SvcLogicException {
+ parameters.put("filename", "testFileName");
+ SliPluginUtils.printContext(parameters, ctx);
+ }
+
+ @Test
+ public void testCtxKeyEmpty() {
+ ctx.setAttribute("key", "");
+ assertTrue(SliPluginUtils.ctxKeyEmpty(ctx, "key"));
+ }
+
+ @Test
+ public void testGetArrayLength() {
+ ctx.setAttribute("key_length", "test");
+ Logger log = LoggerFactory.getLogger(getClass());
+ SliPluginUtils.getArrayLength(ctx, "key", log, LogLevel.INFO, "invalid input");
+ }
+
+ @Test
+ public void testSetPropertiesForRoot() {
+ Map<String, String> parameters = new HashMap<>();
+ parameters.put("root", "RootVal");
+ parameters.put("valueRoot", "ValueRootVal");
+ assertEquals(SvcLogicConstants.SUCCESS, SliPluginUtils.setPropertiesForRoot(parameters, ctx));
+ }
+
+ @Test
+ public void testJsonStringToCtxToplevelArray() throws Exception {
+ String path = "src/test/resources/ArrayMenu.json";
+ String content = new String(Files.readAllBytes(Paths.get(path)));
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute("input", content);
+ Map<String, String> parameters = new HashMap<String, String>();
+ parameters.put("outputPath", "testPath");
+ parameters.put("isEscaped", "false");
+ parameters.put("source", "input");
+
+ SliPluginUtils.jsonStringToCtx(parameters, ctx);
+
+ assertEquals("1000", ctx.getAttribute("testPath.[0].calories"));
+ assertEquals("1", ctx.getAttribute("testPath.[0].id"));
+ assertEquals("plain", ctx.getAttribute("testPath.[0].name"));
+ assertEquals("pizza", ctx.getAttribute("testPath.[0].type"));
+ assertEquals("true", ctx.getAttribute("testPath.[0].vegetarian"));
+ assertEquals(SliPluginUtils.CTX_NULL_VALUE, ctx.getAttribute("testPath.[1].calories"));
+ assertEquals("2", ctx.getAttribute("testPath.[1].id"));
+ assertEquals("Tuesday Special", ctx.getAttribute("testPath.[1].name"));
+ assertEquals("1", ctx.getAttribute("testPath.[1].topping[0].id"));
+ assertEquals("onion", ctx.getAttribute("testPath.[1].topping[0].name"));
+ assertEquals("2", ctx.getAttribute("testPath.[1].topping[1].id"));
+ assertEquals("pepperoni", ctx.getAttribute("testPath.[1].topping[1].name"));
+ assertEquals("2", ctx.getAttribute("testPath.[1].topping_length"));
+ assertEquals("pizza", ctx.getAttribute("testPath.[1].type"));
+ assertEquals("false", ctx.getAttribute("testPath.[1].vegetarian"));
+ assertEquals("1500", ctx.getAttribute("testPath.[2].calories"));
+ assertEquals("3", ctx.getAttribute("testPath.[2].id"));
+ assertEquals("House Special", ctx.getAttribute("testPath.[2].name"));
+ assertEquals("3", ctx.getAttribute("testPath.[2].topping[0].id"));
+ assertEquals("basil", ctx.getAttribute("testPath.[2].topping[0].name"));
+ assertEquals("4", ctx.getAttribute("testPath.[2].topping[1].id"));
+ assertEquals("fresh mozzarella", ctx.getAttribute("testPath.[2].topping[1].name"));
+ assertEquals("5", ctx.getAttribute("testPath.[2].topping[2].id"));
+ assertEquals("tomato", ctx.getAttribute("testPath.[2].topping[2].name"));
+ assertEquals("3", ctx.getAttribute("testPath.[2].topping_length"));
+ assertEquals("pizza", ctx.getAttribute("testPath.[2].type"));
+ assertEquals("true", ctx.getAttribute("testPath.[2].vegetarian"));
+ assertEquals("3", ctx.getAttribute("testPath._length"));
+ }
+
+ @Test
+ public void testJsonStringToCtx() throws Exception {
+ String path = "src/test/resources/ObjectMenu.json";
+ String content = new String(Files.readAllBytes(Paths.get(path)));
+
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute("input", content);
+
+ Map<String, String> parameters = new HashMap<String, String>();
+ parameters.put("outputPath", "testPath");
+ parameters.put("isEscaped", "false");
+ parameters.put("source", "input");
+
+ SliPluginUtils.jsonStringToCtx(parameters, ctx);
+
+
+ assertEquals("1000", ctx.getAttribute("testPath.menu[0].calories"));
+ assertEquals("1", ctx.getAttribute("testPath.menu[0].id"));
+ assertEquals("plain", ctx.getAttribute("testPath.menu[0].name"));
+ assertEquals("pizza", ctx.getAttribute("testPath.menu[0].type"));
+ assertEquals("true", ctx.getAttribute("testPath.menu[0].vegetarian"));
+ assertEquals("2000", ctx.getAttribute("testPath.menu[1].calories"));
+ assertEquals("2", ctx.getAttribute("testPath.menu[1].id"));
+ assertEquals("Tuesday Special", ctx.getAttribute("testPath.menu[1].name"));
+ assertEquals("1", ctx.getAttribute("testPath.menu[1].topping[0].id"));
+ assertEquals("onion", ctx.getAttribute("testPath.menu[1].topping[0].name"));
+ assertEquals("2", ctx.getAttribute("testPath.menu[1].topping[1].id"));
+ assertEquals("pepperoni", ctx.getAttribute("testPath.menu[1].topping[1].name"));
+ assertEquals("2", ctx.getAttribute("testPath.menu[1].topping_length"));
+ assertEquals("pizza", ctx.getAttribute("testPath.menu[1].type"));
+ assertEquals("false", ctx.getAttribute("testPath.menu[1].vegetarian"));
+ assertEquals("1500", ctx.getAttribute("testPath.menu[2].calories"));
+ assertEquals("3", ctx.getAttribute("testPath.menu[2].id"));
+ assertEquals("House Special", ctx.getAttribute("testPath.menu[2].name"));
+ assertEquals("3", ctx.getAttribute("testPath.menu[2].topping[0].id"));
+ assertEquals("basil", ctx.getAttribute("testPath.menu[2].topping[0].name"));
+ assertEquals("4", ctx.getAttribute("testPath.menu[2].topping[1].id"));
+ assertEquals("fresh mozzarella", ctx.getAttribute("testPath.menu[2].topping[1].name"));
+ assertEquals("5", ctx.getAttribute("testPath.menu[2].topping[2].id"));
+ assertEquals("tomato", ctx.getAttribute("testPath.menu[2].topping[2].name"));
+ assertEquals("3", ctx.getAttribute("testPath.menu[2].topping_length"));
+ assertEquals("pizza", ctx.getAttribute("testPath.menu[2].type"));
+ assertEquals("true", ctx.getAttribute("testPath.menu[2].vegetarian"));
+ assertEquals("3", ctx.getAttribute("testPath.menu_length"));
+ }
+
+ @Test
+ public void test2dJsonStringToCtx() throws Exception {
+ String path = "src/test/resources/2dArray.json";
+ String content = new String(Files.readAllBytes(Paths.get(path)));
+
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute("input", content);
+
+ Map<String, String> parameters = new HashMap<String, String>();
+ parameters.put("outputPath", "testPath");
+ parameters.put("isEscaped", "false");
+ parameters.put("source", "input");
+
+ SliPluginUtils.jsonStringToCtx(parameters, ctx);
+ assertEquals("apple", ctx.getAttribute("testPath.[0][0]"));
+ assertEquals("orange", ctx.getAttribute("testPath.[0][1]"));
+ assertEquals("banana", ctx.getAttribute("testPath.[0][2]"));
+ assertEquals(SliPluginUtils.CTX_NULL_VALUE, ctx.getAttribute("testPath.[0][3]"));
+ assertEquals("4", ctx.getAttribute("testPath.[0]_length"));
+ assertEquals("squash", ctx.getAttribute("testPath.[1][0]"));
+ assertEquals("broccoli", ctx.getAttribute("testPath.[1][1]"));
+ assertEquals("cauliflower", ctx.getAttribute("testPath.[1][2]"));
+ assertEquals("3", ctx.getAttribute("testPath.[1]_length"));
+ assertEquals("2", ctx.getAttribute("testPath._length"));
+ }
+
+ @Test
+ public void test3dJsonStringToCtx() throws Exception {
+ String path = "src/test/resources/3dArray.json";
+ String content = new String(Files.readAllBytes(Paths.get(path)));
+
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute("input", content);
+
+ Map<String, String> parameters = new HashMap<String, String>();
+ parameters.put("outputPath", "testPath");
+ parameters.put("isEscaped", "false");
+ parameters.put("source", "input");
+
+ SliPluginUtils.jsonStringToCtx(parameters, ctx);
+ assertEquals("a", ctx.getAttribute("testPath.[0][0][0]"));
+ assertEquals("b", ctx.getAttribute("testPath.[0][0][1]"));
+ assertEquals("c", ctx.getAttribute("testPath.[0][0][2]"));
+ assertEquals("3", ctx.getAttribute("testPath.[0][0]_length"));
+ assertEquals("d", ctx.getAttribute("testPath.[0][1][0]"));
+ assertEquals("e", ctx.getAttribute("testPath.[0][1][1]"));
+ assertEquals("f", ctx.getAttribute("testPath.[0][1][2]"));
+ assertEquals("3", ctx.getAttribute("testPath.[0][1]_length"));
+ assertEquals("2", ctx.getAttribute("testPath.[0]_length"));
+ assertEquals("x", ctx.getAttribute("testPath.[1][0][0]"));
+ assertEquals("y", ctx.getAttribute("testPath.[1][0][1]"));
+ assertEquals("z", ctx.getAttribute("testPath.[1][0][2]"));
+ assertEquals("3", ctx.getAttribute("testPath.[1][0]_length"));
+ assertEquals("1", ctx.getAttribute("testPath.[1]_length"));
+ assertEquals("2", ctx.getAttribute("testPath._length"));
+ }
+
+ @Test
+ public void testJsonWidgetStringToCtx() throws Exception {
+ String path = "src/test/resources/Widget.json";
+ String content = new String(Files.readAllBytes(Paths.get(path)));
+
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute("input", content);
+
+ Map<String, String> parameters = new HashMap<String, String>();
+ parameters.put("outputPath", "testPath");
+ parameters.put("isEscaped", "false");
+ parameters.put("source", "input");
+
+ SliPluginUtils.jsonStringToCtx(parameters, ctx);
+ assertEquals("false", ctx.getAttribute("testPath.widget.debug"));
+ assertEquals("center", ctx.getAttribute("testPath.widget.image.alignment"));
+ assertEquals("150", ctx.getAttribute("testPath.widget.image.hOffset"));
+ assertEquals("moon", ctx.getAttribute("testPath.widget.image.name"));
+ assertEquals("images/moon.png", ctx.getAttribute("testPath.widget.image.src"));
+ assertEquals("150", ctx.getAttribute("testPath.widget.image.vOffset"));
+ assertEquals("center", ctx.getAttribute("testPath.widget.text.alignment"));
+ assertEquals("Click Me", ctx.getAttribute("testPath.widget.text.data"));
+ assertEquals("350", ctx.getAttribute("testPath.widget.text.hOffset"));
+ assertEquals("text1", ctx.getAttribute("testPath.widget.text.name"));
+ assertEquals("21", ctx.getAttribute("testPath.widget.text.size"));
+ assertEquals("bold", ctx.getAttribute("testPath.widget.text.style"));
+ assertEquals(SliPluginUtils.CTX_NULL_VALUE, ctx.getAttribute("testPath.widget.text.vOffset"));
+ assertEquals("300", ctx.getAttribute("testPath.widget.window.height"));
+ assertEquals("main_window", ctx.getAttribute("testPath.widget.window.name"));
+ assertEquals("ONAP Widget", ctx.getAttribute("testPath.widget.window.title"));
+ assertEquals("200", ctx.getAttribute("testPath.widget.window.width"));
+ }
+
+ @Test
+ public void testUpdateJsonObjectString() throws Exception {
+ String path = "src/test/resources/JsonObject.json";
+ String content = new String(Files.readAllBytes(Paths.get(path)));
+
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute("input", content);
+
+ Map<String, String> parametersUpdateJson = new HashMap<String, String>();
+ parametersUpdateJson.put("source", "input");
+ parametersUpdateJson.put("outputPath", "newJsonString");
+
+ // add key "ccc" and its value
+ parametersUpdateJson.put("add.ccc", "abcxyz");
+
+ // update keys and their values of "aaa" and "c.d"
+ parametersUpdateJson.put("add.aaa", "4567");
+ parametersUpdateJson.put("add.c.d", "defg");
+
+ // delete key "bbb"
+ parametersUpdateJson.put("delete.bbb", "");
+
+ SliPluginUtils.updateJsonObjectString(parametersUpdateJson, ctx);
+
+ Map<String, String> parametersJsonToCtx = new HashMap<String, String>();
+ parametersJsonToCtx.put("source", "newJsonString");
+ parametersJsonToCtx.put("outputPath", "testPath");
+ parametersJsonToCtx.put("isEscaped", "false");
+
+ SliPluginUtils.jsonStringToCtx(parametersJsonToCtx, ctx);
+
+ assertEquals("abcxyz", ctx.getAttribute("testPath.ccc"));
+ assertEquals("4567", ctx.getAttribute("testPath.aaa"));
+ assertEquals("defg", ctx.getAttribute("testPath.c.d"));
+ assertEquals(null, ctx.getAttribute("testPath.bbb"));
+ }
+
+ @Test
+ public void testEmbeddedEscapedJsonJsonStringToCtx() throws Exception {
+ String path = "src/test/resources/EmbeddedEscapedJson.json";
+ String content = new String(Files.readAllBytes(Paths.get(path)));
+
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute("input", content);
+
+ Map<String, String> parameters = new HashMap<String, String>();
+ parameters.put("outputPath", "testPath");
+ parameters.put("isEscaped", "false");
+ parameters.put("source", "input");
+
+ SliPluginUtils.jsonStringToCtx(parameters, ctx);
+
+ assertEquals("escapedJsonObject", ctx.getAttribute("testPath.input.parameters[0].name"));
+ assertEquals("[{\"id\":\"0.2.0.0/16\"},{\"id\":\"ge04::/64\"}]",
+ ctx.getAttribute("testPath.input.parameters[0].value"));
+ assertEquals("Hello/World", ctx.getAttribute("testPath.input.parameters[1].value"));
+ assertEquals("resourceName", ctx.getAttribute("testPath.input.parameters[2].name"));
+ assertEquals("The\t\"Best\"\tName", ctx.getAttribute("testPath.input.parameters[2].value"));
+ assertEquals("3", ctx.getAttribute("testPath.input.parameters_length"));
+
+
+ // Break the embedded json object into properties
+ parameters.put("outputPath", "testPath.input.parameters[0].value");
+ parameters.put("source", "testPath.input.parameters[0].value");
+ SliPluginUtils.jsonStringToCtx(parameters, ctx);
+
+ assertEquals("0.2.0.0/16", ctx.getAttribute("testPath.input.parameters[0].value.[0].id"));
+ assertEquals("ge04::/64", ctx.getAttribute("testPath.input.parameters[0].value.[1].id"));
+ assertEquals("2", ctx.getAttribute("testPath.input.parameters[0].value._length"));
+ }
+
+ @Test
+ public void testEscapedJsonStringToCtx() throws Exception {
+ String path = "src/test/resources/EscapedJson.json";
+ String content = new String(Files.readAllBytes(Paths.get(path)));
+
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute("input", content);
+
+ Map<String, String> parameters = new HashMap<String, String>();
+ parameters.put("outputPath", "testPath");
+ parameters.put("isEscaped", "true"); // set to true because the entire json content has been escaped
+ parameters.put("source", "input");
+
+
+ SliPluginUtils.jsonStringToCtx(parameters, ctx);
+ assertEquals("false", ctx.getAttribute("testPath.widget.debug"));
+ assertEquals("center", ctx.getAttribute("testPath.widget.image.alignment"));
+ assertEquals("150", ctx.getAttribute("testPath.widget.image.hOffset"));
+ assertEquals("moon", ctx.getAttribute("testPath.widget.image.name"));
+ assertEquals("images/moon.png", ctx.getAttribute("testPath.widget.image.src"));
+ assertEquals("150", ctx.getAttribute("testPath.widget.image.vOffset"));
+ assertEquals("center", ctx.getAttribute("testPath.widget.text.alignment"));
+ assertEquals("Click Me", ctx.getAttribute("testPath.widget.text.data"));
+ assertEquals("350", ctx.getAttribute("testPath.widget.text.hOffset"));
+ assertEquals("text1", ctx.getAttribute("testPath.widget.text.name"));
+ assertEquals("21", ctx.getAttribute("testPath.widget.text.size"));
+ assertEquals("bold", ctx.getAttribute("testPath.widget.text.style"));
+ assertEquals("200", ctx.getAttribute("testPath.widget.text.vOffset"));
+ assertEquals("300", ctx.getAttribute("testPath.widget.window.height"));
+ assertEquals("main_window", ctx.getAttribute("testPath.widget.window.name"));
+ assertEquals("ONAP Widget", ctx.getAttribute("testPath.widget.window.title"));
+ assertEquals("200", ctx.getAttribute("testPath.widget.window.width"));
+ }
+
+}
diff --git a/core/sliPluginUtils/provider/src/test/java/org/onap/ccsdk/sli/core/slipluginutils/SliPluginUtils_checkParametersTest.java b/core/sliPluginUtils/provider/src/test/java/org/onap/ccsdk/sli/core/slipluginutils/SliPluginUtils_checkParametersTest.java
new file mode 100644
index 000000000..f92271f7c
--- /dev/null
+++ b/core/sliPluginUtils/provider/src/test/java/org/onap/ccsdk/sli/core/slipluginutils/SliPluginUtils_checkParametersTest.java
@@ -0,0 +1,117 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Modifications Copyright (C) 2018 IBM.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.slipluginutils;
+
+import java.util.HashMap;
+import java.util.Map;
+import org.junit.Test;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class SliPluginUtils_checkParametersTest {
+
+ @Test
+ public void nullRequiredParameters() throws Exception {
+ Map<String, String> parametersMap = new HashMap<String, String>();
+ String[] requiredParams = null;
+ Logger Log = LoggerFactory.getLogger(SliPluginUtils.class);
+ SliPluginUtils.checkParameters(parametersMap, requiredParams, Log);
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void emptyParametersMap() throws Exception {
+ Map<String, String> parametersMap = new HashMap<String, String>();
+ String[] requiredParams = new String[] { "param1", "param2", "param3" };
+ Logger Log = LoggerFactory.getLogger(SliPluginUtils.class);
+ SliPluginUtils.checkParameters(parametersMap, requiredParams, Log);
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void paramNotFound() throws Exception {
+ Map<String, String> parametersMap = new HashMap<String, String>();
+ parametersMap.put("tst", "me");
+ String[] requiredParams = new String[] { "param1", "parm2", "param3" };
+ Logger Log = LoggerFactory.getLogger(SliPluginUtils.class);
+ SliPluginUtils.checkParameters(parametersMap, requiredParams, Log);
+ }
+
+ @Test
+ public void testSunnyRequiredParameters() throws Exception {
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute("param1", "hello");
+ ctx.setAttribute("param2", "world");
+ ctx.setAttribute("param3", "!");
+
+ Map<String, String> parameters = new HashMap<String, String>();
+ parameters.put("param1", "dog");
+ parameters.put("param2", "cat");
+ parameters.put("param3", "fish");
+
+ SliPluginUtils.requiredParameters(parameters, ctx);
+ }
+
+ @Test
+ public void testSunnyRequiredParametersWithPrefix() throws Exception {
+ String prefixValue = "my.unique.path.";
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute(prefixValue + "param1", "hello");
+ ctx.setAttribute(prefixValue + "param2", "world");
+ ctx.setAttribute(prefixValue + "param3", "!");
+
+ Map<String, String> parameters = new HashMap<String, String>();
+ parameters.put("prefix", prefixValue);
+ parameters.put("param1", "dog");
+ parameters.put("param2", "cat");
+ parameters.put("param3", "fish");
+
+ SliPluginUtils.requiredParameters(parameters, ctx);
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void testRainyMissingRequiredParameters() throws Exception {
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute("param1", "hello");
+ ctx.setAttribute("param3", "!");
+
+ Map<String, String> parameters = new HashMap<String, String>();
+ parameters.put("param1", null);
+ parameters.put("param2", null);
+ parameters.put("param3", null);
+
+ SliPluginUtils.requiredParameters(parameters, ctx);
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void testEmptyRequiredParameters() throws Exception {
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute("param1", "hello");
+ ctx.setAttribute("param3", "!");
+
+ Map<String, String> parameters = new HashMap<String, String>();
+
+ SliPluginUtils.requiredParameters(parameters, ctx);
+ }
+}
diff --git a/core/sliPluginUtils/provider/src/test/java/org/onap/ccsdk/sli/core/slipluginutils/SliPluginUtils_ctxSortList.java b/core/sliPluginUtils/provider/src/test/java/org/onap/ccsdk/sli/core/slipluginutils/SliPluginUtils_ctxSortList.java
new file mode 100644
index 000000000..3d4469bf2
--- /dev/null
+++ b/core/sliPluginUtils/provider/src/test/java/org/onap/ccsdk/sli/core/slipluginutils/SliPluginUtils_ctxSortList.java
@@ -0,0 +1,149 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Modifications Copyright (C) 2018 IBM.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.slipluginutils;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import java.util.HashMap;
+import java.util.Random;
+import org.junit.Before;
+import org.junit.Test;
+import org.onap.ccsdk.sli.core.sli.SvcLogicConstants;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@SuppressWarnings("unused")
+public class SliPluginUtils_ctxSortList {
+ private static final Logger LOG = LoggerFactory.getLogger(SliPluginUtils_ctxSortList.class);
+ SliPluginUtils utils = new SliPluginUtils();
+ SvcLogicContext ctx;
+ HashMap<String, String> parameters;
+ Random rand = new Random();
+
+ @Before
+ public void setUp() throws Exception {
+ this.ctx = new SvcLogicContext();
+ this.parameters = new HashMap<String, String>();
+ }
+
+ @Test
+ public final void list_of_containers() throws SvcLogicException {
+ this.parameters.put("list", "input.list");
+ this.parameters.put("sort-fields", "sort-key");
+ this.parameters.put("delimiter", ",");
+
+ ctx.setAttribute("input.list_length", "10");
+ for (int i = 0; i < 10; i++) {
+ this.ctx.setAttribute("input.list[" + i + "].sort-key", Integer.toString(rand.nextInt(10)));
+ this.ctx.setAttribute("input.list[" + i + "].value", Integer.toString(rand.nextInt(10)));
+ }
+
+ LOG.trace("BEFORE SORT:");
+ SliPluginUtils.logContextMemory(ctx, LOG, SliPluginUtils.LogLevel.TRACE);
+
+ utils.ctxSortList(this.parameters, this.ctx);
+
+ LOG.trace("AFTER SORT:");
+ SliPluginUtils.logContextMemory(ctx, LOG, SliPluginUtils.LogLevel.TRACE);
+
+ for (int i = 0; i < 9; i++) {
+ assertTrue(this.ctx.getAttribute("input.list[" + i + "].sort-key")
+ .compareTo(this.ctx.getAttribute("input.list[" + (i + 1) + "].sort-key")) < 1);
+ }
+ }
+
+ @Test
+ public final void list_of_elements() throws SvcLogicException {
+ this.parameters.put("list", "input.list");
+ this.parameters.put("delimiter", ",");
+
+ this.ctx.setAttribute("input.list_length", "10");
+ for (int i = 0; i < 10; i++) {
+ this.ctx.setAttribute("input.list[" + i + ']', Integer.toString(rand.nextInt(10)));
+ }
+
+ LOG.trace("BEFORE SORT:");
+ SliPluginUtils.logContextMemory(ctx, LOG, SliPluginUtils.LogLevel.TRACE);
+
+ utils.ctxSortList(this.parameters, this.ctx);
+
+ LOG.trace("AFTER SORT:");
+ SliPluginUtils.logContextMemory(ctx, LOG, SliPluginUtils.LogLevel.TRACE);
+
+ for (int i = 0; i < 9; i++) {
+ assertTrue(this.ctx.getAttribute("input.list[" + i + ']')
+ .compareTo(this.ctx.getAttribute("input.list[" + (i + 1) + ']')) < 1);
+ }
+ }
+
+ @Test
+ public void testGenerateUUID() throws SvcLogicException {
+ SliPluginUtils utils = new SliPluginUtils();
+ this.parameters.put("ctx-destination", "testDestination");
+ utils.generateUUID(this.parameters, ctx);
+ }
+
+ @Test
+ public void testSubstring() throws SvcLogicException {
+ SliPluginUtils utils = new SliPluginUtils();
+ this.parameters.put("string", "testString");
+ this.parameters.put("begin-index", "1");
+ this.parameters.put("result", "testResult");
+ this.parameters.put("end-index", "5");
+ utils.substring(this.parameters, ctx);
+ assertEquals("estS", ctx.getAttribute("testResult"));
+ }
+
+ @Test
+ public void testSubstringForNullEndIndex() throws SvcLogicException {
+ SliPluginUtils utils = new SliPluginUtils();
+ this.parameters.put("string", "testString");
+ this.parameters.put("begin-index", "1");
+ this.parameters.put("result", "testResult");
+ utils.substring(this.parameters, ctx);
+ assertEquals("estString", ctx.getAttribute("testResult"));
+ }
+
+ @Test
+ public void testCtxBulkCopy() {
+ ctx.setAttribute("Mykey1", "MyValue1");
+ ctx.setAttribute("Mykey2", "MyValue2");
+ SliPluginUtils.ctxBulkCopy(ctx, "Mykey", "test.");
+ assertEquals("MyValue1", ctx.getAttribute("test.1"));
+ assertEquals("MyValue2", ctx.getAttribute("test.2"));
+ }
+
+ @Test
+ public void testSetPropertiesForList() {
+ parameters.put("prefixKey", "testPrefixKey");
+ parameters.put("valuePrefixKey", "testPrefixValue");
+ parameters.put("keyName", "testKey");
+ parameters.put("keyValue", "testValue");
+
+ assertEquals(SvcLogicConstants.SUCCESS, SliPluginUtils.setPropertiesForList(parameters, ctx));
+
+ }
+}
diff --git a/core/sliPluginUtils/provider/src/test/java/org/onap/ccsdk/sli/core/slipluginutils/SliPluginUtils_ctxSortListTest.java b/core/sliPluginUtils/provider/src/test/java/org/onap/ccsdk/sli/core/slipluginutils/SliPluginUtils_ctxSortListTest.java
new file mode 100644
index 000000000..bf7cc1399
--- /dev/null
+++ b/core/sliPluginUtils/provider/src/test/java/org/onap/ccsdk/sli/core/slipluginutils/SliPluginUtils_ctxSortListTest.java
@@ -0,0 +1,97 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.slipluginutils;
+
+import static org.junit.Assert.assertTrue;
+
+import java.util.HashMap;
+import java.util.Random;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@SuppressWarnings("unused")
+public class SliPluginUtils_ctxSortListTest {
+ private static final Logger LOG = LoggerFactory.getLogger(SliPluginUtils_ctxSortListTest.class);
+ SliPluginUtils utils = new SliPluginUtils();
+ SvcLogicContext ctx;
+ HashMap<String, String> parameters;
+ Random rand = new Random();
+
+ @Before
+ public void setUp() throws Exception {
+ this.ctx = new SvcLogicContext();
+ this.parameters = new HashMap<String, String>();
+ }
+
+ @Test
+ public final void list_of_containers() throws SvcLogicException {
+ this.parameters.put("list", "input.list");
+ this.parameters.put("sort-fields", "sort-key");
+ this.parameters.put("delimiter", ",");
+
+ ctx.setAttribute("input.list_length", "10");
+ for (int i = 0; i < 10; i++) {
+ this.ctx.setAttribute("input.list[" + i + "].sort-key", Integer.toString(rand.nextInt(10)));
+ this.ctx.setAttribute("input.list[" + i + "].value", Integer.toString(rand.nextInt(10)));
+ }
+
+ LOG.trace("BEFORE SORT:");
+ SliPluginUtils.logContextMemory(ctx, LOG, SliPluginUtils.LogLevel.TRACE);
+
+ utils.ctxSortList(this.parameters, this.ctx);
+
+ LOG.trace("AFTER SORT:");
+ SliPluginUtils.logContextMemory(ctx, LOG, SliPluginUtils.LogLevel.TRACE);
+
+ for (int i = 0; i < 9; i++) {
+ assertTrue(this.ctx.getAttribute("input.list[" + i + "].sort-key").compareTo(this.ctx.getAttribute("input.list[" + (i + 1) + "].sort-key")) < 1);
+ }
+ }
+
+ @Test
+ public final void list_of_elements() throws SvcLogicException {
+ this.parameters.put("list", "input.list");
+ this.parameters.put("delimiter", ",");
+
+ this.ctx.setAttribute("input.list_length", "10");
+ for (int i = 0; i < 10; i++) {
+ this.ctx.setAttribute("input.list[" + i + ']', Integer.toString(rand.nextInt(10)));
+ }
+
+ LOG.trace("BEFORE SORT:");
+ SliPluginUtils.logContextMemory(ctx, LOG, SliPluginUtils.LogLevel.TRACE);
+
+ utils.ctxSortList(this.parameters, this.ctx);
+
+ LOG.trace("AFTER SORT:");
+ SliPluginUtils.logContextMemory(ctx, LOG, SliPluginUtils.LogLevel.TRACE);
+
+ for (int i = 0; i < 9; i++) {
+ assertTrue(this.ctx.getAttribute("input.list[" + i + ']').compareTo(this.ctx.getAttribute("input.list[" + (i + 1) + ']')) < 1);
+ }
+ }
+}
diff --git a/core/sliPluginUtils/provider/src/test/java/org/onap/ccsdk/sli/core/slipluginutils/SliStringUtilsTest.java b/core/sliPluginUtils/provider/src/test/java/org/onap/ccsdk/sli/core/slipluginutils/SliStringUtilsTest.java
new file mode 100644
index 000000000..da7046f43
--- /dev/null
+++ b/core/sliPluginUtils/provider/src/test/java/org/onap/ccsdk/sli/core/slipluginutils/SliStringUtilsTest.java
@@ -0,0 +1,398 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * Modifications Copyright (C) 2018 IBM.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.slipluginutils;
+
+import static org.hamcrest.Matchers.equalTo;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
+import java.util.HashMap;
+import java.util.Map;
+import org.junit.Before;
+import org.junit.Test;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+
+/**
+ * @author km991u
+ *
+ */
+public class SliStringUtilsTest {
+ private SvcLogicContext ctx;
+ private HashMap<String, String> param;
+ private SliStringUtils stringUtils = new SliStringUtils();
+
+ /**
+ * @throws java.lang.Exception
+ */
+ @Before
+ public void setUp() throws Exception {
+ this.ctx = new SvcLogicContext();
+ param = new HashMap<String, String>();
+ }
+
+ /**
+ * @throws SvcLogicException
+ * @see SliStringUtils#split(Map, SvcLogicContext)
+ */
+ @Test
+ public final void testSplit() throws SvcLogicException {
+ param.put("original_string", "one ## two ## three");
+ param.put("regex", " ## ");
+ param.put("ctx_memory_result_key", "result");
+
+ stringUtils.split(param, ctx);
+
+ assertThat(ctx.getAttribute("result[0]"), equalTo("one"));
+ assertThat(ctx.getAttribute("result[1]"), equalTo("two"));
+ assertThat(ctx.getAttribute("result[2]"), equalTo("three"));
+ assertThat(ctx.getAttribute("result_length"), equalTo("3"));
+ }
+
+ /**
+ * @throws SvcLogicException
+ * @see SliStringUtils#split(Map, SvcLogicContext)
+ */
+ @Test
+ public final void testSplit_limit() throws SvcLogicException {
+ param.put("original_string", "one ## two ## three");
+ param.put("regex", " ## ");
+ param.put("limit", "2");
+ param.put("ctx_memory_result_key", "result");
+
+ stringUtils.split(param, ctx);
+
+ assertThat(ctx.getAttribute("result[0]"), equalTo("one"));
+ assertThat(ctx.getAttribute("result[1]"), equalTo("two ## three"));
+ assertThat(ctx.getAttribute("result_length"), equalTo("2"));
+ }
+
+ @Test
+ public final void testSubString() throws SvcLogicException {
+ param.put("string", "splitatgivenindex");
+ param.put("begin-index", "0");
+ param.put("end-index", "5");
+ param.put("result", "result");
+
+ stringUtils.substring(param, ctx);
+
+ assertEquals("split", ctx.getAttribute("result"));
+ }
+
+ @Test
+ public final void testQuotedOrNull() throws SvcLogicException {
+ // param.put("nullString",null);
+ assertEquals("NULL", SliStringUtils.quotedOrNULL(null));
+ }
+
+ @Test
+ public void equalsIgnoreCaseTrue() throws SvcLogicException {
+ String sourceString = "HeLlOwORLD";
+ String targetSTring = "HELLOWORLD";
+ param.put("source", sourceString);
+ param.put("target", targetSTring);
+ assertEquals("true", SliStringUtils.equalsIgnoreCase(param, ctx));
+ }
+
+ @Test
+ public void equalsIgnoreCaseFalse() throws SvcLogicException {
+ String sourceString = "HeLlOwORLD";
+ String targetSTring = "goodbyeWORLD";
+ param.put("source", sourceString);
+ param.put("target", targetSTring);
+ assertEquals("false", SliStringUtils.equalsIgnoreCase(param, ctx));
+ }
+
+ @Test
+ public void toUpper() throws SvcLogicException {
+ String sourceString = "HeLlOwORLD";
+ param.put("source", sourceString);
+ String path = "my.unique.path.";
+ param.put("outputPath", path);
+ SliStringUtils.toUpper(param, ctx);
+ assertEquals(sourceString.toUpperCase(), ctx.getAttribute(path));
+ }
+
+ @Test
+ public void toLower() throws SvcLogicException {
+ String sourceString = "HeLlOwORLD";
+ param.put("source", sourceString);
+ String path = "my.unique.path.";
+ param.put("outputPath", path);
+ SliStringUtils.toLower(param, ctx);
+ assertEquals(sourceString.toLowerCase(), ctx.getAttribute(path));
+ }
+
+ @Test
+ public void containsTrue() throws SvcLogicException {
+ String sourceString = "Pizza";
+ String targetSTring = "izza";
+ param.put("source", sourceString);
+ param.put("target", targetSTring);
+ assertEquals("true", SliStringUtils.contains(param, ctx));
+ }
+
+ @Test
+ public void containsFalse() throws SvcLogicException {
+ String sourceString = "Pizza";
+ String targetSTring = "muffin";
+ param.put("source", sourceString);
+ param.put("target", targetSTring);
+ assertEquals("false", SliStringUtils.contains(param, ctx));
+ }
+
+ @Test
+ public void endsWithTrue() throws SvcLogicException {
+ String sourceString = "Pizza";
+ String targetSTring = "za";
+ param.put("source", sourceString);
+ param.put("target", targetSTring);
+ assertEquals("true", SliStringUtils.endsWith(param, ctx));
+ }
+
+ @Test
+ public void endsWithFalse() throws SvcLogicException {
+ String sourceString = "Pizza";
+ String targetSTring = "muffin";
+ param.put("source", sourceString);
+ param.put("target", targetSTring);
+ assertEquals("false", SliStringUtils.endsWith(param, ctx));
+ }
+
+ @Test
+ public void trim() throws SvcLogicException {
+ String sourceString = " H E L L O W O R L D";
+ String outputPath = "muffin";
+ param.put("source", sourceString);
+ param.put("outputPath", outputPath);
+ SliStringUtils.trim(param, ctx);
+ assertEquals(sourceString.trim(), ctx.getAttribute(outputPath));
+ }
+
+ @Test
+ public void getLength() throws SvcLogicException {
+ String sourceString = "SomeRandomString";
+ String outputPath = "muffin";
+ param.put("source", sourceString);
+ param.put("outputPath", outputPath);
+ SliStringUtils.getLength(param, ctx);
+ assertEquals(String.valueOf(sourceString.length()), ctx.getAttribute(outputPath));
+ }
+
+ @Test
+ public void startsWithFalse() throws SvcLogicException {
+ String sourceString = "Java";
+ String targetSTring = "DG";
+ param.put("source", sourceString);
+ param.put("target", targetSTring);
+ assertEquals("false", SliStringUtils.startsWith(param, ctx));
+ }
+
+ @Test
+ public void startsWithTrue() throws SvcLogicException {
+ String sourceString = "Java";
+ String targetSTring = "Ja";
+ param.put("source", sourceString);
+ param.put("target", targetSTring);
+ assertEquals("true", SliStringUtils.startsWith(param, ctx));
+ }
+
+ @Test
+ public void replace() throws SvcLogicException {
+ String sourceString = "cat Hello World cat";
+ String old = "cat";
+ String neww = "dog";
+ String outputPath = "out";
+
+ param.put("source", sourceString);
+ param.put("target", old);
+ param.put("replacement", neww);
+ param.put("outputPath", outputPath);
+ SliStringUtils.replace(param, ctx);
+ assertEquals(sourceString.replace(old, neww), ctx.getAttribute(outputPath));
+ }
+
+ @Test
+ public void replaceAll() throws SvcLogicException {
+ String source = "cat Hello World cat";
+ String target = "\\s";
+ String replacement = "";
+ String outputPath = "out";
+
+ param.put("source", source);
+ param.put("target", target);
+ param.put("replacement", replacement);
+ param.put("outputPath", outputPath);
+ SliStringUtils.replaceAll(param, ctx);
+ assertEquals(source.replaceAll(target, replacement), ctx.getAttribute(outputPath));
+ }
+
+ @Test
+ public void concat() throws SvcLogicException {
+ String sourceString = "cat";
+ String targetString = "dog";
+ String outputPath = "out";
+
+ param.put("source", sourceString);
+ param.put("target", targetString);
+ param.put("outputPath", outputPath);
+ SliStringUtils.concat(param, ctx);
+ assertEquals(sourceString + targetString, ctx.getAttribute(outputPath));
+ }
+
+ @Test
+ public void urlEncode() throws SvcLogicException {
+ String sourceString = "102/GE100/SNJSCAMCJP8/SNJSCAMCJT4";
+ String outputPath = "out";
+
+ param.put("source", sourceString);
+ param.put("outputPath", outputPath);
+ SliStringUtils.urlEncode(param, ctx);
+ assertEquals("102%2FGE100%2FSNJSCAMCJP8%2FSNJSCAMCJT4", ctx.getAttribute(outputPath));
+ }
+
+ @Test
+ public void urlDecode() throws SvcLogicException {
+ String sourceString = "102%2FGE100%2FSNJSCAMCJP8%2FSNJSCAMCJT4";
+ String outputPath = "out";
+
+ param.put("source", sourceString);
+ param.put("outputPath", outputPath);
+ SliStringUtils.urlDecode(param, ctx);
+ assertEquals("102/GE100/SNJSCAMCJP8/SNJSCAMCJT4", ctx.getAttribute(outputPath));
+ }
+
+ @Test
+ public void testXmlEscapeText() {
+ param.put("source", "102/GE100/SNJSCAMCJP8/SNJSCAMCJT4");
+ param.put("target", "target");
+ SliStringUtils.xmlEscapeText(param, ctx);
+ assertEquals("102/GE100/SNJSCAMCJP8/SNJSCAMCJT4", ctx.getAttribute("target"));
+ }
+
+ @Test(expected = Exception.class)
+ public void testSplitForEmptyParams() throws Exception {
+ SliStringUtils utils = new SliStringUtils();
+ ctx = new SvcLogicContext();
+ param = new HashMap<>();
+ utils.split(param, ctx);
+ }
+
+ @Test(expected = Exception.class)
+ public void testSubstringForEmptyParams() throws Exception {
+ SliStringUtils utils = new SliStringUtils();
+ ctx = new SvcLogicContext();
+ param = new HashMap<>();
+ utils.substring(param, ctx);
+ }
+
+ @Test
+ public void testUnescapeJsonString() throws Exception {
+ String source = "{\\\"image_name\\\":\\\"Ubuntu 14.04\\\",\\\"service-instance-id\\\":\\\"1\\\",\\\"vnf-model-customization-uuid\\\":\\\"2f\\\",\\\"vnf-id\\\":\\\"3b\\\"}";
+ param.put(SliStringUtils.INPUT_PARAM_SOURCE, source);
+ String outputPath = "unescaped";
+ param.put(SliStringUtils.INPUT_PARAM_TARGET, outputPath);
+ SliStringUtils.unescapeJsonString(param, ctx);
+ assertEquals("{\"image_name\":\"Ubuntu 14.04\",\"service-instance-id\":\"1\",\"vnf-model-customization-uuid\":\"2f\",\"vnf-id\":\"3b\"}", ctx.getAttribute(outputPath));
+ }
+
+ @Test
+ public void testEscapeJsonString() throws Exception {
+ String source = "{\"image_name\":\"Ubuntu 14.04\",\"service-instance-id\":\"1\",\"vnf-model-customization-uuid\":\"2f\",\"vnf-id\":\"3b\"}";
+ param.put(SliStringUtils.INPUT_PARAM_SOURCE, source);
+ String outputPath = "unescaped";
+ param.put(SliStringUtils.INPUT_PARAM_TARGET, outputPath);
+ SliStringUtils.escapeJsonString(param, ctx);
+ assertEquals("{\\\"image_name\\\":\\\"Ubuntu 14.04\\\",\\\"service-instance-id\\\":\\\"1\\\",\\\"vnf-model-customization-uuid\\\":\\\"2f\\\",\\\"vnf-id\\\":\\\"3b\\\"}", ctx.getAttribute(outputPath));
+ }
+
+ @Test
+ public void isEmpty() throws Exception {
+ String result = SliStringUtils.isEmpty(param, ctx);
+ param.put(SliStringUtils.INPUT_PARAM_KEY, "key_does_not_exist");
+ assertEquals(SliStringUtils.TRUE_CONSTANT, result);
+
+ ctx.setAttribute("a", null);
+ param.put(SliStringUtils.INPUT_PARAM_KEY, "a");
+ result = SliStringUtils.isEmpty(param, ctx);
+ assertEquals(SliStringUtils.TRUE_CONSTANT, result);
+
+ ctx.setAttribute("a", "");
+ result = SliStringUtils.isEmpty(param, ctx);
+ assertEquals(SliStringUtils.TRUE_CONSTANT, result);
+
+ ctx.setAttribute("a", " ");
+ result = SliStringUtils.isEmpty(param, ctx);
+ assertEquals(SliStringUtils.FALSE_CONSTANT, result);
+ }
+
+ @Test
+ public void isBlank() throws Exception {
+ String result = SliStringUtils.isBlank(param, ctx);
+ param.put(SliStringUtils.INPUT_PARAM_KEY, "key_does_not_exist");
+ assertEquals(SliStringUtils.TRUE_CONSTANT, result);
+
+ ctx.setAttribute("a", null);
+ param.put(SliStringUtils.INPUT_PARAM_KEY, "a");
+ result = SliStringUtils.isBlank(param, ctx);
+ assertEquals(SliStringUtils.TRUE_CONSTANT, result);
+
+ ctx.setAttribute("a", "");
+ result = SliStringUtils.isBlank(param, ctx);
+ assertEquals(SliStringUtils.TRUE_CONSTANT, result);
+
+ ctx.setAttribute("a", " ");
+ result = SliStringUtils.isBlank(param, ctx);
+ assertEquals(SliStringUtils.TRUE_CONSTANT, result);
+ }
+
+ @Test
+ public void isNull() throws Exception {
+ String result = SliStringUtils.isNull(param, ctx);
+ param.put(SliStringUtils.INPUT_PARAM_KEY, "key_does_not_exist");
+ assertEquals(SliStringUtils.TRUE_CONSTANT, result);
+
+ ctx.setAttribute("a", null);
+ param.put(SliStringUtils.INPUT_PARAM_KEY, "a");
+ result = SliStringUtils.isNull(param, ctx);
+ assertEquals(SliStringUtils.TRUE_CONSTANT, result);
+
+ ctx.setAttribute("a", "");
+ result = SliStringUtils.isNull(param, ctx);
+ assertEquals(SliStringUtils.FALSE_CONSTANT, result);
+
+ ctx.setAttribute("a", " ");
+ result = SliStringUtils.isNull(param, ctx);
+ assertEquals(SliStringUtils.FALSE_CONSTANT, result);
+ }
+
+ @Test
+ public void testBase64DecodingAlgo() throws Exception{
+ String input = "MDUxMDAw";
+ String decodeVal = "decodedPath";
+ param.put("encodedValue",input);
+ param.put("decodedValue", decodeVal);
+ SliStringUtils.base64DecodingAlgo(param,ctx);
+ assertEquals("051000",ctx.getAttribute(decodeVal));
+ }
+}
diff --git a/core/sliPluginUtils/provider/src/test/java/org/onap/ccsdk/sli/core/slipluginutils/SvcLogicContextListTest.java b/core/sliPluginUtils/provider/src/test/java/org/onap/ccsdk/sli/core/slipluginutils/SvcLogicContextListTest.java
new file mode 100644
index 000000000..f916bbfca
--- /dev/null
+++ b/core/sliPluginUtils/provider/src/test/java/org/onap/ccsdk/sli/core/slipluginutils/SvcLogicContextListTest.java
@@ -0,0 +1,307 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.slipluginutils;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import java.util.HashMap;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+
+public class SvcLogicContextListTest {
+ //private static final Logger LOG = LoggerFactory.getLogger(SvcLogicContextTest.class);
+ private SvcLogicContext ctx;
+
+ @Before
+ public void setUp() throws Exception {
+ this.ctx = new SvcLogicContext();
+ }
+
+ // TODO: javadoc
+ @Test
+ public final void testSvcLogicContextList_SingleValueList() {
+ ctx.setAttribute("list[0]", "0");
+ ctx.setAttribute("list[1]", "1");
+ ctx.setAttribute("list[2]", "2");
+ ctx.setAttribute("list[3]", "3");
+ ctx.setAttribute("list[4]", "4");
+ ctx.setAttribute("list_length", "5");
+
+ SvcLogicContextList list = new SvcLogicContextList( ctx, "list" );
+
+ // Check that size of list is 5
+ assertEquals(5, list.size());
+
+ // Check that each HashMap has it's list value in the empty string key
+ // and has no other values
+ assertEquals(1, list.get(0).size());
+ assertEquals("0", list.get(0).get(""));
+ assertEquals(1, list.get(1).size());
+ assertEquals("1", list.get(1).get(""));
+ assertEquals(1, list.get(2).size());
+ assertEquals("2", list.get(2).get(""));
+ assertEquals(1, list.get(3).size());
+ assertEquals("3", list.get(3).get(""));
+ assertEquals(1, list.get(4).size());
+ assertEquals("4", list.get(4).get(""));
+ }
+
+ // TODO: javadoc
+ @Test
+ public final void testSvcLogicContextList_ObjectList() {
+ ctx.setAttribute("list[0].ipv4", "1.1.1.0");
+ ctx.setAttribute("list[0].ipv6", "2001::0");
+ ctx.setAttribute("list[1].ipv4", "1.1.1.1");
+ ctx.setAttribute("list[1].ipv6", "2001::1");
+ ctx.setAttribute("list[2].ipv4", "1.1.1.2");
+ ctx.setAttribute("list[2].ipv6", "2001::2");
+ ctx.setAttribute("list[3].ipv4", "1.1.1.3");
+ ctx.setAttribute("list[3].ipv6", "2001::3");
+ ctx.setAttribute("list[4].ipv4", "1.1.1.4");
+ ctx.setAttribute("list[4].ipv6", "2001::4");
+ ctx.setAttribute("list_length", "5");
+
+ SvcLogicContextList list = new SvcLogicContextList( ctx, "list" );
+
+ // Check that size of list is 5
+ assertEquals(5, list.size());
+
+ assertEquals(2, list.get(0).size());
+ assertEquals("1.1.1.0", list.get(0).get("ipv4"));
+ assertEquals("2001::0", list.get(0).get("ipv6"));
+ assertEquals(2, list.get(1).size());
+ assertEquals("1.1.1.1", list.get(1).get("ipv4"));
+ assertEquals("2001::1", list.get(1).get("ipv6"));
+ assertEquals(2, list.get(2).size());
+ assertEquals("1.1.1.2", list.get(2).get("ipv4"));
+ assertEquals("2001::2", list.get(2).get("ipv6"));
+ assertEquals(2, list.get(3).size());
+ assertEquals("1.1.1.3", list.get(3).get("ipv4"));
+ assertEquals("2001::3", list.get(3).get("ipv6"));
+ assertEquals(2, list.get(4).size());
+ assertEquals("1.1.1.4", list.get(4).get("ipv4"));
+ assertEquals("2001::4", list.get(4).get("ipv6"));
+ }
+
+ // TODO: javadoc
+ @Test
+ public final void testExtract() {
+ ctx.setAttribute("list[0]", "0");
+ ctx.setAttribute("list[1]", "1");
+ ctx.setAttribute("list[2]", "2");
+ ctx.setAttribute("list[3]", "3");
+ ctx.setAttribute("list[4]", "4");
+ ctx.setAttribute("list_length", "5");
+ ctx.setAttribute("Other", "other");
+
+ SvcLogicContextList list = SvcLogicContextList.extract(ctx, "list");
+
+ // Check that size of list is 5
+ assertEquals(5, list.size());
+
+ // Check that all list values exist in list object
+ assertEquals(1, list.get(0).size());
+ assertEquals("0", list.get(0).get(""));
+ assertEquals(1, list.get(1).size());
+ assertEquals("1", list.get(1).get(""));
+ assertEquals(1, list.get(2).size());
+ assertEquals("2", list.get(2).get(""));
+ assertEquals(1, list.get(3).size());
+ assertEquals("3", list.get(3).get(""));
+ assertEquals(1, list.get(4).size());
+ assertEquals("4", list.get(4).get(""));
+
+ // Check that all list values no longer exist in ctx
+ assertNull(ctx.getAttribute("list[0]"));
+ assertNull(ctx.getAttribute("list[1]"));
+ assertNull(ctx.getAttribute("list[2]"));
+ assertNull(ctx.getAttribute("list[3]"));
+ assertNull(ctx.getAttribute("list[4]"));
+ assertNull(ctx.getAttribute("list_length"));
+
+ // Check that non-list values still exist in ctx
+ assertEquals("other", ctx.getAttribute("Other"));
+ }
+
+ // TODO: javadoc
+ @Test
+ public final void testRemove_int() {
+ ctx.setAttribute("list[0]", "0");
+ ctx.setAttribute("list[1]", "1");
+ ctx.setAttribute("list[2]", "2");
+ ctx.setAttribute("list[3]", "3");
+ ctx.setAttribute("list[4]", "4");
+ ctx.setAttribute("list_length", "5");
+
+ SvcLogicContextList list = new SvcLogicContextList( ctx, "list" );
+ list.remove(2);
+
+ // Check that size of list is 4 (1 less than original)
+ assertEquals(4, list.size());
+
+ // Check that value was remove from list
+ assertEquals(1, list.get(0).size());
+ assertEquals("0", list.get(0).get(""));
+ assertEquals(1, list.get(1).size());
+ assertEquals("1", list.get(1).get(""));
+ assertEquals(1, list.get(2).size());
+ assertEquals("3", list.get(2).get(""));
+ assertEquals(1, list.get(3).size());
+ assertEquals("4", list.get(3).get(""));
+ }
+
+ // TODO: javadoc
+ @Test
+ public final void testRemove_StringString() {
+ ctx.setAttribute("list[0].ipv4", "1.1.1.0");
+ ctx.setAttribute("list[0].ipv6", "2001::0");
+ ctx.setAttribute("list[1].ipv4", "1.1.1.1");
+ ctx.setAttribute("list[1].ipv6", "2001::1");
+ ctx.setAttribute("list[2].ipv4", "1.1.1.2");
+ ctx.setAttribute("list[2].ipv6", "2001::2");
+ ctx.setAttribute("list[3].ipv4", "1.1.1.3");
+ ctx.setAttribute("list[3].ipv6", "2001::3");
+ ctx.setAttribute("list[4].ipv4", "1.1.1.4");
+ ctx.setAttribute("list[4].ipv6", "2001::4");
+ ctx.setAttribute("list[5].ipv4", "1.1.1.2");
+ ctx.setAttribute("list[5].ipv6", "2001::2");
+ ctx.setAttribute("list_length", "6");
+
+ SvcLogicContextList list = new SvcLogicContextList( ctx, "list" );
+ list.remove("ipv4", "1.1.1.2");
+
+ // Check that size of list is 4 (2 less than original)
+ assertEquals(4, list.size());
+
+ // Check that all elements with values ending in 2 were removed
+ assertEquals("1.1.1.0", list.get(0).get("ipv4"));
+ assertEquals("2001::0", list.get(0).get("ipv6"));
+ assertEquals("1.1.1.1", list.get(1).get("ipv4"));
+ assertEquals("2001::1", list.get(1).get("ipv6"));
+ assertEquals("1.1.1.3", list.get(2).get("ipv4"));
+ assertEquals("2001::3", list.get(2).get("ipv6"));
+ assertEquals("1.1.1.4", list.get(3).get("ipv4"));
+ assertEquals("2001::4", list.get(3).get("ipv6"));
+ }
+
+ // TODO: javadoc
+ @Test
+ public final void testRemove_StringString_ValueList() {
+ ctx.setAttribute("list[0]", "5");
+ ctx.setAttribute("list[1]", "6");
+ ctx.setAttribute("list[2]", "7");
+ ctx.setAttribute("list[3]", "8");
+ ctx.setAttribute("list[4]", "9");
+ ctx.setAttribute("list_length", "5");
+
+ SvcLogicContextList list = new SvcLogicContextList( ctx, "list" );
+ list.remove("", "6");
+
+ // Check that size of list is 4 (1 less than original)
+ assertEquals(4, list.size());
+
+ // Check that value was remove from list
+ assertEquals(1, list.get(0).size());
+ assertEquals("5", list.get(0).get(""));
+ assertEquals(1, list.get(1).size());
+ assertEquals("7", list.get(1).get(""));
+ assertEquals(1, list.get(2).size());
+ assertEquals("8", list.get(2).get(""));
+ assertEquals(1, list.get(3).size());
+ assertEquals("9", list.get(3).get(""));
+ }
+
+ // TODO: javadoc
+ @Test
+ public final void testRemove_Map() {
+ ctx.setAttribute("list[0].ipv4", "1.1.1.0");
+ ctx.setAttribute("list[0].ipv6", "2001::0");
+ ctx.setAttribute("list[1].ipv4", "1.1.1.1");
+ ctx.setAttribute("list[1].ipv6", "2001::1");
+ ctx.setAttribute("list[2].ipv4", "1.1.1.2");
+ ctx.setAttribute("list[2].ipv6", "2001::2");
+ ctx.setAttribute("list[3].ipv4", "1.1.1.3");
+ ctx.setAttribute("list[3].ipv6", "2001::3");
+ ctx.setAttribute("list[4].ipv4", "1.1.1.4");
+ ctx.setAttribute("list[4].ipv6", "2001::4");
+ ctx.setAttribute("list[5].ipv4", "1.1.1.2");
+ ctx.setAttribute("list[5].ipv6", "2001::2");
+ ctx.setAttribute("list_length", "6");
+
+ HashMap<String,String> remove_key = new HashMap<String,String>();
+ remove_key.put("ipv4", "1.1.1.2");
+ remove_key.put("ipv6", "2001::2");
+
+ SvcLogicContextList list = new SvcLogicContextList( ctx, "list" );
+ list.remove(remove_key);
+
+ // Check that size of list is 4 (2 less than original)
+ assertEquals(4, list.size());
+
+ // Check that all elements with values ending in 2 were removed
+ assertEquals("1.1.1.0", list.get(0).get("ipv4"));
+ assertEquals("2001::0", list.get(0).get("ipv6"));
+ assertEquals("1.1.1.1", list.get(1).get("ipv4"));
+ assertEquals("2001::1", list.get(1).get("ipv6"));
+ assertEquals("1.1.1.3", list.get(2).get("ipv4"));
+ assertEquals("2001::3", list.get(2).get("ipv6"));
+ assertEquals("1.1.1.4", list.get(3).get("ipv4"));
+ assertEquals("2001::4", list.get(3).get("ipv6"));
+ }
+
+ // TODO: javadoc
+ @Test
+ public final void testWriteToContext() {
+ ctx.setAttribute("list[0]", "0");
+ ctx.setAttribute("list[1]", "1");
+ ctx.setAttribute("list[2]", "2");
+ ctx.setAttribute("list[3]", "3");
+ ctx.setAttribute("list[4]", "4");
+ ctx.setAttribute("list_length", "5");
+ ctx.setAttribute("Other", "other");
+
+ SvcLogicContextList list = new SvcLogicContextList( ctx, "list" );
+
+ // Erase context memory
+ ctx = new SvcLogicContext();
+
+ // Write list back into context memory
+ list.writeToContext(ctx);
+
+ // Check that size of list is 5
+ assertEquals(5, list.size());
+
+ // Check that all list values exist in list object
+ assertEquals("0", ctx.getAttribute("list[0]"));
+ assertEquals("1", ctx.getAttribute("list[1]"));
+ assertEquals("2", ctx.getAttribute("list[2]"));
+ assertEquals("3", ctx.getAttribute("list[3]"));
+ assertEquals("4", ctx.getAttribute("list[4]"));
+ assertEquals("5", ctx.getAttribute("list_length"));
+
+ // Check that old list values aren't in new list
+ assertNull(ctx.getAttribute("Other"));
+ }
+}
diff --git a/core/sliPluginUtils/provider/src/test/resources/2dArray.json b/core/sliPluginUtils/provider/src/test/resources/2dArray.json
new file mode 100644
index 000000000..2a94b46f4
--- /dev/null
+++ b/core/sliPluginUtils/provider/src/test/resources/2dArray.json
@@ -0,0 +1,4 @@
+[
+ ["apple", "orange", "banana", null],
+ ["squash", "broccoli", "cauliflower"]
+] \ No newline at end of file
diff --git a/core/sliPluginUtils/provider/src/test/resources/3dArray.json b/core/sliPluginUtils/provider/src/test/resources/3dArray.json
new file mode 100644
index 000000000..149955596
--- /dev/null
+++ b/core/sliPluginUtils/provider/src/test/resources/3dArray.json
@@ -0,0 +1,4 @@
+[
+ [["a","b","c"], ["d","e","f"]],
+ [["x","y","z"]]
+] \ No newline at end of file
diff --git a/core/sliPluginUtils/provider/src/test/resources/ArrayMenu.json b/core/sliPluginUtils/provider/src/test/resources/ArrayMenu.json
new file mode 100644
index 000000000..26a24f292
--- /dev/null
+++ b/core/sliPluginUtils/provider/src/test/resources/ArrayMenu.json
@@ -0,0 +1,41 @@
+[{
+ "id": "1",
+ "type": "pizza",
+ "name": "plain",
+ "calories": 1000,
+ "vegetarian": true
+ }, {
+ "id": "2",
+ "type": "pizza",
+ "name": "Tuesday Special",
+ "calories": null,
+ "vegetarian": false,
+ "topping":
+ [{
+ "id": "1",
+ "name": "onion"
+ }, {
+ "id": "2",
+ "name": "pepperoni"
+ }
+ ]
+ }, {
+ "id": "3",
+ "type": "pizza",
+ "name": "House Special",
+ "calories": 1500,
+ "vegetarian": true,
+ "topping":
+ [{
+ "id": "3",
+ "name": "basil"
+ }, {
+ "id": "4",
+ "name": "fresh mozzarella"
+ }, {
+ "id": "5",
+ "name": "tomato"
+ }
+ ]
+ }
+]
diff --git a/core/sliPluginUtils/provider/src/test/resources/EmbeddedEscapedJson.json b/core/sliPluginUtils/provider/src/test/resources/EmbeddedEscapedJson.json
new file mode 100644
index 000000000..dbb6d8d3a
--- /dev/null
+++ b/core/sliPluginUtils/provider/src/test/resources/EmbeddedEscapedJson.json
@@ -0,0 +1,16 @@
+{
+ "input": {
+ "parameters":
+ [{
+ "name": "escapedJsonObject",
+ "value": "[{\"id\":\"0.2.0.0\/16\"},{\"id\":\"ge04::\/64\"}]"
+ }, {
+ "name": "password",
+ "value": "Hello\/World"
+ }, {
+ "name": "resourceName",
+ "value": "The\t\"Best\"\tName"
+ }
+ ]
+ }
+} \ No newline at end of file
diff --git a/core/sliPluginUtils/provider/src/test/resources/EscapedJson.json b/core/sliPluginUtils/provider/src/test/resources/EscapedJson.json
new file mode 100644
index 000000000..a7719e819
--- /dev/null
+++ b/core/sliPluginUtils/provider/src/test/resources/EscapedJson.json
@@ -0,0 +1 @@
+{\"widget\":{\"debug\":false,\"window\":{\"title\":\"ONAP Widget\",\"name\":\"main_window\",\"width\":200,\"height\":300},\"image\":{\"src\":\"images\/moon.png\",\"name\":\"moon\",\"hOffset\":150,\"vOffset\":150,\"alignment\":\"center\"},\"text\":{\"data\":\"Click Me\",\"size\":21,\"style\":\"bold\",\"name\":\"text1\",\"hOffset\":350,\"vOffset\":200,\"alignment\":\"center\"}}} \ No newline at end of file
diff --git a/core/sliPluginUtils/provider/src/test/resources/JsonObject.json b/core/sliPluginUtils/provider/src/test/resources/JsonObject.json
new file mode 100644
index 000000000..0578368f8
--- /dev/null
+++ b/core/sliPluginUtils/provider/src/test/resources/JsonObject.json
@@ -0,0 +1,5 @@
+{
+ "aaa": "123",
+ "bbb": "xyz",
+ "c.d": "abc"
+} \ No newline at end of file
diff --git a/core/sliPluginUtils/provider/src/test/resources/ObjectMenu.json b/core/sliPluginUtils/provider/src/test/resources/ObjectMenu.json
new file mode 100644
index 000000000..56f842d48
--- /dev/null
+++ b/core/sliPluginUtils/provider/src/test/resources/ObjectMenu.json
@@ -0,0 +1,43 @@
+{
+ "menu": [{
+ "id": "1",
+ "type": "pizza",
+ "name": "plain",
+ "calories": 1000,
+ "vegetarian": true
+ }, {
+ "id": "2",
+ "type": "pizza",
+ "name": "Tuesday Special",
+ "calories": 2000,
+ "vegetarian": false,
+ "topping":
+ [{
+ "id": "1",
+ "name": "onion"
+ }, {
+ "id": "2",
+ "name": "pepperoni"
+ }
+ ]
+ }, {
+ "id": "3",
+ "type": "pizza",
+ "name": "House Special",
+ "calories": 1500,
+ "vegetarian": true,
+ "topping":
+ [{
+ "id": "3",
+ "name": "basil"
+ }, {
+ "id": "4",
+ "name": "fresh mozzarella"
+ }, {
+ "id": "5",
+ "name": "tomato"
+ }
+ ]
+ }
+ ]
+}
diff --git a/core/sliPluginUtils/provider/src/test/resources/Widget.json b/core/sliPluginUtils/provider/src/test/resources/Widget.json
new file mode 100644
index 000000000..6b90907ce
--- /dev/null
+++ b/core/sliPluginUtils/provider/src/test/resources/Widget.json
@@ -0,0 +1,27 @@
+{
+ "widget": {
+ "debug": false,
+ "window": {
+ "title": "ONAP Widget",
+ "name": "main_window",
+ "width": 200,
+ "height": 300
+ },
+ "image": {
+ "src": "images/moon.png",
+ "name": "moon",
+ "hOffset": 150,
+ "vOffset": 150,
+ "alignment": "center"
+ },
+ "text": {
+ "data": "Click Me",
+ "size": 21,
+ "style": "bold",
+ "name": "text1",
+ "hOffset": 350,
+ "vOffset": null,
+ "alignment": "center"
+ }
+ }
+} \ No newline at end of file
diff --git a/core/sliapi/.gitignore b/core/sliapi/.gitignore
new file mode 100755
index 000000000..1558a77c4
--- /dev/null
+++ b/core/sliapi/.gitignore
@@ -0,0 +1,38 @@
+#####standard .git ignore entries#####
+
+## IDE Specific Files ##
+org.eclipse.core.resources.prefs
+.classpath
+.project
+.settings
+.idea
+.externalToolBuilders
+maven-eclipse.xml
+workspace
+
+## Compilation Files ##
+*.class
+**/target
+target
+target-ide
+MANIFEST.MF
+
+## Misc Ignores (OS specific etc) ##
+bin/
+dist
+*~
+*.ipr
+*.iml
+*.iws
+classes
+out/
+.DS_STORE
+.metadata
+
+## Derby files
+sdnctl
+derby.log
+
+## Folders which contain auto generated source code ##
+yang-gen-config
+yang-gen-sal
diff --git a/core/sliapi/README.txt b/core/sliapi/README.txt
new file mode 100755
index 000000000..f9f4a2ab5
--- /dev/null
+++ b/core/sliapi/README.txt
@@ -0,0 +1,35 @@
+======================
+Introduction
+======================
+You have generated an MD-SAL module using the Brocade Archetype.
+
+* You should be able to successfully run 'mvn clean install' on this project.
+* This will produce a .zip file under the karaf.extension directory which you can deploy using
+Brocade's extension deployment mechanism.
+
+======================
+Next Steps:
+======================
+* run a 'mvn clean install' if you haven't already. This will generate some code from the yang models.
+* Modify the model yang file under the model project.
+* Follow the comments in the generated provider class to wire your new provider into the generated
+code.
+* Modify the generated provider model to respond to and handle the yang model. Depending on what
+you added to your model you may need to inherit additional interfaces or make other changes to
+the provider model.
+
+======================
+Generated Bundles:
+======================
+* model
+ - Provides the yang model for your application. This is your primary northbound interface.
+* provider
+ - Provides a template implementation for a provider to respond to your yang model.
+* features
+ - Defines a karaf feature. If you add dependencies on third-party bundles then you will need to
+ modify the features.xml to list out the dependencies.
+* karaf.extension
+ - Bundles all of the jars and third party dependencies (minus ODL dependencies) into a single
+ .zip file with the necessary configuration files to work correctly with the Brocade extension
+ mechanism.
+
diff --git a/core/sliapi/installer/pom.xml b/core/sliapi/installer/pom.xml
new file mode 100755
index 000000000..1b3b24a45
--- /dev/null
+++ b/core/sliapi/installer/pom.xml
@@ -0,0 +1,164 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>odlparent-lite</artifactId>
+ <version>2.1.0-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sliapi-installer</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>pom</packaging>
+
+ <name>ccsdk-sli-core :: sliapi :: ${project.artifactId}</name>
+
+ <properties>
+ <application.name>ccsdk-sliapi</application.name>
+ <features.boot>${application.name}</features.boot>
+ <features.repositories>mvn:org.onap.ccsdk.sli.core/${features.boot}/${project.version}/xml/features
+ </features.repositories>
+ <include.transitive.dependencies>false</include.transitive.dependencies>
+ </properties>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sli-common</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sli-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>dblib-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>${application.name}</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ <exclusions>
+ <exclusion>
+ <groupId>*</groupId>
+ <artifactId>*</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>sliapi-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>sliapi-model-yang</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>maven-repo-zip</id>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ <phase>package</phase>
+ <configuration>
+ <attach>true</attach>
+ <finalName>stage/${application.name}-${project.version}</finalName>
+ <descriptors>
+ <descriptor>src/assembly/assemble_mvnrepo_zip.xml</descriptor>
+ </descriptors>
+ <appendAssemblyId>true</appendAssemblyId>
+ </configuration>
+ </execution>
+ <execution>
+ <id>installer-zip</id>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ <phase>package</phase>
+ <configuration>
+ <attach>true</attach>
+ <finalName>${application.name}-${project.version}-installer</finalName>
+ <descriptors>
+ <descriptor>src/assembly/assemble_installer_zip.xml</descriptor>
+ </descriptors>
+ <appendAssemblyId>false</appendAssemblyId>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>copy-dependencies</id>
+ <goals>
+ <goal>copy-dependencies</goal>
+ </goals>
+ <phase>prepare-package</phase>
+ <configuration>
+ <transitive>false</transitive>
+ <outputDirectory>${project.build.directory}/assembly/system</outputDirectory>
+ <overWriteReleases>false</overWriteReleases>
+ <overWriteSnapshots>true</overWriteSnapshots>
+ <overWriteIfNewer>true</overWriteIfNewer>
+ <useRepositoryLayout>true</useRepositoryLayout>
+ <addParentPoms>false</addParentPoms>
+ <copyPom>false</copyPom>
+ <includeArtifactIds>sliapi-model,sliapi-provider,sliapi-model-yang,ccsdk-sliapi,features-sliapi
+ </includeArtifactIds>
+ <scope>provided</scope>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <artifactId>maven-resources-plugin</artifactId>
+ <version>2.6</version>
+ <executions>
+ <execution>
+ <id>copy-version</id>
+ <goals>
+ <goal>copy-resources</goal>
+ </goals><!-- here the phase you need -->
+ <phase>validate</phase>
+ <configuration>
+ <outputDirectory>${basedir}/target/stage</outputDirectory>
+ <resources>
+ <resource>
+ <directory>src/main/resources/scripts</directory>
+ <includes>
+ <include>install-feature.sh</include>
+ </includes>
+ <filtering>true</filtering>
+ </resource>
+ </resources>
+ </configuration>
+ </execution>
+
+ </executions>
+ </plugin>
+
+ </plugins>
+ </build>
+</project>
diff --git a/core/sliapi/installer/src/assembly/assemble_installer_zip.xml b/core/sliapi/installer/src/assembly/assemble_installer_zip.xml
new file mode 100644
index 000000000..2d3c0606d
--- /dev/null
+++ b/core/sliapi/installer/src/assembly/assemble_installer_zip.xml
@@ -0,0 +1,59 @@
+<!--
+ ============LICENSE_START=======================================================
+ ONAP : CCSDK
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property. All rights
+ reserved.
+ ================================================================================
+ 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.
+ ============LICENSE_END=========================================================
+ -->
+
+<!-- Defines how we build the .zip file which is our distribution. -->
+
+<assembly
+ xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
+ <id>bin</id>
+ <formats>
+ <format>zip</format>
+ </formats>
+
+ <!-- we want "system" and related files right at the root level
+ as this file is suppose to be unzip on top of a karaf
+ distro. -->
+ <includeBaseDirectory>false</includeBaseDirectory>
+
+ <fileSets>
+ <fileSet>
+ <directory>target/stage/</directory>
+ <outputDirectory>${application.name}</outputDirectory>
+ <fileMode>755</fileMode>
+ <includes>
+ <include>*.sh</include>
+ </includes>
+ </fileSet>
+ <fileSet>
+ <directory>target/stage/</directory>
+ <outputDirectory>${application.name}</outputDirectory>
+ <fileMode>644</fileMode>
+ <excludes>
+ <exclude>*.sh</exclude>
+ </excludes>
+ </fileSet>
+ </fileSets>
+
+
+
+</assembly>
diff --git a/core/sliapi/installer/src/assembly/assemble_mvnrepo_zip.xml b/core/sliapi/installer/src/assembly/assemble_mvnrepo_zip.xml
new file mode 100644
index 000000000..c4eb9aa25
--- /dev/null
+++ b/core/sliapi/installer/src/assembly/assemble_mvnrepo_zip.xml
@@ -0,0 +1,49 @@
+<!--
+ ============LICENSE_START=======================================================
+ ONAP : CCSDK
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property. All rights
+ reserved.
+ ================================================================================
+ 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.
+ ============LICENSE_END=========================================================
+ -->
+
+<!-- Defines how we build the .zip file which is our distribution. -->
+
+<assembly
+ xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
+ <id>repo</id>
+ <formats>
+ <format>zip</format>
+ </formats>
+
+ <!-- we want "system" and related files right at the root level
+ as this file is suppose to be unzip on top of a karaf
+ distro. -->
+ <includeBaseDirectory>false</includeBaseDirectory>
+
+ <fileSets>
+ <fileSet>
+ <directory>target/assembly/</directory>
+ <outputDirectory>.</outputDirectory>
+ <excludes>
+ </excludes>
+ </fileSet>
+ </fileSets>
+
+
+
+</assembly>
diff --git a/core/sliapi/installer/src/main/resources/scripts/install-feature.sh b/core/sliapi/installer/src/main/resources/scripts/install-feature.sh
new file mode 100644
index 000000000..74b95b5c8
--- /dev/null
+++ b/core/sliapi/installer/src/main/resources/scripts/install-feature.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+
+###
+# ============LICENSE_START=======================================================
+# ONAP : CCSDK
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights
+# reserved.
+# ================================================================================
+# 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.
+# ============LICENSE_END=========================================================
+###
+
+ODL_HOME=${ODL_HOME:-/opt/opendaylight/current}
+ODL_KARAF_CLIENT=${ODL_KARAF_CLIENT:-${ODL_HOME}/bin/client}
+INSTALLERDIR=$(dirname $0)
+
+REPOZIP=${INSTALLERDIR}/${features.boot}-${project.version}.zip
+
+if [ -f ${REPOZIP} ]
+then
+ unzip -d ${ODL_HOME} ${REPOZIP}
+else
+ echo "ERROR : repo zip ($REPOZIP) not found"
+ exit 1
+fi
+
+${ODL_KARAF_CLIENT} feature:repo-add ${features.repositories}
+${ODL_KARAF_CLIENT} feature:install ${features.boot}
diff --git a/core/sliapi/model/pom.xml b/core/sliapi/model/pom.xml
new file mode 100755
index 000000000..f23ad8da7
--- /dev/null
+++ b/core/sliapi/model/pom.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>odlparent-lite</artifactId>
+ <version>2.1.0-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sliapi-model</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>pom</packaging>
+
+ <name>ccsdk-sli-core :: sliapi</name>
+
+ <modules>
+ <module>yang</module>
+ <module>swagger</module>
+ </modules>
+
+</project>
diff --git a/core/sliapi/model/src/main/resources/sli-api.20161110.yaml b/core/sliapi/model/src/main/resources/sli-api.20161110.yaml
new file mode 100644
index 000000000..3420c66b5
--- /dev/null
+++ b/core/sliapi/model/src/main/resources/sli-api.20161110.yaml
@@ -0,0 +1,254 @@
+---
+swagger: '2.0'
+info:
+ version: 1.0.0
+ title: "SLI API"
+basePath: '/restconf'
+schemes:
+ - http
+ - https
+paths:
+ '/restconf/config/SLI-API:test-results':
+ delete:
+ produces:
+ - application/json
+ - application/xml
+ responses:
+ '200':
+ description: No response was specified
+ description: Test results
+ operationId: delete-test-results
+ get:
+ produces:
+ - application/json
+ - application/xml
+ responses:
+ '200':
+ description: No response was specified
+ schema:
+ $ref: '#/definitions/test-results'
+ description: Test results
+ operationId: get-test-results
+ post:
+ consumes:
+ - application/json
+ - application/xml
+ produces:
+ - application/json
+ - application/xml
+ parameters:
+ - in: body
+ name: testResults
+ required: false
+ schema:
+ $ref: '#/definitions/test-results'
+ responses:
+ '200':
+ description: No response was specified
+ schema:
+ $ref: '#/definitions/test-results'
+ description: Test results
+ operationId: post-test-results
+ put:
+ consumes:
+ - application/json
+ - application/xml
+ produces:
+ - application/json
+ - application/xml
+ parameters:
+ - in: body
+ name: testResults
+ required: false
+ schema:
+ $ref: '#/definitions/test-results'
+ responses:
+ '200':
+ description: No response was specified
+ schema:
+ $ref: '#/definitions/test-results'
+ description: Test results
+ operationId: put-test-results
+
+ '/restconf/config/SLI-API:test-results/test-result/{test-identifier}':
+ delete:
+ produces:
+ - application/json
+ - application/xml
+ parameters:
+ - in: path
+ name: test-identifier
+ required: true
+ type: string
+ responses:
+ '200':
+ description: No response was specified
+ operationId: delete-test-result
+ get:
+ produces:
+ - application/json
+ - application/xml
+ parameters:
+ - in: path
+ name: test-identifier
+ required: true
+ type: string
+ responses:
+ '200':
+ description: No response was specified
+ schema:
+ $ref: '#/definitions/test-result'
+ operationId: get-test-result
+ put:
+ consumes:
+ - application/json
+ - application/xml
+ produces:
+ - application/json
+ - application/xml
+ parameters:
+ - in: path
+ name: test-identifier
+ required: true
+ type: string
+ - in: body
+ name: testResult
+ required: false
+ schema:
+ $ref: '#/definitions/test-result'
+ responses:
+ '200':
+ description: No response was specified
+ schema:
+ $ref: '#/definitions/test-result'
+ operationId: PUT-test-result
+
+ '/restconf/operational/SLI-API:test-results':
+ get:
+ produces:
+ - application/json
+ - application/xml
+ responses:
+ '200':
+ description: No response was specified
+ schema:
+ $ref: '#/definitions/test-results'
+ description: Test results
+ operationId: GET-test-results
+ '/restconf/operations/SLI-API:execute-graph':
+ post:
+ consumes:
+ - application/json
+ - application/xml
+ produces:
+ - application/json
+ - application/xml
+ parameters:
+ - in: body
+ name: executeGraphInput
+ required: false
+ schema:
+ $ref: '#/definitions/execute-graph-input'
+ responses:
+ '200':
+ description: No response was specified
+ schema:
+ $ref: '#/definitions/response-fields'
+ description: ' Method to add a new parameter.'
+ operationId: execute-graph
+ '/restconf/operations/SLI-API:healthcheck':
+ post:
+ consumes:
+ - application/json
+ - application/xml
+ produces:
+ - application/json
+ - application/xml
+ responses:
+ '200':
+ description: No response was specified
+ schema:
+ $ref: '#/definitions/response-fields'
+ operationId: healthcheck
+ '/restconf/operations/SLI-API:vlbcheck':
+ post:
+ consumes:
+ - application/json
+ - application/xml
+ produces:
+ - application/json
+ - application/xml
+ responses:
+ '200':
+ description: No response was specified
+ schema:
+ $ref: '#/definitions/response-fields'
+ operationId: vlbcheck
+
+definitions:
+ parameter-setting:
+ type: object
+ properties:
+ parameter-name:
+ type: string
+ int-value:
+ type: integer
+ string-value:
+ type: string
+ boolean-value:
+ type: boolean
+
+ response-fields:
+ type: object
+ properties:
+ response-code:
+ type: string
+ ack-final-indicator:
+ type: string
+ response-message:
+ type: string
+ context-memory-json:
+ type: string
+
+ test-results:
+ type: object
+ properties:
+ test-results:
+ type: array
+ items:
+ $ref: '#/definitions/test-result'
+
+ test-result:
+ type: object
+ properties:
+ test-identifier:
+ type: string
+ results:
+ type: array
+ items:
+ type: string
+
+ execute-graph-input:
+ properties:
+ 'input':
+ type: object
+ properties:
+ 'mode':
+ type: string
+ 'module-name':
+ type: string
+ 'rpc-name':
+ type: string
+ 'sli-parameter':
+ items:
+ $ref: '#/definitions/parameter-setting'
+ type: array
+ type: object
+
+
+
+
+
+
+ unique_empty_identifier: {}
+
diff --git a/core/sliapi/model/swagger/pom.xml b/core/sliapi/model/swagger/pom.xml
new file mode 100644
index 000000000..db9ddbc42
--- /dev/null
+++ b/core/sliapi/model/swagger/pom.xml
@@ -0,0 +1,222 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>oparent</artifactId>
+ <version>2.1.0-SNAPSHOT</version>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sliapi-model-swagger</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>jar</packaging>
+
+ <name>ccsdk-sli-core :: sliapi :: ${project.artifactId}</name>
+ <description>Generates swagger model from yang model</description>
+ <url>http://wiki.onap.org</url>
+
+ <properties>
+ <api.name>sliapi</api.name>
+ <jackson.version>2.9.5</jackson.version>
+ </properties>
+
+ <dependencies>
+ <!-- This is where the yang comes from -->
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>sliapi-model-yang</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <!-- End this is where the yang comes from -->
+ </dependencies>
+
+ <repositories>
+ <repository>
+ <id>&gt;bintray-yang2swagger-yang2swagge</id>
+ <name>bintray</name>
+ <url>https://dl.bintray.com/yang2swagger/yang2swagger</url>
+ <snapshots>
+ <enabled>false</enabled>
+ </snapshots>
+ </repository>
+ </repositories>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <version>2.10</version>
+ <configuration>
+ <outputDirectory>${project.build.directory}/dependency</outputDirectory>
+ <includes>**\/*.yang</includes>
+ <includeGroupIds>org.opendaylight.mdsal.model,org.opendaylight.mdsal.binding.model.ietf,org.onap.ccsdk.sli.core</includeGroupIds>
+ </configuration>
+ <executions>
+ <execution>
+ <id>unpack-shared-resources</id>
+ <goals>
+ <goal>unpack-dependencies</goal>
+ </goals>
+ <phase>initialize</phase>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <artifactId>maven-antrun-plugin</artifactId>
+ <version>1.8</version>
+ <executions>
+ <execution>
+ <phase>initialize</phase>
+ <goals>
+ <goal>run</goal>
+ </goals>
+ </execution>
+ </executions>
+ <configuration>
+ <tasks>
+ <!-- flatten out structure -->
+ <move todir="${project.build.directory}/dependency" failonerror="false">
+ <fileset dir="${project.build.directory}/dependency"/>
+ <mapper type="flatten"/>
+ </move>
+ <!-- move to yang folder -->
+ <copy todir="${project.build.directory}/yang" failonerror="false">
+ <fileset dir="${project.build.directory}/dependency" includes="**/*.yang"/>
+ <mapper type="flatten"/>
+ </copy>
+ </tasks>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-maven-plugin</artifactId>
+ <version>1.2.3</version>
+ <dependencies>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-core</artifactId>
+ <version>${jackson.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-databind</artifactId>
+ <version>${jackson.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-annotations</artifactId>
+ <version>${jackson.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.module</groupId>
+ <artifactId>jackson-module-jaxb-annotations</artifactId>
+ <version>${jackson.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.jaxrs</groupId>
+ <artifactId>jackson-jaxrs-base</artifactId>
+ <version>${jackson.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.jaxrs</groupId>
+ <artifactId>jackson-jaxrs-json-provider</artifactId>
+ <version>${jackson.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>com.mrv.yangtools</groupId>
+ <artifactId>swagger-maven-plugin</artifactId>
+ <version>1.1.12</version>
+ </dependency>
+ <dependency>
+ <groupId>com.github.romix</groupId>
+ <artifactId>java-concurrent-hash-trie-map</artifactId>
+ <version>0.2.23</version>
+ </dependency>
+ </dependencies>
+ <executions>
+ <execution>
+ <id>yang2swagger-json</id>
+ <goals>
+ <goal>generate-sources</goal>
+ </goals>
+ <configuration>
+ <codeGenerators>
+ <generator>
+ <codeGeneratorClass>com.mrv.yangtools.maven.gen.swagger.MavenSwaggerGenerator</codeGeneratorClass>
+ <outputBaseDir>${project.basedir}/src/main/json</outputBaseDir>
+ <resourceBaseDir>${project.build.directory}/yang</resourceBaseDir>
+ <additionalConfiguration>
+ <api-version>${project.version}</api-version>
+ <base-module>${api.name}</base-module>
+ <swagger-format>json</swagger-format>
+ <path-format>odl</path-format>
+ <use-namespaces>true</use-namespaces>
+ </additionalConfiguration>
+ </generator>
+ </codeGenerators>
+ <inspectDependencies>false</inspectDependencies>
+ <yangFilesRootDir>${project.build.directory}/yang</yangFilesRootDir>
+ </configuration>
+ </execution>
+ <execution>
+ <id>yang2swagger-yaml</id>
+ <goals>
+ <goal>generate-sources</goal>
+ </goals>
+ <configuration>
+ <codeGenerators>
+ <generator>
+ <codeGeneratorClass>com.mrv.yangtools.maven.gen.swagger.MavenSwaggerGenerator</codeGeneratorClass>
+ <outputBaseDir>${project.basedir}/src/main/yaml</outputBaseDir>
+ <resourceBaseDir>${project.build.directory}/yang</resourceBaseDir>
+ <additionalConfiguration>
+ <api-version>${project.version}</api-version>
+ <base-module>${api.name}</base-module>
+ <swagger-format>yaml</swagger-format>
+ <path-format>odl</path-format>
+ <use-namespaces>true</use-namespaces>
+ </additionalConfiguration>
+ </generator>
+ </codeGenerators>
+ <inspectDependencies>false</inspectDependencies>
+ <yangFilesRootDir>${project.build.directory}/yang</yangFilesRootDir>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-source-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>build-helper-maven-plugin</artifactId>
+ <version>1.10</version>
+ <executions>
+ <execution>
+ <id>attach-artifacts</id>
+ <phase>package</phase>
+ <goals>
+ <goal>attach-artifact</goal>
+ </goals>
+ <configuration>
+ <artifacts>
+ <artifact>
+ <file>src/main/json/${api.name}.json</file>
+ <type>json</type>
+ </artifact>
+ <artifact>
+ <file>src/main/yaml/${api.name}.yaml</file>
+ <type>yaml</type>
+ </artifact>
+ </artifacts>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/core/sliapi/model/swagger/src/main/json/sliapi.json b/core/sliapi/model/swagger/src/main/json/sliapi.json
new file mode 100644
index 000000000..b53663201
--- /dev/null
+++ b/core/sliapi/model/swagger/src/main/json/sliapi.json
@@ -0,0 +1 @@
+{"swagger":"2.0","info":{"description":"Defines API to service logic interpreter,This module contains a collection of generally useful derived\nYANG data types.\n\nCopyright (c) 2013 IETF Trust and the persons identified as\nauthors of the code. All rights reserved.\n\nRedistribution and use in source and binary forms, with or\nwithout modification, is permitted pursuant to, and subject\nto the license terms contained in, the Simplified BSD License\nset forth in Section 4.c of the IETF Trust's Legal Provisions\nRelating to IETF Documents\n(http://trustee.ietf.org/license-info).\n\nThis version of this YANG module is part of RFC 6991; see\nthe RFC itself for full legal notices.,This module contains a collection of generally useful derived\nYANG data types for Internet addresses and related things.\n\nCopyright (c) 2013 IETF Trust and the persons identified as\nauthors of the code. All rights reserved.\n\nRedistribution and use in source and binary forms, with or\nwithout modification, is permitted pursuant to, and subject\nto the license terms contained in, the Simplified BSD License\nset forth in Section 4.c of the IETF Trust's Legal Provisions\nRelating to IETF Documents\n(http://trustee.ietf.org/license-info).\n\nThis version of this YANG module is part of RFC 6991; see\nthe RFC itself for full legal notices.","version":"1.1.0-SNAPSHOT","title":"SLI-API,ietf-yang-types,ietf-inet-types API"},"consumes":["application/json","application/xml"],"produces":["application/json","application/xml"],"paths":{"/config/SLI-API:test-results/":{"get":{"tags":["SLI-API"],"description":"returns sli.api.TestResults","parameters":[],"responses":{"400":{"description":"Internal error"},"200":{"description":"sli.api.TestResults","schema":{"originalRef":"#/definitions/sli.api.TestResults","$ref":"#/definitions/sli.api.TestResults"},"responseSchema":{"originalRef":"#/definitions/sli.api.TestResults","$ref":"#/definitions/sli.api.TestResults"}}}},"post":{"tags":["SLI-API"],"description":"creates sli.api.TestResults","parameters":[{"in":"body","name":"sli.api.TestResults.body-param","description":"sli.api.TestResults to be added to list","required":false,"schema":{"originalRef":"#/definitions/sli.api.TestResults","$ref":"#/definitions/sli.api.TestResults"}}],"responses":{"400":{"description":"Internal error"},"201":{"description":"Object created"},"409":{"description":"Object already exists"}}},"put":{"tags":["SLI-API"],"description":"creates or updates sli.api.TestResults","parameters":[{"in":"body","name":"sli.api.TestResults.body-param","description":"sli.api.TestResults to be added or updated","required":false,"schema":{"originalRef":"#/definitions/sli.api.TestResults","$ref":"#/definitions/sli.api.TestResults"}}],"responses":{"400":{"description":"Internal error"},"201":{"description":"Object created"},"204":{"description":"Object modified"}}},"delete":{"tags":["SLI-API"],"description":"removes sli.api.TestResults","parameters":[],"responses":{"400":{"description":"Internal error"},"204":{"description":"Object deleted"}}}},"/config/SLI-API:test-results/SLI-API:test-result/":{"post":{"description":"creates sli.api.testresults.TestResult","parameters":[{"in":"body","name":"sli.api.testresults.TestResult.body-param","description":"sli.api.testresults.TestResult to be added to list","required":false,"schema":{"originalRef":"#/definitions/sli.api.testresults.TestResult","$ref":"#/definitions/sli.api.testresults.TestResult"}}],"responses":{"400":{"description":"Internal error"},"201":{"description":"Object created"},"409":{"description":"Object already exists"}}}},"/config/SLI-API:test-results/SLI-API:test-result/{test-identifier}/":{"get":{"tags":["SLI-API"],"description":"returns sli.api.testresults.TestResult","parameters":[{"name":"test-identifier","in":"path","description":"Id of test-result","required":true,"type":"string"}],"responses":{"400":{"description":"Internal error"},"200":{"description":"sli.api.testresults.TestResult","schema":{"originalRef":"#/definitions/sli.api.testresults.TestResult","$ref":"#/definitions/sli.api.testresults.TestResult"},"responseSchema":{"originalRef":"#/definitions/sli.api.testresults.TestResult","$ref":"#/definitions/sli.api.testresults.TestResult"}}}},"post":{"tags":["SLI-API"],"description":"creates sli.api.testresults.TestResult","parameters":[{"name":"test-identifier","in":"path","description":"Id of test-result","required":true,"type":"string"},{"in":"body","name":"sli.api.testresults.TestResult.body-param","description":"sli.api.testresults.TestResult to be added to list","required":false,"schema":{"originalRef":"#/definitions/sli.api.testresults.TestResult","$ref":"#/definitions/sli.api.testresults.TestResult"}}],"responses":{"400":{"description":"Internal error"},"201":{"description":"Object created"},"409":{"description":"Object already exists"}}},"put":{"tags":["SLI-API"],"description":"creates or updates sli.api.testresults.TestResult","parameters":[{"name":"test-identifier","in":"path","description":"Id of test-result","required":true,"type":"string"},{"in":"body","name":"sli.api.testresults.TestResult.body-param","description":"sli.api.testresults.TestResult to be added or updated","required":false,"schema":{"originalRef":"#/definitions/sli.api.testresults.TestResult","$ref":"#/definitions/sli.api.testresults.TestResult"}}],"responses":{"400":{"description":"Internal error"},"201":{"description":"Object created"},"204":{"description":"Object modified"}}},"delete":{"tags":["SLI-API"],"description":"removes sli.api.testresults.TestResult","parameters":[{"name":"test-identifier","in":"path","description":"Id of test-result","required":true,"type":"string"}],"responses":{"400":{"description":"Internal error"},"204":{"description":"Object deleted"}}}},"/operational/SLI-API:test-results/":{"get":{"tags":["SLI-API"],"description":"returns sli.api.TestResults","parameters":[],"responses":{"400":{"description":"Internal error"},"200":{"description":"sli.api.TestResults","schema":{"originalRef":"#/definitions/sli.api.TestResults","$ref":"#/definitions/sli.api.TestResults"},"responseSchema":{"originalRef":"#/definitions/sli.api.TestResults","$ref":"#/definitions/sli.api.TestResults"}}}}},"/operational/SLI-API:test-results/SLI-API:test-result/{test-identifier}/":{"get":{"tags":["SLI-API"],"description":"returns sli.api.testresults.TestResult","parameters":[{"name":"test-identifier","in":"path","description":"Id of test-result","required":true,"type":"string"}],"responses":{"400":{"description":"Internal error"},"200":{"description":"sli.api.testresults.TestResult","schema":{"originalRef":"#/definitions/sli.api.testresults.TestResult","$ref":"#/definitions/sli.api.testresults.TestResult"},"responseSchema":{"originalRef":"#/definitions/sli.api.testresults.TestResult","$ref":"#/definitions/sli.api.testresults.TestResult"}}}}},"/operations/SLI-API:execute-graph/":{"post":{"tags":["SLI-API"],"parameters":[{"in":"body","name":"sli.api.executegraph.Input.body-param","required":false,"schema":{"properties":{"input":{"originalRef":"#/definitions/sli.api.executegraph.Input","$ref":"#/definitions/sli.api.executegraph.Input"}}}}],"responses":{"400":{"description":"Internal error"},"200":{"description":"Correct response","schema":{"originalRef":"#/definitions/sli.api.ExecuteGraph","$ref":"#/definitions/sli.api.ExecuteGraph"},"responseSchema":{"originalRef":"#/definitions/sli.api.ExecuteGraph","$ref":"#/definitions/sli.api.ExecuteGraph"}},"201":{"description":"No response"}}}},"/operations/SLI-API:healthcheck/":{"post":{"tags":["SLI-API"],"parameters":[],"responses":{"400":{"description":"Internal error"},"200":{"description":"Correct response","schema":{"originalRef":"#/definitions/sli.api.Healthcheck","$ref":"#/definitions/sli.api.Healthcheck"},"responseSchema":{"originalRef":"#/definitions/sli.api.Healthcheck","$ref":"#/definitions/sli.api.Healthcheck"}},"201":{"description":"No response"}}}},"/operations/SLI-API:vlbcheck/":{"post":{"tags":["SLI-API"],"parameters":[],"responses":{"400":{"description":"Internal error"},"200":{"description":"Correct response","schema":{"originalRef":"#/definitions/sli.api.Vlbcheck","$ref":"#/definitions/sli.api.Vlbcheck"},"responseSchema":{"originalRef":"#/definitions/sli.api.Vlbcheck","$ref":"#/definitions/sli.api.Vlbcheck"}},"201":{"description":"No response"}}}}},"definitions":{"sli.api.ExecuteGraph":{"type":"object","properties":{"output":{"originalRef":"#/definitions/sli.api.ResponseFields","$ref":"#/definitions/sli.api.ResponseFields"}}},"sli.api.Healthcheck":{"type":"object","properties":{"output":{"originalRef":"#/definitions/sli.api.ResponseFields","$ref":"#/definitions/sli.api.ResponseFields"}}},"sli.api.ModeEnumeration":{"type":"string","enum":["sync","async"]},"sli.api.ParameterSetting":{"type":"object","properties":{"string-value":{"type":"string"},"boolean-value":{"type":"boolean"},"parameter-name":{"type":"string","description":"Parameter name"},"int-value":{"type":"integer","format":"int32"}}},"sli.api.ResponseFields":{"type":"object","properties":{"response-code":{"type":"string"},"response-message":{"type":"string"},"context-memory-json":{"type":"string"},"ack-final-indicator":{"type":"string"}}},"sli.api.TestResults":{"type":"object","properties":{"test-result":{"type":"array","items":{"originalRef":"#/definitions/sli.api.testresults.TestResult","$ref":"#/definitions/sli.api.testresults.TestResult"}}}},"sli.api.Vlbcheck":{"type":"object","properties":{"output":{"originalRef":"#/definitions/sli.api.ResponseFields","$ref":"#/definitions/sli.api.ResponseFields"}}},"sli.api.executegraph.Input":{"type":"object","properties":{"mode":{"originalRef":"#/definitions/sli.api.ModeEnumeration","$ref":"#/definitions/sli.api.ModeEnumeration"},"module-name":{"type":"string"},"sli-parameter":{"type":"array","items":{"originalRef":"#/definitions/sli.api.ParameterSetting","$ref":"#/definitions/sli.api.ParameterSetting"}},"rpc-name":{"type":"string"}}},"sli.api.testresults.TestResult":{"type":"object","properties":{"results":{"type":"array","items":{"type":"string"}},"test-identifier":{"type":"string"}}}}} \ No newline at end of file
diff --git a/core/sliapi/model/swagger/src/main/yaml/sliapi.yaml b/core/sliapi/model/swagger/src/main/yaml/sliapi.yaml
new file mode 100644
index 000000000..b1a63be5d
--- /dev/null
+++ b/core/sliapi/model/swagger/src/main/yaml/sliapi.yaml
@@ -0,0 +1,378 @@
+---
+swagger: "2.0"
+info:
+ description: "Defines API to service logic interpreter,This module contains a collection\
+ \ of generally useful derived\nYANG data types.\n\nCopyright (c) 2013 IETF Trust\
+ \ and the persons identified as\nauthors of the code. All rights reserved.\n\n\
+ Redistribution and use in source and binary forms, with or\nwithout modification,\
+ \ is permitted pursuant to, and subject\nto the license terms contained in, the\
+ \ Simplified BSD License\nset forth in Section 4.c of the IETF Trust's Legal Provisions\n\
+ Relating to IETF Documents\n(http://trustee.ietf.org/license-info).\n\nThis version\
+ \ of this YANG module is part of RFC 6991; see\nthe RFC itself for full legal\
+ \ notices.,This module contains a collection of generally useful derived\nYANG\
+ \ data types for Internet addresses and related things.\n\nCopyright (c) 2013\
+ \ IETF Trust and the persons identified as\nauthors of the code. All rights reserved.\n\
+ \nRedistribution and use in source and binary forms, with or\nwithout modification,\
+ \ is permitted pursuant to, and subject\nto the license terms contained in, the\
+ \ Simplified BSD License\nset forth in Section 4.c of the IETF Trust's Legal Provisions\n\
+ Relating to IETF Documents\n(http://trustee.ietf.org/license-info).\n\nThis version\
+ \ of this YANG module is part of RFC 6991; see\nthe RFC itself for full legal\
+ \ notices."
+ version: "1.1.0-SNAPSHOT"
+ title: "SLI-API,ietf-yang-types,ietf-inet-types API"
+consumes:
+- "application/json"
+- "application/xml"
+produces:
+- "application/json"
+- "application/xml"
+paths:
+ /config/SLI-API:test-results/:
+ get:
+ tags:
+ - "SLI-API"
+ description: "returns sli.api.TestResults"
+ parameters: []
+ responses:
+ 400:
+ description: "Internal error"
+ 200:
+ description: "sli.api.TestResults"
+ schema:
+ originalRef: "#/definitions/sli.api.TestResults"
+ $ref: "#/definitions/sli.api.TestResults"
+ responseSchema:
+ originalRef: "#/definitions/sli.api.TestResults"
+ $ref: "#/definitions/sli.api.TestResults"
+ post:
+ tags:
+ - "SLI-API"
+ description: "creates sli.api.TestResults"
+ parameters:
+ - in: "body"
+ name: "sli.api.TestResults.body-param"
+ description: "sli.api.TestResults to be added to list"
+ required: false
+ schema:
+ originalRef: "#/definitions/sli.api.TestResults"
+ $ref: "#/definitions/sli.api.TestResults"
+ responses:
+ 400:
+ description: "Internal error"
+ 201:
+ description: "Object created"
+ 409:
+ description: "Object already exists"
+ put:
+ tags:
+ - "SLI-API"
+ description: "creates or updates sli.api.TestResults"
+ parameters:
+ - in: "body"
+ name: "sli.api.TestResults.body-param"
+ description: "sli.api.TestResults to be added or updated"
+ required: false
+ schema:
+ originalRef: "#/definitions/sli.api.TestResults"
+ $ref: "#/definitions/sli.api.TestResults"
+ responses:
+ 400:
+ description: "Internal error"
+ 201:
+ description: "Object created"
+ 204:
+ description: "Object modified"
+ delete:
+ tags:
+ - "SLI-API"
+ description: "removes sli.api.TestResults"
+ parameters: []
+ responses:
+ 400:
+ description: "Internal error"
+ 204:
+ description: "Object deleted"
+ /config/SLI-API:test-results/SLI-API:test-result/:
+ post:
+ description: "creates sli.api.testresults.TestResult"
+ parameters:
+ - in: "body"
+ name: "sli.api.testresults.TestResult.body-param"
+ description: "sli.api.testresults.TestResult to be added to list"
+ required: false
+ schema:
+ originalRef: "#/definitions/sli.api.testresults.TestResult"
+ $ref: "#/definitions/sli.api.testresults.TestResult"
+ responses:
+ 400:
+ description: "Internal error"
+ 201:
+ description: "Object created"
+ 409:
+ description: "Object already exists"
+ /config/SLI-API:test-results/SLI-API:test-result/{test-identifier}/:
+ get:
+ tags:
+ - "SLI-API"
+ description: "returns sli.api.testresults.TestResult"
+ parameters:
+ - name: "test-identifier"
+ in: "path"
+ description: "Id of test-result"
+ required: true
+ type: "string"
+ responses:
+ 400:
+ description: "Internal error"
+ 200:
+ description: "sli.api.testresults.TestResult"
+ schema:
+ originalRef: "#/definitions/sli.api.testresults.TestResult"
+ $ref: "#/definitions/sli.api.testresults.TestResult"
+ responseSchema:
+ originalRef: "#/definitions/sli.api.testresults.TestResult"
+ $ref: "#/definitions/sli.api.testresults.TestResult"
+ post:
+ tags:
+ - "SLI-API"
+ description: "creates sli.api.testresults.TestResult"
+ parameters:
+ - name: "test-identifier"
+ in: "path"
+ description: "Id of test-result"
+ required: true
+ type: "string"
+ - in: "body"
+ name: "sli.api.testresults.TestResult.body-param"
+ description: "sli.api.testresults.TestResult to be added to list"
+ required: false
+ schema:
+ originalRef: "#/definitions/sli.api.testresults.TestResult"
+ $ref: "#/definitions/sli.api.testresults.TestResult"
+ responses:
+ 400:
+ description: "Internal error"
+ 201:
+ description: "Object created"
+ 409:
+ description: "Object already exists"
+ put:
+ tags:
+ - "SLI-API"
+ description: "creates or updates sli.api.testresults.TestResult"
+ parameters:
+ - name: "test-identifier"
+ in: "path"
+ description: "Id of test-result"
+ required: true
+ type: "string"
+ - in: "body"
+ name: "sli.api.testresults.TestResult.body-param"
+ description: "sli.api.testresults.TestResult to be added or updated"
+ required: false
+ schema:
+ originalRef: "#/definitions/sli.api.testresults.TestResult"
+ $ref: "#/definitions/sli.api.testresults.TestResult"
+ responses:
+ 400:
+ description: "Internal error"
+ 201:
+ description: "Object created"
+ 204:
+ description: "Object modified"
+ delete:
+ tags:
+ - "SLI-API"
+ description: "removes sli.api.testresults.TestResult"
+ parameters:
+ - name: "test-identifier"
+ in: "path"
+ description: "Id of test-result"
+ required: true
+ type: "string"
+ responses:
+ 400:
+ description: "Internal error"
+ 204:
+ description: "Object deleted"
+ /operational/SLI-API:test-results/:
+ get:
+ tags:
+ - "SLI-API"
+ description: "returns sli.api.TestResults"
+ parameters: []
+ responses:
+ 400:
+ description: "Internal error"
+ 200:
+ description: "sli.api.TestResults"
+ schema:
+ originalRef: "#/definitions/sli.api.TestResults"
+ $ref: "#/definitions/sli.api.TestResults"
+ responseSchema:
+ originalRef: "#/definitions/sli.api.TestResults"
+ $ref: "#/definitions/sli.api.TestResults"
+ /operational/SLI-API:test-results/SLI-API:test-result/{test-identifier}/:
+ get:
+ tags:
+ - "SLI-API"
+ description: "returns sli.api.testresults.TestResult"
+ parameters:
+ - name: "test-identifier"
+ in: "path"
+ description: "Id of test-result"
+ required: true
+ type: "string"
+ responses:
+ 400:
+ description: "Internal error"
+ 200:
+ description: "sli.api.testresults.TestResult"
+ schema:
+ originalRef: "#/definitions/sli.api.testresults.TestResult"
+ $ref: "#/definitions/sli.api.testresults.TestResult"
+ responseSchema:
+ originalRef: "#/definitions/sli.api.testresults.TestResult"
+ $ref: "#/definitions/sli.api.testresults.TestResult"
+ /operations/SLI-API:execute-graph/:
+ post:
+ tags:
+ - "SLI-API"
+ parameters:
+ - in: "body"
+ name: "sli.api.executegraph.Input.body-param"
+ required: false
+ schema:
+ properties:
+ input:
+ originalRef: "#/definitions/sli.api.executegraph.Input"
+ $ref: "#/definitions/sli.api.executegraph.Input"
+ responses:
+ 400:
+ description: "Internal error"
+ 200:
+ description: "Correct response"
+ schema:
+ originalRef: "#/definitions/sli.api.ExecuteGraph"
+ $ref: "#/definitions/sli.api.ExecuteGraph"
+ responseSchema:
+ originalRef: "#/definitions/sli.api.ExecuteGraph"
+ $ref: "#/definitions/sli.api.ExecuteGraph"
+ 201:
+ description: "No response"
+ /operations/SLI-API:healthcheck/:
+ post:
+ tags:
+ - "SLI-API"
+ parameters: []
+ responses:
+ 400:
+ description: "Internal error"
+ 200:
+ description: "Correct response"
+ schema:
+ originalRef: "#/definitions/sli.api.Healthcheck"
+ $ref: "#/definitions/sli.api.Healthcheck"
+ responseSchema:
+ originalRef: "#/definitions/sli.api.Healthcheck"
+ $ref: "#/definitions/sli.api.Healthcheck"
+ 201:
+ description: "No response"
+ /operations/SLI-API:vlbcheck/:
+ post:
+ tags:
+ - "SLI-API"
+ parameters: []
+ responses:
+ 400:
+ description: "Internal error"
+ 200:
+ description: "Correct response"
+ schema:
+ originalRef: "#/definitions/sli.api.Vlbcheck"
+ $ref: "#/definitions/sli.api.Vlbcheck"
+ responseSchema:
+ originalRef: "#/definitions/sli.api.Vlbcheck"
+ $ref: "#/definitions/sli.api.Vlbcheck"
+ 201:
+ description: "No response"
+definitions:
+ sli.api.ExecuteGraph:
+ type: "object"
+ properties:
+ output:
+ originalRef: "#/definitions/sli.api.ResponseFields"
+ $ref: "#/definitions/sli.api.ResponseFields"
+ sli.api.Healthcheck:
+ type: "object"
+ properties:
+ output:
+ originalRef: "#/definitions/sli.api.ResponseFields"
+ $ref: "#/definitions/sli.api.ResponseFields"
+ sli.api.ModeEnumeration:
+ type: "string"
+ enum:
+ - "sync"
+ - "async"
+ sli.api.ParameterSetting:
+ type: "object"
+ properties:
+ string-value:
+ type: "string"
+ boolean-value:
+ type: "boolean"
+ parameter-name:
+ type: "string"
+ description: "Parameter name"
+ int-value:
+ type: "integer"
+ format: "int32"
+ sli.api.ResponseFields:
+ type: "object"
+ properties:
+ response-code:
+ type: "string"
+ response-message:
+ type: "string"
+ context-memory-json:
+ type: "string"
+ ack-final-indicator:
+ type: "string"
+ sli.api.TestResults:
+ type: "object"
+ properties:
+ test-result:
+ type: "array"
+ items:
+ originalRef: "#/definitions/sli.api.testresults.TestResult"
+ $ref: "#/definitions/sli.api.testresults.TestResult"
+ sli.api.Vlbcheck:
+ type: "object"
+ properties:
+ output:
+ originalRef: "#/definitions/sli.api.ResponseFields"
+ $ref: "#/definitions/sli.api.ResponseFields"
+ sli.api.executegraph.Input:
+ type: "object"
+ properties:
+ mode:
+ originalRef: "#/definitions/sli.api.ModeEnumeration"
+ $ref: "#/definitions/sli.api.ModeEnumeration"
+ module-name:
+ type: "string"
+ sli-parameter:
+ type: "array"
+ items:
+ originalRef: "#/definitions/sli.api.ParameterSetting"
+ $ref: "#/definitions/sli.api.ParameterSetting"
+ rpc-name:
+ type: "string"
+ sli.api.testresults.TestResult:
+ type: "object"
+ properties:
+ results:
+ type: "array"
+ items:
+ type: "string"
+ test-identifier:
+ type: "string"
diff --git a/core/sliapi/model/yang/pom.xml b/core/sliapi/model/yang/pom.xml
new file mode 100755
index 000000000..4d35f025c
--- /dev/null
+++ b/core/sliapi/model/yang/pom.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>binding-parent</artifactId>
+ <version>2.1.0-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sliapi-model-yang</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>bundle</packaging>
+
+ <name>ccsdk-sli-core :: sliapi :: ${project.artifactId}</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.mdsal.binding.model.ietf</groupId>
+ <artifactId>rfc6991</artifactId>
+ </dependency>
+
+
+ </dependencies>
+</project>
diff --git a/core/sliapi/model/yang/src/main/resources/sli-api.20161110.json b/core/sliapi/model/yang/src/main/resources/sli-api.20161110.json
new file mode 100644
index 000000000..1c6cdabfe
--- /dev/null
+++ b/core/sliapi/model/yang/src/main/resources/sli-api.20161110.json
@@ -0,0 +1,554 @@
+{
+ "swagger": "2.0",
+ "info": {
+ "version": "1.0.0"
+ },
+ "basePath": "/restconf",
+ "paths": {
+ "/config": {
+ "post": {
+ "consumes": [
+ "application/json",
+ "application/xml"
+ ],
+ "produces": [
+ "application/json",
+ "application/xml"
+ ],
+ "parameters": [
+ {
+ "in": "body",
+ "name": "**(config)test-results",
+ "required": false,
+ "schema": {
+ "$ref": "#/definitions/SLI-API(config)test-results-TOP"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "No response was specified",
+ "schema": {
+ "$ref": "#/definitions/(config)SLI-API_modulePOST"
+ }
+ }
+ },
+ "description": "Defines API to service logic interpreter",
+ "operationId": "POST-SLI-API_module"
+ }
+ },
+ "/config/SLI-API:test-results": {
+ "delete": {
+ "produces": [
+ "application/json",
+ "application/xml"
+ ],
+ "responses": {
+ "200": {
+ "description": "No response was specified"
+ }
+ },
+ "description": "Test results",
+ "operationId": "DELETE-test-results"
+ },
+ "get": {
+ "produces": [
+ "application/json",
+ "application/xml"
+ ],
+ "responses": {
+ "200": {
+ "description": "No response was specified",
+ "schema": {
+ "$ref": "#/definitions/(config)test-results"
+ }
+ }
+ },
+ "description": "Test results",
+ "operationId": "GET-test-results"
+ },
+ "post": {
+ "consumes": [
+ "application/json",
+ "application/xml"
+ ],
+ "produces": [
+ "application/json",
+ "application/xml"
+ ],
+ "parameters": [
+ {
+ "in": "body",
+ "name": "**(config)test-result",
+ "required": false,
+ "schema": {
+ "$ref": "#/definitions/SLI-API/test-results(config)test-result-TOP"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "No response was specified",
+ "schema": {
+ "$ref": "#/definitions/(config)test-resultsPOST"
+ }
+ }
+ },
+ "description": "Test results",
+ "operationId": "POST-test-results"
+ },
+ "put": {
+ "consumes": [
+ "application/json",
+ "application/xml"
+ ],
+ "produces": [
+ "application/json",
+ "application/xml"
+ ],
+ "parameters": [
+ {
+ "in": "body",
+ "name": "(config)test-results",
+ "required": false,
+ "schema": {
+ "$ref": "#/definitions/SLI-API(config)test-results-TOP"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "No response was specified",
+ "schema": {
+ "$ref": "#/definitions/SLI-API(config)test-results-TOP"
+ }
+ }
+ },
+ "description": "Test results",
+ "operationId": "PUT-test-results"
+ }
+ },
+ "/config/SLI-API:test-results/test-result/{test-identifier}": {
+ "delete": {
+ "produces": [
+ "application/json",
+ "application/xml"
+ ],
+ "parameters": [
+ {
+ "in": "path",
+ "name": "test-identifier",
+ "required": true,
+ "type": "string"
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "No response was specified"
+ }
+ },
+ "operationId": "DELETE-test-result"
+ },
+ "get": {
+ "produces": [
+ "application/json",
+ "application/xml"
+ ],
+ "parameters": [
+ {
+ "in": "path",
+ "name": "test-identifier",
+ "required": true,
+ "type": "string"
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "No response was specified",
+ "schema": {
+ "$ref": "#/definitions/(config)test-result"
+ }
+ }
+ },
+ "operationId": "GET-test-result"
+ },
+ "put": {
+ "consumes": [
+ "application/json",
+ "application/xml"
+ ],
+ "produces": [
+ "application/json",
+ "application/xml"
+ ],
+ "parameters": [
+ {
+ "in": "path",
+ "name": "test-identifier",
+ "required": true,
+ "type": "string"
+ },
+ {
+ "in": "body",
+ "name": "(config)test-result",
+ "required": false,
+ "schema": {
+ "$ref": "#/definitions/SLI-API/test-results(config)test-result-TOP"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "No response was specified",
+ "schema": {
+ "$ref": "#/definitions/SLI-API/test-results(config)test-result-TOP"
+ }
+ }
+ },
+ "operationId": "PUT-test-result"
+ }
+ },
+ "/operational/SLI-API:test-results": {
+ "get": {
+ "produces": [
+ "application/json",
+ "application/xml"
+ ],
+ "responses": {
+ "200": {
+ "description": "No response was specified",
+ "schema": {
+ "$ref": "#/definitions/(operational)test-results"
+ }
+ }
+ },
+ "description": "Test results",
+ "operationId": "GET-test-results"
+ }
+ },
+ "/operations/SLI-API:execute-graph": {
+ "post": {
+ "consumes": [
+ "application/json",
+ "application/xml"
+ ],
+ "produces": [
+ "application/json",
+ "application/xml"
+ ],
+ "parameters": [
+ {
+ "in": "body",
+ "name": "body",
+ "required": false,
+ "schema": {
+ "$ref": "#/definitions/(execute-graph)input-TOP"
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "No response was specified",
+ "schema": {
+ "$ref": "#/definitions/(execute-graph)output-TOP"
+ }
+ }
+ },
+ "description": " Method to add a new parameter.",
+ "operationId": "execute-graph"
+ }
+ },
+ "/operations/SLI-API:healthcheck": {
+ "post": {
+ "produces": [
+ "application/json",
+ "application/xml"
+ ],
+ "responses": {
+ "200": {
+ "description": "No response was specified",
+ "schema": {
+ "$ref": "#/definitions/(healthcheck)output-TOP"
+ }
+ }
+ },
+ "operationId": "healthcheck"
+ }
+ },
+ "/operations/SLI-API:vlbcheck": {
+ "post": {
+ "produces": [
+ "application/json",
+ "application/xml"
+ ],
+ "responses": {
+ "200": {
+ "description": "No response was specified",
+ "schema": {
+ "$ref": "#/definitions/(vlbcheck)output-TOP"
+ }
+ }
+ },
+ "operationId": "vlbcheck"
+ }
+ }
+ },
+ "definitions": {
+ "(config)SLI-API_modulePOST": {
+ "properties": {
+ "test-results": {
+ "items": {
+ "$ref": "#/definitions/SLI-API(config)test-results"
+ },
+ "type": "object"
+ }
+ },
+ "type": "object"
+ },
+ "(config)sli-parameterPOST": {
+ "properties": {
+ "boolean-value": {
+ "$ref": "#/definitions/Optional.empty"
+ },
+ "int-value": {
+ "$ref": "#/definitions/Optional.empty"
+ },
+ "parameter-name": {
+ "$ref": "#/definitions/Optional.empty",
+ "description": "Parameter name"
+ },
+ "string-value": {
+ "$ref": "#/definitions/Optional.empty"
+ }
+ },
+ "type": "object"
+ },
+ "(config)test-resultPOST": {
+ "properties": {
+ "test-identifier": {
+ "$ref": "#/definitions/Optional.empty"
+ }
+ },
+ "type": "object"
+ },
+ "(config)test-resultsPOST": {
+ "properties": {
+ "test-result": {
+ "items": {
+ "$ref": "#/definitions/SLI-API/test-results(config)test-result"
+ },
+ "type": "array"
+ }
+ },
+ "type": "object"
+ },
+ "(execute-graph)input": {
+ "properties": {
+ "SLI-API:mode": {
+ "$ref": "#/definitions/Optional.empty"
+ },
+ "SLI-API:module-name": {
+ "$ref": "#/definitions/Optional.empty"
+ },
+ "SLI-API:rpc-name": {
+ "$ref": "#/definitions/Optional.empty"
+ },
+ "SLI-API:sli-parameter": {
+ "items": {
+ "$ref": "#/definitions/SLI-API(config)sli-parameter"
+ },
+ "type": "array"
+ }
+ },
+ "type": "object"
+ },
+ "(execute-graph)input-TOP": {
+ "properties": {
+ "SLI-API:input": {
+ "items": {
+ "$ref": "#/definitions/(execute-graph)input"
+ },
+ "type": "object"
+ }
+ },
+ "type": "object"
+ },
+ "(execute-graph)output": {
+ "properties": {
+ "SLI-API:ack-final-indicator": {
+ "$ref": "#/definitions/Optional.empty"
+ },
+ "SLI-API:context-memory-json": {
+ "$ref": "#/definitions/Optional.empty"
+ },
+ "SLI-API:response-code": {
+ "$ref": "#/definitions/Optional.empty"
+ },
+ "SLI-API:response-message": {
+ "$ref": "#/definitions/Optional.empty"
+ }
+ },
+ "type": "object"
+ },
+ "(execute-graph)output-TOP": {
+ "properties": {
+ "SLI-API:output": {
+ "items": {
+ "$ref": "#/definitions/(execute-graph)output"
+ },
+ "type": "object"
+ }
+ },
+ "type": "object"
+ },
+ "(healthcheck)output": {
+ "properties": {
+ "SLI-API:ack-final-indicator": {
+ "$ref": "#/definitions/Optional.empty"
+ },
+ "SLI-API:context-memory-json": {
+ "$ref": "#/definitions/Optional.empty"
+ },
+ "SLI-API:response-code": {
+ "$ref": "#/definitions/Optional.empty"
+ },
+ "SLI-API:response-message": {
+ "$ref": "#/definitions/Optional.empty"
+ }
+ },
+ "type": "object"
+ },
+ "(healthcheck)output-TOP": {
+ "properties": {
+ "SLI-API:output": {
+ "items": {
+ "$ref": "#/definitions/(healthcheck)output"
+ },
+ "type": "object"
+ }
+ },
+ "type": "object"
+ },
+ "(vlbcheck)output": {
+ "properties": {
+ "SLI-API:ack-final-indicator": {
+ "$ref": "#/definitions/Optional.empty"
+ },
+ "SLI-API:context-memory-json": {
+ "$ref": "#/definitions/Optional.empty"
+ },
+ "SLI-API:response-code": {
+ "$ref": "#/definitions/Optional.empty"
+ },
+ "SLI-API:response-message": {
+ "$ref": "#/definitions/Optional.empty"
+ }
+ },
+ "type": "object"
+ },
+ "(vlbcheck)output-TOP": {
+ "properties": {
+ "SLI-API:output": {
+ "items": {
+ "$ref": "#/definitions/(vlbcheck)output"
+ },
+ "type": "object"
+ }
+ },
+ "type": "object"
+ },
+ "SLI-API(config)sli-parameter": {
+ "properties": {
+ "SLI-API:boolean-value": {
+ "$ref": "#/definitions/Optional.empty"
+ },
+ "SLI-API:int-value": {
+ "$ref": "#/definitions/Optional.empty"
+ },
+ "SLI-API:parameter-name": {
+ "$ref": "#/definitions/Optional.empty",
+ "description": "Parameter name"
+ },
+ "SLI-API:string-value": {
+ "$ref": "#/definitions/Optional.empty"
+ }
+ },
+ "type": "object"
+ },
+ "SLI-API(config)sli-parameter-TOP": {
+ "properties": {
+ "SLI-API:sli-parameter": {
+ "items": {
+ "$ref": "#/definitions/SLI-API(config)sli-parameter"
+ },
+ "type": "array"
+ }
+ },
+ "type": "object"
+ },
+ "SLI-API(config)test-results": {
+ "properties": {
+ "SLI-API:test-result": {
+ "items": {
+ "$ref": "#/definitions/SLI-API/test-results(config)test-result"
+ },
+ "type": "array"
+ }
+ },
+ "type": "object"
+ },
+ "SLI-API(config)test-results-TOP": {
+ "properties": {
+ "SLI-API:test-results": {
+ "description": "Test results",
+ "items": {
+ "$ref": "#/definitions/SLI-API(config)test-results"
+ },
+ "type": "object"
+ }
+ },
+ "type": "object"
+ },
+ "SLI-API(operational)test-results": {
+ "type": "object"
+ },
+ "SLI-API(operational)test-results-TOP": {
+ "properties": {
+ "SLI-API:test-results": {
+ "description": "Test results",
+ "items": {
+ "$ref": "#/definitions/SLI-API(operational)test-results"
+ },
+ "type": "object"
+ }
+ },
+ "type": "object"
+ },
+ "SLI-API/test-results(config)test-result": {
+ "properties": {
+ "SLI-API:results": {
+ "items": {
+ "$ref": "#/definitions/Optional.empty"
+ },
+ "type": "array"
+ },
+ "SLI-API:test-identifier": {
+ "$ref": "#/definitions/Optional.empty"
+ }
+ },
+ "type": "object"
+ },
+ "SLI-API/test-results(config)test-result-TOP": {
+ "properties": {
+ "SLI-API:test-result": {
+ "items": {
+ "$ref": "#/definitions/SLI-API/test-results(config)test-result"
+ },
+ "type": "array"
+ }
+ },
+ "type": "object"
+ },
+ "unique_empty_identifier": {}
+ }
+}
diff --git a/core/sliapi/model/yang/src/main/resources/sli-api.20161110.yaml b/core/sliapi/model/yang/src/main/resources/sli-api.20161110.yaml
new file mode 100644
index 000000000..3420c66b5
--- /dev/null
+++ b/core/sliapi/model/yang/src/main/resources/sli-api.20161110.yaml
@@ -0,0 +1,254 @@
+---
+swagger: '2.0'
+info:
+ version: 1.0.0
+ title: "SLI API"
+basePath: '/restconf'
+schemes:
+ - http
+ - https
+paths:
+ '/restconf/config/SLI-API:test-results':
+ delete:
+ produces:
+ - application/json
+ - application/xml
+ responses:
+ '200':
+ description: No response was specified
+ description: Test results
+ operationId: delete-test-results
+ get:
+ produces:
+ - application/json
+ - application/xml
+ responses:
+ '200':
+ description: No response was specified
+ schema:
+ $ref: '#/definitions/test-results'
+ description: Test results
+ operationId: get-test-results
+ post:
+ consumes:
+ - application/json
+ - application/xml
+ produces:
+ - application/json
+ - application/xml
+ parameters:
+ - in: body
+ name: testResults
+ required: false
+ schema:
+ $ref: '#/definitions/test-results'
+ responses:
+ '200':
+ description: No response was specified
+ schema:
+ $ref: '#/definitions/test-results'
+ description: Test results
+ operationId: post-test-results
+ put:
+ consumes:
+ - application/json
+ - application/xml
+ produces:
+ - application/json
+ - application/xml
+ parameters:
+ - in: body
+ name: testResults
+ required: false
+ schema:
+ $ref: '#/definitions/test-results'
+ responses:
+ '200':
+ description: No response was specified
+ schema:
+ $ref: '#/definitions/test-results'
+ description: Test results
+ operationId: put-test-results
+
+ '/restconf/config/SLI-API:test-results/test-result/{test-identifier}':
+ delete:
+ produces:
+ - application/json
+ - application/xml
+ parameters:
+ - in: path
+ name: test-identifier
+ required: true
+ type: string
+ responses:
+ '200':
+ description: No response was specified
+ operationId: delete-test-result
+ get:
+ produces:
+ - application/json
+ - application/xml
+ parameters:
+ - in: path
+ name: test-identifier
+ required: true
+ type: string
+ responses:
+ '200':
+ description: No response was specified
+ schema:
+ $ref: '#/definitions/test-result'
+ operationId: get-test-result
+ put:
+ consumes:
+ - application/json
+ - application/xml
+ produces:
+ - application/json
+ - application/xml
+ parameters:
+ - in: path
+ name: test-identifier
+ required: true
+ type: string
+ - in: body
+ name: testResult
+ required: false
+ schema:
+ $ref: '#/definitions/test-result'
+ responses:
+ '200':
+ description: No response was specified
+ schema:
+ $ref: '#/definitions/test-result'
+ operationId: PUT-test-result
+
+ '/restconf/operational/SLI-API:test-results':
+ get:
+ produces:
+ - application/json
+ - application/xml
+ responses:
+ '200':
+ description: No response was specified
+ schema:
+ $ref: '#/definitions/test-results'
+ description: Test results
+ operationId: GET-test-results
+ '/restconf/operations/SLI-API:execute-graph':
+ post:
+ consumes:
+ - application/json
+ - application/xml
+ produces:
+ - application/json
+ - application/xml
+ parameters:
+ - in: body
+ name: executeGraphInput
+ required: false
+ schema:
+ $ref: '#/definitions/execute-graph-input'
+ responses:
+ '200':
+ description: No response was specified
+ schema:
+ $ref: '#/definitions/response-fields'
+ description: ' Method to add a new parameter.'
+ operationId: execute-graph
+ '/restconf/operations/SLI-API:healthcheck':
+ post:
+ consumes:
+ - application/json
+ - application/xml
+ produces:
+ - application/json
+ - application/xml
+ responses:
+ '200':
+ description: No response was specified
+ schema:
+ $ref: '#/definitions/response-fields'
+ operationId: healthcheck
+ '/restconf/operations/SLI-API:vlbcheck':
+ post:
+ consumes:
+ - application/json
+ - application/xml
+ produces:
+ - application/json
+ - application/xml
+ responses:
+ '200':
+ description: No response was specified
+ schema:
+ $ref: '#/definitions/response-fields'
+ operationId: vlbcheck
+
+definitions:
+ parameter-setting:
+ type: object
+ properties:
+ parameter-name:
+ type: string
+ int-value:
+ type: integer
+ string-value:
+ type: string
+ boolean-value:
+ type: boolean
+
+ response-fields:
+ type: object
+ properties:
+ response-code:
+ type: string
+ ack-final-indicator:
+ type: string
+ response-message:
+ type: string
+ context-memory-json:
+ type: string
+
+ test-results:
+ type: object
+ properties:
+ test-results:
+ type: array
+ items:
+ $ref: '#/definitions/test-result'
+
+ test-result:
+ type: object
+ properties:
+ test-identifier:
+ type: string
+ results:
+ type: array
+ items:
+ type: string
+
+ execute-graph-input:
+ properties:
+ 'input':
+ type: object
+ properties:
+ 'mode':
+ type: string
+ 'module-name':
+ type: string
+ 'rpc-name':
+ type: string
+ 'sli-parameter':
+ items:
+ $ref: '#/definitions/parameter-setting'
+ type: array
+ type: object
+
+
+
+
+
+
+ unique_empty_identifier: {}
+
diff --git a/core/sliapi/model/yang/src/main/yang/sliapi.yang b/core/sliapi/model/yang/src/main/yang/sliapi.yang
new file mode 100755
index 000000000..98cbb2aa7
--- /dev/null
+++ b/core/sliapi/model/yang/src/main/yang/sliapi.yang
@@ -0,0 +1,117 @@
+module SLI-API {
+
+ yang-version 1;
+
+ namespace "org:onap:ccsdk:sli:core:sliapi";
+
+ prefix sample;
+
+ import ietf-inet-types { prefix "inet"; revision-date 2013-07-15; }
+
+ organization "ONAP";
+
+ contact
+ "Dan Timoney";
+
+ description
+ "Defines API to service logic interpreter";
+
+ revision "2016-11-10" {
+ description
+ "REST API to Service Logic Interpreter";
+ }
+
+ grouping parameter-setting {
+ description
+ "Parameter setting";
+
+ leaf parameter-name {
+ type string;
+ description "Parameter name";
+ }
+
+ leaf int-value {
+ type int32;
+ }
+ leaf string-value {
+ type string;
+ }
+ leaf boolean-value {
+ type boolean;
+ }
+ }
+
+ grouping response-fields {
+ leaf response-code {
+ type string;
+ }
+ leaf ack-final-indicator {
+ type string;
+ }
+ leaf response-message {
+ type string;
+ }
+ leaf context-memory-json {
+ type string;
+ }
+ }
+
+ container test-results {
+ description "Test results";
+
+ list test-result {
+ key "test-identifier";
+
+ leaf test-identifier {
+ type string;
+ }
+
+ leaf-list results {
+ type string;
+ }
+ }
+ }
+
+ rpc execute-graph {
+ description " Method to add a new parameter.";
+ input {
+
+ leaf module-name {
+ type string;
+ }
+
+ leaf rpc-name {
+ type string;
+ }
+
+ leaf mode {
+ type enumeration {
+ enum sync;
+ enum async;
+ }
+ }
+
+ list sli-parameter {
+ key "parameter-name";
+ uses parameter-setting;
+ }
+ }
+
+ output {
+ uses response-fields;
+ }
+ }
+
+ rpc healthcheck {
+ output {
+ uses response-fields;
+ }
+ }
+
+ rpc vlbcheck {
+ output {
+ uses response-fields;
+ }
+ }
+
+}
diff --git a/core/sliapi/pom.xml b/core/sliapi/pom.xml
new file mode 100755
index 000000000..2af92cf7e
--- /dev/null
+++ b/core/sliapi/pom.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>odlparent-lite</artifactId>
+ <version>2.1.0-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sliapi</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>pom</packaging>
+
+ <name>ccsdk-sli-core :: sliapi</name>
+
+ <modules>
+ <module>model</module>
+ <module>provider</module>
+ <module>installer</module>
+ </modules>
+
+ <properties>
+ <feature-name>sliapi</feature-name>
+ </properties>
+</project>
diff --git a/core/sliapi/provider/pom.xml b/core/sliapi/provider/pom.xml
new file mode 100755
index 000000000..79f3d5560
--- /dev/null
+++ b/core/sliapi/provider/pom.xml
@@ -0,0 +1,112 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>binding-parent</artifactId>
+ <version>2.1.0-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sliapi-provider</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>bundle</packaging>
+
+ <name>ccsdk-sli-core :: sliapi :: ${project.artifactId}</name>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>dblib-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sliapi-model-yang</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ <dependency>
+ <groupId>org.opendaylight.mdsal</groupId>
+ <artifactId>mdsal-binding-api</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-binding-api</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-binding-broker-impl</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.opendaylight.mdsal</groupId>
+ <artifactId>mdsal-binding-dom-adapter</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.opendaylight.mdsal</groupId>
+ <artifactId>yang-binding</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-common-util</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.core</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sli-common</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sli-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sli-provider-base</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-core-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-data-impl</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.derby</groupId>
+ <artifactId>derby</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/core/sliapi/provider/src/main/java/org/onap/ccsdk/sli/core/sliapi/SliapiHelper.java b/core/sliapi/provider/src/main/java/org/onap/ccsdk/sli/core/sliapi/SliapiHelper.java
new file mode 100644
index 000000000..95e51537f
--- /dev/null
+++ b/core/sliapi/provider/src/main/java/org/onap/ccsdk/sli/core/sliapi/SliapiHelper.java
@@ -0,0 +1,40 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.sliapi;
+
+import org.onap.ccsdk.sli.core.sli.provider.MdsalHelper;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.core.sliapi.rev161110.ExecuteGraphInputBuilder;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.core.sliapi.rev161110.execute.graph.input.SliParameterBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class SliapiHelper extends MdsalHelper {
+
+ private static final Logger LOG = LoggerFactory.getLogger(SliapiHelper.class);
+
+ static {
+ ExecuteGraphInputBuilder b1 = new ExecuteGraphInputBuilder();
+ SliParameterBuilder b2 = new SliParameterBuilder();
+
+ }
+
+}
diff --git a/core/sliapi/provider/src/main/java/org/onap/ccsdk/sli/core/sliapi/SliapiProvider.java b/core/sliapi/provider/src/main/java/org/onap/ccsdk/sli/core/sliapi/SliapiProvider.java
new file mode 100644
index 000000000..449fc3822
--- /dev/null
+++ b/core/sliapi/provider/src/main/java/org/onap/ccsdk/sli/core/sliapi/SliapiProvider.java
@@ -0,0 +1,676 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.sliapi;
+
+import java.io.BufferedReader;
+import java.io.FileNotFoundException;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.LinkedList;
+import java.util.Properties;
+
+import org.onap.ccsdk.sli.core.sli.provider.SvcLogicService;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
+import org.opendaylight.controller.md.sal.binding.api.WriteTransaction;
+import org.opendaylight.controller.md.sal.binding.impl.AbstractForwardedDataBroker;
+import org.opendaylight.controller.md.sal.common.api.data.LogicalDatastoreType;
+import org.opendaylight.controller.md.sal.common.api.data.OptimisticLockFailedException;
+import org.opendaylight.controller.md.sal.common.api.data.TransactionCommitFailedException;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataBroker;
+import org.opendaylight.controller.md.sal.dom.api.DOMDataWriteTransaction;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
+import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.core.sliapi.rev161110.ExecuteGraphInput;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.core.sliapi.rev161110.ExecuteGraphInput.Mode;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.core.sliapi.rev161110.ExecuteGraphInputBuilder;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.core.sliapi.rev161110.ExecuteGraphOutput;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.core.sliapi.rev161110.ExecuteGraphOutputBuilder;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.core.sliapi.rev161110.HealthcheckInput;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.core.sliapi.rev161110.HealthcheckOutput;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.core.sliapi.rev161110.HealthcheckOutputBuilder;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.core.sliapi.rev161110.SLIAPIService;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.core.sliapi.rev161110.TestResults;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.core.sliapi.rev161110.VlbcheckInput;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.core.sliapi.rev161110.VlbcheckOutput;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.core.sliapi.rev161110.VlbcheckOutputBuilder;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.core.sliapi.rev161110.execute.graph.input.SliParameter;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.core.sliapi.rev161110.test.results.TestResult;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.core.sliapi.rev161110.test.results.TestResultBuilder;
+import org.opendaylight.yangtools.yang.binding.InstanceIdentifier;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.RpcError.ErrorType;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifier;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeIdentifierWithPredicates;
+import org.opendaylight.yangtools.yang.data.api.YangInstanceIdentifier.NodeWithValue;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafSetEntryNode;
+import org.opendaylight.yangtools.yang.data.api.schema.LeafSetNode;
+import org.opendaylight.yangtools.yang.data.api.schema.MapEntryNode;
+import org.opendaylight.yangtools.yang.data.impl.schema.ImmutableNodes;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafSetEntryNodeBuilder;
+import org.opendaylight.yangtools.yang.data.impl.schema.builder.impl.ImmutableLeafSetNodeBuilder;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.ServiceReference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+
+/**
+ * Defines a base implementation for your provider. This class extends from a
+ * helper class which provides storage for the most commonly used components of
+ * the MD-SAL. Additionally the base class provides some basic logging and
+ * initialization / clean up methods.
+ *
+ * To use this, copy and paste (overwrite) the following method into the
+ * TestApplicationProviderModule class which is auto generated under
+ * src/main/java in this project (created only once during first compilation):
+ *
+ * <pre>
+ *
+ * &#64;Override
+ * public java.lang.AutoCloseable createInstance() {
+ *
+ * final SliapiProvider provider = new SliapiProvider();
+ * provider.setDataBroker(getDataBrokerDependency());
+ * provider.setNotificationService(getNotificationServiceDependency());
+ * provider.setRpcRegistry(getRpcRegistryDependency());
+ * provider.initialize();
+ * return new AutoCloseable() {
+ *
+ * &#64;Override
+ * public void close() throws Exception {
+ * // TODO: CLOSE ANY REGISTRATION OBJECTS CREATED USING ABOVE
+ * // BROKER/NOTIFICATION
+ * // SERVIE/RPC REGISTRY
+ * provider.close();
+ * }
+ * };
+ * }
+ *
+ * </pre>
+ */
+public class SliapiProvider implements AutoCloseable, SLIAPIService {
+
+ private static final Logger LOG = LoggerFactory.getLogger(SliapiProvider.class);
+ private static final String appName = "slitester";
+
+ protected DataBroker dataBroker;
+ protected DOMDataBroker domDataBroker;
+ protected NotificationPublishService notificationService;
+ protected RpcProviderRegistry rpcRegistry;
+
+ private SvcLogicService svcLogic;
+
+ protected BindingAwareBroker.RpcRegistration<SLIAPIService> rpcRegistration;
+
+ private static String SLIAPI_NAMESPACE = "org:onap:ccsdk:sli:core:sliapi";
+ private static String SLIAPI_REVISION = "2016-11-10";
+ private static String SDNC_STATUS_FILE = "SDNC_STATUS_FILE";
+ private static String sdncStatusFile = null;
+
+ private static QName TEST_RESULTS_QNAME = null;
+ private static QName TEST_RESULT_QNAME = null;
+ private static QName TEST_ID_QNAME = null;
+ private static QName RESULTS_QNAME = null;
+ private static final String NON_NULL = "non-null";
+
+ static {
+
+ TEST_RESULTS_QNAME = QName.create(SLIAPI_NAMESPACE, SLIAPI_REVISION, "test-results");
+ TEST_RESULT_QNAME = QName.create(TEST_RESULTS_QNAME, "test-result");
+ TEST_ID_QNAME = QName.create(TEST_RESULT_QNAME, "test-identifier");
+ RESULTS_QNAME = QName.create(TEST_RESULT_QNAME, "results");
+ }
+
+ public SliapiProvider(DataBroker dataBroker, NotificationPublishService notificationPublishService,
+ RpcProviderRegistry rpcProviderRegistry) {
+ this(dataBroker, notificationPublishService, rpcProviderRegistry, findSvcLogicService());
+ }
+
+ public SliapiProvider(DataBroker dataBroker, NotificationPublishService notificationPublishService,
+ RpcProviderRegistry rpcProviderRegistry, SvcLogicService svcLogic) {
+ this.LOG.info("Creating provider for " + appName);
+ this.dataBroker = dataBroker;
+ this.notificationService = notificationPublishService;
+ this.rpcRegistry = rpcProviderRegistry;
+ this.svcLogic = svcLogic;
+ initialize();
+ }
+
+ public void initialize() {
+ LOG.info("Initializing provider for " + appName);
+ // initialization code goes here.
+ rpcRegistration = rpcRegistry.addRpcImplementation(SLIAPIService.class, this);
+
+ sdncStatusFile = System.getenv(SDNC_STATUS_FILE);
+ LOG.info("SDNC STATUS FILE = " + sdncStatusFile);
+ LOG.info("Initialization complete for " + appName);
+ }
+
+ protected void initializeChild() {
+ // Override if you have custom initialization intelligence
+ }
+
+ @Override
+ public void close() throws Exception {
+ LOG.info("Closing provider for " + appName);
+ // closing code goes here
+
+ rpcRegistration.close();
+ LOG.info("Successfully closed provider for " + appName);
+ }
+
+ public void setDataBroker(DataBroker dataBroker) {
+ this.dataBroker = dataBroker;
+ if (dataBroker instanceof AbstractForwardedDataBroker) {
+ domDataBroker = ((AbstractForwardedDataBroker) dataBroker).getDelegate();
+ }
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("DataBroker set to " + (dataBroker == null ? "null" : NON_NULL) + ".");
+ }
+ }
+
+ public void setNotificationService(NotificationPublishService notificationService) {
+ this.notificationService = notificationService;
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Notification Service set to " + (notificationService == null ? "null" : NON_NULL) + ".");
+ }
+ }
+
+ public void setRpcRegistry(RpcProviderRegistry rpcRegistry) {
+ this.rpcRegistry = rpcRegistry;
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("RpcRegistry set to " + (rpcRegistry == null ? "null" : NON_NULL) + ".");
+ }
+ }
+
+ @Override
+ public ListenableFuture<RpcResult<ExecuteGraphOutput>> executeGraph(ExecuteGraphInput input) {
+ RpcResult<ExecuteGraphOutput> rpcResult = null;
+
+ SvcLogicService svcLogic = getSvcLogicService();
+ ExecuteGraphOutputBuilder respBuilder = new ExecuteGraphOutputBuilder();
+
+ String calledModule = input.getModuleName();
+ String calledRpc = input.getRpcName();
+ Mode calledMode = input.getMode();
+ String modeStr = "sync";
+
+ if (calledMode == Mode.Async) {
+ modeStr = "async";
+ }
+
+ if (svcLogic == null) {
+ respBuilder.setResponseCode("500");
+ respBuilder.setResponseMessage("Could not locate OSGi SvcLogicService service");
+ respBuilder.setAckFinalIndicator("Y");
+
+ rpcResult = RpcResultBuilder.<ExecuteGraphOutput>status(true).withResult(respBuilder.build()).build();
+ return (Futures.immediateFuture(rpcResult));
+ }
+
+ try {
+ if (!svcLogic.hasGraph(calledModule, calledRpc, null, modeStr)) {
+ respBuilder.setResponseCode("404");
+ respBuilder.setResponseMessage(
+ "Directed graph for " + calledModule + "/" + calledRpc + "/" + modeStr + " not found");
+ respBuilder.setAckFinalIndicator("Y");
+
+ rpcResult = RpcResultBuilder.<ExecuteGraphOutput>status(true).withResult(respBuilder.build()).build();
+ return (Futures.immediateFuture(rpcResult));
+ }
+ } catch (Exception e) {
+ LOG.error(
+ "Caught exception looking for directed graph for " + calledModule + "/" + calledRpc + "/" + modeStr,
+ e);
+
+ respBuilder.setResponseCode("500");
+ respBuilder.setResponseMessage("Internal error : could not determine if target graph exists");
+ respBuilder.setAckFinalIndicator("Y");
+
+ rpcResult = RpcResultBuilder.<ExecuteGraphOutput>status(true).withResult(respBuilder.build()).build();
+ return (Futures.immediateFuture(rpcResult));
+ }
+
+ // Load properties
+ Properties parms = new Properties();
+
+ // Pass properties using names from sli-parameters
+ for (SliParameter sliParm : input.getSliParameter()) {
+
+ String propValue = "";
+
+ Boolean boolval = sliParm.isBooleanValue();
+
+ if (boolval != null) {
+ propValue = boolval.toString();
+ } else {
+ Integer intval = sliParm.getIntValue();
+ if (intval != null) {
+ propValue = intval.toString();
+ } else {
+ propValue = sliParm.getStringValue();
+ if (propValue == null) {
+ propValue = "";
+ }
+ }
+ }
+ parms.setProperty(sliParm.getParameterName(), propValue);
+ }
+
+ // Also, pass "meta" properties (i.e. pass SliParameter objects themselves)
+ ExecuteGraphInputBuilder inputBuilder = new ExecuteGraphInputBuilder(input);
+
+ SliapiHelper.toProperties(parms, "input", inputBuilder);
+
+ try {
+ LOG.info("Calling directed graph for " + calledModule + "/" + calledRpc + "/" + modeStr);
+
+ if (LOG.isTraceEnabled()) {
+ StringBuffer argList = new StringBuffer();
+ argList.append("Parameters : {");
+ Enumeration e = parms.propertyNames();
+ while (e.hasMoreElements()) {
+ String propName = (String) e.nextElement();
+ argList.append(" (" + propName + "," + parms.getProperty(propName) + ") ");
+ }
+ argList.append("}");
+ LOG.trace(argList.toString());
+ argList = null;
+ }
+
+ Properties respProps = svcLogic.execute(calledModule, calledRpc, null, modeStr, parms, domDataBroker);
+
+ StringBuilder sb = new StringBuilder("{");
+
+ for (Object key : respProps.keySet()) {
+ String keyValue = (String) key;
+ if (keyValue != null && !"".equals(keyValue) && !keyValue.contains("input.sli-parameter")) {
+ sb.append("\"").append(keyValue).append("\": \"").append(respProps.getProperty(keyValue))
+ .append("\",");
+ }
+ }
+
+ sb.setLength(sb.length() - 1);
+ sb.append("}");
+
+ respBuilder.setResponseCode(respProps.getProperty("error-code", "0"));
+ respBuilder.setResponseMessage(respProps.getProperty("error-message", ""));// TODO change response-text to
+ // response-message to match
+ // other BVC APIs
+ respBuilder.setAckFinalIndicator(respProps.getProperty("ack-final", "Y"));
+ respBuilder.setContextMemoryJson(sb.toString());
+
+ TestResultBuilder testResultBuilder = new TestResultBuilder();
+
+ SliapiHelper.toBuilder(respProps, testResultBuilder);
+
+ String testIdentifier = testResultBuilder.getTestIdentifier();
+
+ if ((testIdentifier != null) && (testIdentifier.length() > 0)) {
+
+ // Add test results to config tree
+ LOG.debug("Saving test results for test id " + testIdentifier);
+
+ DomSaveTestResult(testResultBuilder.build(), true, LogicalDatastoreType.CONFIGURATION);
+
+ }
+
+ } catch (Exception e) {
+ LOG.error("Caught exception executing directed graph for" + calledModule + ":" + calledRpc + "," + modeStr
+ + ">", e);
+
+ respBuilder.setResponseCode("500");
+ respBuilder.setResponseMessage("Internal error : caught exception executing directed graph " + calledModule
+ + "/" + calledRpc + "/" + modeStr);
+ respBuilder.setAckFinalIndicator("Y");
+
+ }
+
+ rpcResult = RpcResultBuilder.<ExecuteGraphOutput>status(true).withResult(respBuilder.build()).build();
+ return (Futures.immediateFuture(rpcResult));
+ }
+
+ private SvcLogicService getSvcLogicService() {
+ if (svcLogic == null) {
+ svcLogic = findSvcLogicService();
+ }
+
+ return (svcLogic);
+ }
+
+ private static SvcLogicService findSvcLogicService() {
+ BundleContext bctx = FrameworkUtil.getBundle(SvcLogicService.class).getBundleContext();
+
+ SvcLogicService svcLogic = null;
+
+ // Get SvcLogicService reference
+ ServiceReference sref = bctx.getServiceReference(SvcLogicService.NAME);
+ if (sref != null) {
+ svcLogic = (SvcLogicService) bctx.getService(sref);
+
+ } else {
+ LOG.warn("Cannot find service reference for " + SvcLogicService.NAME);
+
+ }
+
+ return (svcLogic);
+ }
+
+ @Override
+ public ListenableFuture<RpcResult<HealthcheckOutput>> healthcheck(HealthcheckInput healthcheckInput) {
+
+ RpcResult<HealthcheckOutput> rpcResult = null;
+ SvcLogicService svcLogic = getSvcLogicService();
+
+ HealthcheckOutputBuilder respBuilder = new HealthcheckOutputBuilder();
+
+ String calledModule = "sli";
+ String calledRpc = "healthcheck";
+ String modeStr = "sync";
+
+ if (svcLogic == null) {
+ respBuilder.setResponseCode("500");
+ respBuilder.setResponseMessage("Could not locate OSGi SvcLogicService service");
+ respBuilder.setAckFinalIndicator("Y");
+
+ rpcResult = RpcResultBuilder.<HealthcheckOutput>failed().withResult(respBuilder.build()).build();
+ return (Futures.immediateFuture(rpcResult));
+ }
+
+ try {
+ if (!svcLogic.hasGraph(calledModule, calledRpc, null, modeStr)) {
+ respBuilder.setResponseCode("404");
+ respBuilder.setResponseMessage(
+ "Directed graph for " + calledModule + "/" + calledRpc + "/" + modeStr + " not found");
+
+ respBuilder.setAckFinalIndicator("Y");
+
+ rpcResult = RpcResultBuilder.<HealthcheckOutput>status(true).withResult(respBuilder.build()).build();
+ return (Futures.immediateFuture(rpcResult));
+ }
+ } catch (Exception e) {
+ LOG.error(
+ "Caught exception looking for directed graph for " + calledModule + "/" + calledRpc + "/" + modeStr,
+ e);
+
+ respBuilder.setResponseCode("500");
+ respBuilder.setResponseMessage("Internal error : could not determine if target graph exists");
+ respBuilder.setAckFinalIndicator("Y");
+
+ rpcResult = RpcResultBuilder.<HealthcheckOutput>failed().withResult(respBuilder.build()).build();
+ return (Futures.immediateFuture(rpcResult));
+ }
+
+ try {
+ LOG.info("Calling directed graph for " + calledModule + "/" + calledRpc + "/" + modeStr);
+
+ Properties parms = new Properties();
+
+ Properties respProps = svcLogic.execute(calledModule, calledRpc, null, modeStr, parms);
+
+ respBuilder.setResponseCode(respProps.getProperty("error-code", "0"));
+ respBuilder.setResponseMessage(respProps.getProperty("error-message", ""));
+ respBuilder.setAckFinalIndicator(respProps.getProperty("ack-final", "Y"));
+
+ } catch (Exception e) {
+ LOG.error("Caught exception executing directed graph for" + calledModule + ":" + calledRpc + "," + modeStr
+ + ">", e);
+
+ respBuilder.setResponseCode("500");
+ respBuilder.setResponseMessage("Internal error : caught exception executing directed graph " + calledModule
+ + "/" + calledRpc + "/" + modeStr);
+ respBuilder.setAckFinalIndicator("Y");
+
+ }
+
+ rpcResult = RpcResultBuilder.<HealthcheckOutput>status(true).withResult(respBuilder.build()).build();
+ return (Futures.immediateFuture(rpcResult));
+ }
+
+ public ListenableFuture<RpcResult<VlbcheckOutput>> vlbcheck(VlbcheckInput vlbInput) {
+
+ RpcResult<VlbcheckOutput> rpcResult = null;
+ SvcLogicService svcLogic = getSvcLogicService();
+
+ VlbcheckOutputBuilder respBuilder = new VlbcheckOutputBuilder();
+
+ String calledModule = "sli";
+ String calledRpc = "vlbcheck";
+ String modeStr = "sync";
+
+ if (svcLogic == null) {
+ respBuilder.setResponseCode("500");
+ respBuilder.setResponseMessage("Could not locate OSGi SvcLogicService service");
+ respBuilder.setAckFinalIndicator("Y");
+
+ rpcResult = RpcResultBuilder.<VlbcheckOutput>failed().withResult(respBuilder.build()).build();
+ return (Futures.immediateFuture(rpcResult));
+ }
+
+ boolean dgExists = true;
+ try {
+ if (!svcLogic.hasGraph(calledModule, calledRpc, null, modeStr)) {
+ dgExists = false;
+ }
+ } catch (Exception e) {
+ LOG.warn(
+ "Caught exception looking for directed graph for " + calledModule + "/" + calledRpc + "/" + modeStr,
+ e);
+
+ dgExists = false;
+ }
+
+ if (dgExists) {
+ try {
+ LOG.info("Calling directed graph for " + calledModule + "/" + calledRpc + "/" + modeStr);
+
+ Properties parms = new Properties();
+
+ Properties respProps = svcLogic.execute(calledModule, calledRpc, null, modeStr, parms);
+
+ respBuilder.setResponseCode(respProps.getProperty("error-code", "0"));
+ respBuilder.setResponseMessage(respProps.getProperty("error-message", ""));
+ respBuilder.setAckFinalIndicator(respProps.getProperty("ack-final", "Y"));
+
+ } catch (Exception e) {
+ LOG.error("Caught exception executing directed graph for" + calledModule + ":" + calledRpc + ","
+ + modeStr + ">", e);
+
+ respBuilder.setResponseCode("500");
+ respBuilder.setResponseMessage("Internal error : caught exception executing directed graph "
+ + calledModule + "/" + calledRpc + "/" + modeStr);
+ respBuilder.setAckFinalIndicator("Y");
+
+ }
+
+ rpcResult = RpcResultBuilder.<VlbcheckOutput>status(true).withResult(respBuilder.build()).build();
+ return (Futures.immediateFuture(rpcResult));
+ } else {
+ // check the state based on the config file
+
+ boolean suspended = false;
+ BufferedReader br = null;
+ String line = "";
+
+ if (sdncStatusFile != null) {
+ try {
+ br = new BufferedReader(new FileReader(sdncStatusFile));
+ while ((line = br.readLine()) != null) {
+ if ("ODL_STATE=SUSPENDED".equals(line)) {
+ suspended = true;
+ LOG.debug("vlbcheck: server is suspended");
+ }
+ }
+ br.close();
+ } catch (FileNotFoundException e) {
+ LOG.trace("Caught File not found exception " + sdncStatusFile + "\n", e);
+ } catch (Exception e) {
+ LOG.trace("Failed to read status file " + sdncStatusFile + "\n", e);
+ } finally {
+ if (br != null) {
+ try {
+ br.close();
+ } catch (IOException e) {
+ LOG.warn("Failed to close status file " + sdncStatusFile + "\n", e);
+ }
+ }
+ }
+ }
+
+ if (suspended) {
+ rpcResult = RpcResultBuilder.<VlbcheckOutput>failed()
+ .withError(ErrorType.APPLICATION, "resource-denied", "Server Suspended").build();
+ } else {
+ respBuilder.setResponseMessage("server is normal");
+ rpcResult = RpcResultBuilder.<VlbcheckOutput>status(true).withResult(respBuilder.build()).build();
+ }
+ return (Futures.immediateFuture(rpcResult));
+ }
+ }
+
+ private void DomSaveTestResult(final TestResult entry, boolean merge, LogicalDatastoreType storeType) {
+
+ if (domDataBroker == null) {
+ LOG.error("domDataBroker unset - cannot save test result using DOMDataBroker");
+ return;
+ }
+
+ MapEntryNode resultNode = null;
+
+ try {
+ resultNode = toMapEntryNode(entry);
+ } catch (Exception e) {
+ LOG.error("Caught exception trying to create map entry node", e);
+ }
+
+ if (resultNode == null) {
+ LOG.error("Could not convert entry to MapEntryNode");
+ return;
+ }
+
+ YangInstanceIdentifier testResultsPid = YangInstanceIdentifier.builder().node(TEST_RESULTS_QNAME)
+ .node(QName.create(TEST_RESULTS_QNAME, "test-result")).build();
+ YangInstanceIdentifier testResultPid = testResultsPid
+ .node(new NodeIdentifierWithPredicates(TEST_RESULT_QNAME, resultNode.getIdentifier().getKeyValues()));
+
+ int tries = 2;
+ while (true) {
+ try {
+ DOMDataWriteTransaction wtx = domDataBroker.newWriteOnlyTransaction();
+ if (merge) {
+ LOG.info("Merging test identifier " + entry.getTestIdentifier());
+ wtx.merge(storeType, testResultPid, resultNode);
+ } else {
+ LOG.info("Putting test identifier " + entry.getTestIdentifier());
+ wtx.put(storeType, testResultPid, resultNode);
+ }
+ wtx.submit().checkedGet();
+ LOG.trace("Update DataStore succeeded");
+ break;
+ } catch (final TransactionCommitFailedException e) {
+ if (e instanceof OptimisticLockFailedException) {
+ if (--tries <= 0) {
+ LOG.trace("Got OptimisticLockFailedException on last try - failing ");
+ throw new IllegalStateException(e);
+ }
+ LOG.trace("Got OptimisticLockFailedException - trying again ");
+ } else {
+ LOG.trace("Update DataStore failed");
+ throw new IllegalStateException(e);
+ }
+ }
+ }
+
+ }
+
+ private void SaveTestResult(final TestResult entry, boolean merge, LogicalDatastoreType storeType)
+ throws IllegalStateException {
+ // Each entry will be identifiable by a unique key, we have to create that
+ // identifier
+
+ InstanceIdentifier.InstanceIdentifierBuilder<TestResult> testResultIdBuilder = InstanceIdentifier
+ .<TestResults>builder(TestResults.class).child(TestResult.class, entry.key());
+ InstanceIdentifier<TestResult> path = testResultIdBuilder.build();
+ int tries = 2;
+ while (true) {
+ try {
+ WriteTransaction tx = dataBroker.newWriteOnlyTransaction();
+ if (merge) {
+ tx.merge(storeType, path, entry);
+ } else {
+ tx.put(storeType, path, entry);
+ }
+ tx.submit().checkedGet();
+ LOG.trace("Update DataStore succeeded");
+ break;
+ } catch (final TransactionCommitFailedException e) {
+ if (e instanceof OptimisticLockFailedException) {
+ if (--tries <= 0) {
+ LOG.trace("Got OptimisticLockFailedException on last try - failing ");
+ throw new IllegalStateException(e);
+ }
+ LOG.trace("Got OptimisticLockFailedException - trying again ");
+ } else {
+ LOG.trace("Update DataStore failed");
+ throw new IllegalStateException(e);
+ }
+ }
+ }
+ }
+
+ private MapEntryNode toMapEntryNode(TestResult testResult) {
+
+ YangInstanceIdentifier testResultId = YangInstanceIdentifier.builder().node(TEST_RESULTS_QNAME)
+ .node(TEST_RESULT_QNAME).build();
+
+ // Construct results list
+ LinkedList<LeafSetEntryNode<Object>> entryList = new LinkedList<>();
+ for (String result : testResult.getResults()) {
+ LeafSetEntryNode<Object> leafSetEntryNode = ImmutableLeafSetEntryNodeBuilder.create()
+ .withNodeIdentifier(new NodeWithValue(RESULTS_QNAME, result)).withValue(result).build();
+ entryList.add(leafSetEntryNode);
+ }
+ // Construct results LeafSetNode
+ LeafSetNode<?> resultsNode = ImmutableLeafSetNodeBuilder.create()
+ .withNodeIdentifier(new NodeIdentifier(RESULTS_QNAME)).withValue(entryList).build();
+
+ // Construct test result ContainerNode with 2 children - test-identifier leaf
+ // and results leaf-set
+ MapEntryNode testResultNode = ImmutableNodes.mapEntryBuilder()
+ .withNodeIdentifier(new NodeIdentifierWithPredicates(TEST_RESULT_QNAME, TEST_ID_QNAME,
+ testResult.getTestIdentifier()))
+ .withChild(ImmutableNodes.leafNode(TEST_ID_QNAME, testResult.getTestIdentifier()))
+ .withChild(resultsNode).build();
+
+ return (testResultNode);
+
+ }
+
+}
diff --git a/core/sliapi/provider/src/main/resources/OSGI-INF/blueprint/sliapi-blueprint.xml b/core/sliapi/provider/src/main/resources/OSGI-INF/blueprint/sliapi-blueprint.xml
new file mode 100644
index 000000000..875027e63
--- /dev/null
+++ b/core/sliapi/provider/src/main/resources/OSGI-INF/blueprint/sliapi-blueprint.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+ xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0"
+ odl:use-default-for-reference-types="true">
+
+ <reference id="svcLogicService"
+ interface="org.onap.ccsdk.sli.core.sli.provider.SvcLogicService" />
+
+
+ <reference id="dataBroker"
+ interface="org.opendaylight.controller.md.sal.binding.api.DataBroker"
+ odl:type="default" />
+
+ <reference id="notificationService"
+ interface="org.opendaylight.controller.md.sal.binding.api.NotificationPublishService"
+ odl:type="default" />
+
+ <reference id="rpcRegistry"
+ interface="org.opendaylight.controller.sal.binding.api.RpcProviderRegistry"
+ odl:type="default" />
+
+ <bean id="provider" class="org.onap.ccsdk.sli.core.sliapi.SliapiProvider">
+ <argument ref="dataBroker" />
+ <argument ref="notificationService" />
+ <argument ref="rpcRegistry" />
+
+ </bean>
+</blueprint> \ No newline at end of file
diff --git a/core/sliapi/provider/src/main/resources/org/opendaylight/blueprint/sliapi-blueprint.xml b/core/sliapi/provider/src/main/resources/org/opendaylight/blueprint/sliapi-blueprint.xml
new file mode 100644
index 000000000..875027e63
--- /dev/null
+++ b/core/sliapi/provider/src/main/resources/org/opendaylight/blueprint/sliapi-blueprint.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+ xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0"
+ odl:use-default-for-reference-types="true">
+
+ <reference id="svcLogicService"
+ interface="org.onap.ccsdk.sli.core.sli.provider.SvcLogicService" />
+
+
+ <reference id="dataBroker"
+ interface="org.opendaylight.controller.md.sal.binding.api.DataBroker"
+ odl:type="default" />
+
+ <reference id="notificationService"
+ interface="org.opendaylight.controller.md.sal.binding.api.NotificationPublishService"
+ odl:type="default" />
+
+ <reference id="rpcRegistry"
+ interface="org.opendaylight.controller.sal.binding.api.RpcProviderRegistry"
+ odl:type="default" />
+
+ <bean id="provider" class="org.onap.ccsdk.sli.core.sliapi.SliapiProvider">
+ <argument ref="dataBroker" />
+ <argument ref="notificationService" />
+ <argument ref="rpcRegistry" />
+
+ </bean>
+</blueprint> \ No newline at end of file
diff --git a/core/sliapi/provider/src/test/java/org/onap/ccsdk/sli/core/sliapi/SliapiHelperTest.java b/core/sliapi/provider/src/test/java/org/onap/ccsdk/sli/core/sliapi/SliapiHelperTest.java
new file mode 100644
index 000000000..228f6127e
--- /dev/null
+++ b/core/sliapi/provider/src/test/java/org/onap/ccsdk/sli/core/sliapi/SliapiHelperTest.java
@@ -0,0 +1,35 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 IBM. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.sliapi;
+
+import static org.junit.Assert.assertNotNull;
+
+import org.junit.Test;
+
+public class SliapiHelperTest {
+
+ @Test
+ public void TestSliapiHelper()
+ {
+ SliapiHelper sliapiHelper= new SliapiHelper();
+ assertNotNull(sliapiHelper);
+ }
+}
diff --git a/core/sliapi/provider/src/test/java/org/onap/ccsdk/sli/core/sliapi/TestSliapiProvider.java b/core/sliapi/provider/src/test/java/org/onap/ccsdk/sli/core/sliapi/TestSliapiProvider.java
new file mode 100644
index 000000000..f48cf783b
--- /dev/null
+++ b/core/sliapi/provider/src/test/java/org/onap/ccsdk/sli/core/sliapi/TestSliapiProvider.java
@@ -0,0 +1,209 @@
+/**
+ *
+ */
+package org.onap.ccsdk.sli.core.sliapi;
+
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.io.InputStream;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.concurrent.Future;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.onap.ccsdk.sli.core.sli.SvcLogicParser;
+import org.onap.ccsdk.sli.core.sli.SvcLogicStore;
+import org.onap.ccsdk.sli.core.sli.SvcLogicStoreFactory;
+import org.onap.ccsdk.sli.core.sli.provider.SvcLogicClassResolver;
+import org.onap.ccsdk.sli.core.sli.provider.SvcLogicPropertiesProviderImpl;
+import org.onap.ccsdk.sli.core.sli.provider.SvcLogicServiceImpl;
+import org.onap.ccsdk.sli.core.sli.provider.base.AbstractSvcLogicNodeExecutor;
+import org.onap.ccsdk.sli.core.sli.provider.base.BlockNodeExecutor;
+import org.onap.ccsdk.sli.core.sli.provider.base.CallNodeExecutor;
+import org.onap.ccsdk.sli.core.sli.provider.base.ConfigureNodeExecutor;
+import org.onap.ccsdk.sli.core.sli.provider.base.DeleteNodeExecutor;
+import org.onap.ccsdk.sli.core.sli.provider.base.ExecuteNodeExecutor;
+import org.onap.ccsdk.sli.core.sli.provider.base.ExistsNodeExecutor;
+import org.onap.ccsdk.sli.core.sli.provider.base.ForNodeExecutor;
+import org.onap.ccsdk.sli.core.sli.provider.base.GetResourceNodeExecutor;
+import org.onap.ccsdk.sli.core.sli.provider.base.IsAvailableNodeExecutor;
+import org.onap.ccsdk.sli.core.sli.provider.base.NotifyNodeExecutor;
+import org.onap.ccsdk.sli.core.sli.provider.base.RecordNodeExecutor;
+import org.onap.ccsdk.sli.core.sli.provider.base.ReleaseNodeExecutor;
+import org.onap.ccsdk.sli.core.sli.provider.base.ReserveNodeExecutor;
+import org.onap.ccsdk.sli.core.sli.provider.base.ReturnNodeExecutor;
+import org.onap.ccsdk.sli.core.sli.provider.base.SaveNodeExecutor;
+import org.onap.ccsdk.sli.core.sli.provider.base.SetNodeExecutor;
+import org.onap.ccsdk.sli.core.sli.provider.base.SwitchNodeExecutor;
+import org.onap.ccsdk.sli.core.sli.provider.base.UpdateNodeExecutor;
+import org.onap.ccsdk.sli.core.sli.provider.base.WhileNodeExecutor;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
+import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.core.sliapi.rev161110.ExecuteGraphInput;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.core.sliapi.rev161110.ExecuteGraphInputBuilder;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.core.sliapi.rev161110.HealthcheckInput;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.core.sliapi.rev161110.SLIAPIService;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.core.sliapi.rev161110.VlbcheckInput;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.core.sliapi.rev161110.execute.graph.input.SliParameter;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.core.sliapi.rev161110.execute.graph.input.SliParameterBuilder;
+
+/**
+ * @author dt5972
+ *
+ */
+public class TestSliapiProvider {
+
+ private SliapiProvider provider;
+
+ private static final String HEALTHCHECK_DG = "sli_healthcheck.xml";
+
+ private static final Map<String, AbstractSvcLogicNodeExecutor> BUILTIN_NODES = new HashMap<String, AbstractSvcLogicNodeExecutor>() {
+ {
+ put("block", new BlockNodeExecutor());
+ put("call", new CallNodeExecutor());
+ put("configure", new ConfigureNodeExecutor());
+ put("delete", new DeleteNodeExecutor());
+ put("execute", new ExecuteNodeExecutor());
+ put("exists", new ExistsNodeExecutor());
+ put("for", new ForNodeExecutor());
+ put("get-resource", new GetResourceNodeExecutor());
+ put("is-available", new IsAvailableNodeExecutor());
+ put("notify", new NotifyNodeExecutor());
+ put("record", new RecordNodeExecutor());
+ put("release", new ReleaseNodeExecutor());
+ put("reserve", new ReserveNodeExecutor());
+ put("return", new ReturnNodeExecutor());
+ put("save", new SaveNodeExecutor());
+ put("set", new SetNodeExecutor());
+ put("switch", new SwitchNodeExecutor());
+ put("update", new UpdateNodeExecutor());
+ put("while", new WhileNodeExecutor());
+
+ }
+ };
+
+ /**
+ * @throws java.lang.Exception
+ */
+ @Before
+ public void setUp() throws Exception {
+ DataBroker dataBroker = mock(DataBroker.class);
+ NotificationPublishService notifyService = mock(NotificationPublishService.class);
+ RpcProviderRegistry rpcRegistry = mock(RpcProviderRegistry.class);
+ BindingAwareBroker.RpcRegistration<SLIAPIService> rpcRegistration = (BindingAwareBroker.RpcRegistration<SLIAPIService>) mock(
+ BindingAwareBroker.RpcRegistration.class);
+ when(rpcRegistry.addRpcImplementation(any(Class.class), any(SLIAPIService.class))).thenReturn(rpcRegistration);
+
+ // Load svclogic.properties and get a SvcLogicStore
+ InputStream propStr = TestSliapiProvider.class.getResourceAsStream("/svclogic.properties");
+ Properties svcprops = new Properties();
+ svcprops.load(propStr);
+
+ SvcLogicStore store = SvcLogicStoreFactory.getSvcLogicStore(svcprops);
+
+ assertNotNull(store);
+
+ // Load the DG for the healthcheck api
+ URL testCaseUrl = TestSliapiProvider.class.getClassLoader().getResource(HEALTHCHECK_DG);
+ if (testCaseUrl == null) {
+ fail("Cannot find " + HEALTHCHECK_DG);
+ }
+ SvcLogicParser.load(testCaseUrl.getPath(), store);
+ SvcLogicParser.activate("sli", "healthcheck", "1.0.0", "sync", store);
+
+ // Create a ServiceLogicService and initialize it
+ SvcLogicServiceImpl svc = new SvcLogicServiceImpl(new SvcLogicPropertiesProviderImpl(),
+ new SvcLogicClassResolver());
+ for (String nodeType : BUILTIN_NODES.keySet()) {
+ svc.registerExecutor(nodeType, BUILTIN_NODES.get(nodeType));
+ }
+
+ // Finally ready to create SliapiProvider
+ provider = new SliapiProvider(dataBroker, notifyService, rpcRegistry, svc);
+ provider.setDataBroker(dataBroker);
+ provider.setNotificationService(notifyService);
+ provider.setRpcRegistry(rpcRegistry);
+ }
+
+ /**
+ * @throws java.lang.Exception
+ */
+ @After
+ public void tearDown() throws Exception {
+ provider.close();
+ }
+
+ /**
+ * Test method for
+ * {@link SliapiProvider#executeGraph(org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.core.sliapi.rev161110.ExecuteGraphInput)}.
+ */
+ @Test
+ public void testExecuteGraph() {
+ ExecuteGraphInputBuilder inputBuilder = new ExecuteGraphInputBuilder();
+
+ // Valid test - graph exists
+ inputBuilder.setMode(ExecuteGraphInput.Mode.Sync);
+ inputBuilder.setModuleName("sli");
+ inputBuilder.setRpcName("healthcheck");
+ List<SliParameter> pList = new LinkedList<>();
+ SliParameterBuilder pBuilder = new SliParameterBuilder();
+ pBuilder.setParameterName("int-parameter");
+ pBuilder.setIntValue(1);
+ pList.add(pBuilder.build());
+ pBuilder.setParameterName("bool-parameter");
+ pBuilder.setIntValue(null);
+ pBuilder.setBooleanValue(true);
+ pList.add(pBuilder.build());
+ pBuilder.setParameterName("str-parameter");
+ pBuilder.setBooleanValue(null);
+ pBuilder.setStringValue("value");
+ pList.add(pBuilder.build());
+ inputBuilder.setSliParameter(pList);
+ provider.executeGraph(inputBuilder.build());
+
+
+ // Invalid test - graph does not exist
+ inputBuilder.setMode(ExecuteGraphInput.Mode.Sync);
+ inputBuilder.setModuleName("sli");
+ inputBuilder.setRpcName("no-such-graph");
+ pList = new LinkedList<>();
+ pBuilder = new SliParameterBuilder();
+ pBuilder.setParameterName("int-parameter");
+ pBuilder.setIntValue(1);
+ pList.add(pBuilder.build());
+ pBuilder.setParameterName("bool-parameter");
+ pBuilder.setIntValue(null);
+ pBuilder.setBooleanValue(true);
+ pList.add(pBuilder.build());
+ pBuilder.setParameterName("str-parameter");
+ pBuilder.setBooleanValue(null);
+ pBuilder.setStringValue("value");
+ pList.add(pBuilder.build());
+ inputBuilder.setSliParameter(pList);
+ provider.executeGraph(inputBuilder.build());
+
+ assertTrue(provider.vlbcheck(mock(VlbcheckInput.class)) instanceof Future<?>);
+ }
+
+ /**
+ * Test method for
+ * {@link SliapiProvider#healthcheck()}.
+ */
+ @Test
+ public void testHealthcheck() {
+ provider.healthcheck(mock(HealthcheckInput.class));
+ }
+
+}
diff --git a/core/sliapi/provider/src/test/resources/simplelogger.properties b/core/sliapi/provider/src/test/resources/simplelogger.properties
new file mode 100644
index 000000000..2f7d8ea0b
--- /dev/null
+++ b/core/sliapi/provider/src/test/resources/simplelogger.properties
@@ -0,0 +1,23 @@
+###
+# ============LICENSE_START=======================================================
+# ONAP : CCSDK
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights
+# reserved.
+# ================================================================================
+# 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.
+# ============LICENSE_END=========================================================
+###
+
+org.slf4j.simpleLogger.defaultLogLevel=info
+org.slf4j.simplelogger.log.org.onap.ccsdk.sli.core.sliapi.SliapiProvider=debug
diff --git a/core/sliapi/provider/src/test/resources/sli_healthcheck.xml b/core/sliapi/provider/src/test/resources/sli_healthcheck.xml
new file mode 100644
index 000000000..d512f546f
--- /dev/null
+++ b/core/sliapi/provider/src/test/resources/sli_healthcheck.xml
@@ -0,0 +1,27 @@
+<!--
+ ============LICENSE_START=======================================================
+ openECOMP : SDN-C
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property. All rights
+ reserved.
+ ================================================================================
+ 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.
+ ============LICENSE_END=========================================================
+ -->
+
+<service-logic xmlns="http://www.onap.org/sdnc/svclogic"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.onap.org/sdnc/svclogic ./svclogic.xsd" module='sli' version='1.0.0'><method rpc='healthcheck' mode='sync'>
+<set>
+<parameter name='error-code' value='200' />
+<parameter name='error-message' value='SDN-C is healthy'/>
+<parameter name='ack-final' value='Y'/>
+</set></method></service-logic>
diff --git a/core/sliapi/provider/src/test/resources/svclogic.properties b/core/sliapi/provider/src/test/resources/svclogic.properties
new file mode 100644
index 000000000..426960f76
--- /dev/null
+++ b/core/sliapi/provider/src/test/resources/svclogic.properties
@@ -0,0 +1,27 @@
+###
+# ============LICENSE_START=======================================================
+# ONAP : CCSDK
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights
+# reserved.
+# ================================================================================
+# 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.
+# ============LICENSE_END=========================================================
+###
+
+org.onap.ccsdk.sli.dbtype = jdbc
+org.onap.ccsdk.sli.jdbc.url=jdbc:derby:memory:sdnctl;create=true
+org.onap.ccsdk.sli.jdbc.driver=org.apache.derby.jdbc.EmbeddedDriver
+org.onap.ccsdk.sli.jdbc.database = sdnctl
+org.onap.ccsdk.sli.jdbc.user = test
+org.onap.ccsdk.sli.jdbc.password = test
diff --git a/core/src/site/apt/nodes.apt b/core/src/site/apt/nodes.apt
new file mode 100644
index 000000000..95a51467c
--- /dev/null
+++ b/core/src/site/apt/nodes.apt
@@ -0,0 +1,953 @@
+~~~
+~~ ============LICENSE_START=======================================================
+~~ ONAP : CCSDK
+~~ ================================================================================
+~~ Copyright (C) 2017 AT&T Intellectual Property. All rights
+~~ reserved.
+~~ ================================================================================
+~~ 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.
+~~ ============LICENSE_END=========================================================
+~~~
+
+ ---
+ Service Logic Interpreter
+ ---
+ Dan Timoney
+ ---
+ 2014-11-12
+ ---
+
+Supported node types
+
+ The following built-in node types are currently supported:
+
+ * Flow Control
+
+ * {{{Block node}<<block>>}}
+
+ * {{{Call node}<<call>>}}
+
+ * {{{For node}<<for>>}}
+
+ * {{{Return node}<<return>>}}
+
+ * {{{Set node}<<set>>}}
+
+ * {{{Switch node}<<switch>>}}
+
+ * Device Management
+
+ * {{{Configure node}<<configure>>}}
+
+ * Java Plugin Support
+
+ * {{{Execute node}<<execute>>}}
+
+ * Recording
+
+ * {{{Record node}<<record>>}}
+
+ * Resource Management
+
+ * {{{Delete node}<<delete>>}}
+
+ * {{{Exists node}<<exists>>}}
+
+ * {{{Get-resource node}<<get-resource>>}}
+
+ * {{{Is-available node}<<is-available>>}}
+
+ * {{{Notify node}<<notify>>}}
+
+ * {{{Release node}<<release>>}}
+
+ * {{{Reserve node}<<reserve>>}}
+
+ * {{{Save node}<<save>>}}
+
+ * {{{Update node}<<update>>}}
+
+
+* Flow Control
+
+** Block node
+
+*** Description
+
+ A <<block>> node is used to executes a set of nodes.
+
+*** Attributes
+
+*--------------*--------------------------------------------+
+| <<atomic>> | if <true>, then if a node returns failure, subsequent nodes will not be executed and nodes already executed will be backed out.
+*--------------*--------------------------------------------+
+
+*** Parameters
+
+ None
+
+*** Outcomes
+
+ None
+
+*** Example
+
++-----------------+
+<block>
+ <record plugin="org.onap.ccsdk.sli.core.sli.recording.FileRecorder">
+ <parameter name="file" value="/tmp/sample_r1.log" />
+ <parameter name="field1" value="__TIMESTAMP__"/>
+ <parameter name="field2" value="RESERVED"/>
+ <parameter name="field3" value="$asePort.uni_circuit_id"/>
+ </record>
+ <return status="success">
+ <parameter name="uni-circuit-id" value="$asePort.uni_circuit_id" />
+ </return>
+</block>
++-----------------+
+
+
+
+**Call node
+
+*** Description
+
+ A <<call>> node is used to call another graph
+
+*** Attributes
+
+*--------------*-------+
+| <<module>> | Module of directed graph to call. If unset, defaults to that of calling graph
+*--------------*-------+
+| <<rpc>> | rpc of directed graph to call.
+*--------------*-------+
+| <<version>> | version of graph to call, If unset, uses active version.
+*--------------*-------+
+| <<mode>> | mode (sync/async) of graph to call. If unset, defaults to that of calling graph.
+*--------------*-------+
+
+
+
+*** Parameters
+
+ Not applicable
+
+*** Outcomes
+
+*----------*---------+
+| <<success>> | Sub graph returned success
+*----------*---------+
+| <<not-found>> | Graph not found
+*----------*---------+
+| <<failure>> | Subgraph returned success
+*----------*---------+
+ .
+
+*** Example
+
++-------------------+
+<call rpc="svc-topology-reserve" mode="sync" />
++-------------------+
+
+**For node
+
+*** Description
+
+ A <<for>> node provides a fixed iteration looping mechanism, similar to the Java for loop
+
+*** Attributes
+
+*--------------*-------+
+| <<index>> | index variable
+*--------------*-------+
+| <<start>> | initial value
+*--------------*-------+
+| <<end>> | maximum value
+*--------------*-------+
+
+
+*** Parameters
+
+ Not applicable.
+
+*** Outcomes
+
+ Not applicable. The <<status>> node has no outcomes.
+
+*** Example
+
++-------------------+
+<for index="i" start="0" end="`$service-data.universal-cpe-ft.l2-switch-interfaces_length`">
+ <record plugin="org.onap.ccsdk.sli.core.sli.recording.Slf4jRecorder">
+ <parameter name="logger" value="message-log"/>
+ <parameter name="level" value="info"/>
+ <parameter name="field1" value="`'current l2-switch-interface name is ' + $service-data.universal-cpe-ft.l2-switch-interfaces[$i].name`"/>
+ </record>
+</for>
++-------------------+
+
+**Return node
+
+*** Description
+
+ A <<return>> node is used to return a status to the invoking MD-SAL application
+
+*** Attributes
+
+*--------------*-------+
+| <<status>> | Status value to return (<success> or <failure>)
+*--------------*-------+
+
+
+*** Parameters
+
+ The following optional parameters may be passed to convey more
+ detailed status information.
+
+*------------*-----------+
+| <<error-code>> | A brief, usually numeric, code indicating the error condition
+*------------*-----------+
+| <<error-message>> | A more detailed error message
+*------------*-----------+
+
+*** Outcomes
+
+ Not applicable. The <<status>> node has no outcomes.
+
+*** Example
+
++-------------------+
+<return status="failure">
+ <parameter name="error-code" value="1542" />
+ <parameter name="error-message" value="Activation failure" />
+</return>
++-------------------+
+
+**Set node
+
+*** Description
+
+ A <<set>> node is used to set one or more values in the execution context
+
+*** Attributes
+
+*--------------*-------+
+| <<only-if-unset>> | If true the set node will only execute if the current value of the target is null
+*--------------*-------+
+
+*** Parameters
+
+ Values to be set are passed as parameters
+
+*** Outcomes
+
+ Not applicable. The <<set>> node has no outcomes.
+
+*** Example
+
++-------------------+
+<set>
+ <parameter name="vlan" value="$network.provider-segmentation-id" />
+</set>
++-------------------+
+
+**Switch node
+
+*** Description
+
+ A <<switch>> node is used to make a decision based on its <<test>> attribute.
+
+*** Attributes
+
+*--------------*-------+
+| <<test>> | Condition to test
+*--------------*-------+
+
+
+*** Parameters
+
+ None
+
+
+*** Outcomes
+
+ Depends on the <<test>> condition
+
+*** Example
+
++-------------------+
+<switch test="$uni-cir-units">
+ <outcome value="Mbps">
+ <reserve plugin="org.onap.ccsdk.sli.adaptors.samplesvc.SampleServiceResource"
+ resource="ase-port"
+ key="resource-emt-clli == $edge-device-clli and speed >= $uni-cir-value"
+ pfx="asePort">
+
+ <outcome value="success">
+ <return status="success">
+ <parameter name="uni-circuit-id" value="$asePort.uni_circuit_id" />
+ </return>
+ </outcome>
+ <outcome value="Other">
+ <return status="failure">
+ <parameter name="error-code" value="1010" />
+ <parameter name="error-message" value="No ports found that match criteria" />
+ </return>
+ </outcome>
+ </reserve>
+ </outcome>
+ <outcome value="Gbps">
+ <reserve plugin="org.onap.ccsdk.sli.adaptors.samplesvc.SampleServiceResource"
+ resource="ase-port"
+ key="resource-emt-clli == $edge-device-clli and speed >= $uni-cir-value*1000"
+ pfx="asePort">
+
+ <outcome value="success">
+ <return status="success">
+ <parameter name="uni-circuit-id" value="$asePort.uni_circuit_id" />
+ </return>
+ </outcome>
+ <outcome value="Other">
+ <return status="failure">
+ <parameter name="error-code" value="1010" />
+ <parameter name="error-message" value="No ports found that match criteria" />
+ </return>
+ </outcome>
+ </reserve>
+ </outcome>
+</switch>
++-------------------+
+
+* Device Management
+
+**Configure node
+
+*** Description
+
+ A <<configure>> node is used to configure a device.
+
+*** Attributes
+
+*--------------*-------+
+| <<adaptor>> | Fully qualified Java class of resource adaptor to be used
+*--------------*-------+
+| <<activate>> | Activate device/interface, for devices that support a separate activation step.
+*--------------*-------+
+| <<key>> | SQL-like string specifying criteria for item to configure
+*--------------*-------+
+
+*** Parameters
+
+ Specific to device adaptor.
+
+*** Outcomes
+
+*-----------*-------+
+| <<success>> | Device successfully configured
+*-----------*-------+
+| <<not-found>> | Element to be configured does not exist.
+*-----------*--------+
+| <<not-ready>> | Element is not in a state where it can be configured/activated
+*-----------*-------+
+| <<already-active>> | Attempt to activate element that is already active
+*-----------*-------+
+| <<failure>> | Configure failed for some other reason
+*-----------*-------+
+
+*** Example
+
++-------------------+
+<configure adaptor="org.onap.ccsdk.sli.adaptors.emt.EmtAdaptor"
+ key="$uni-circuit-id" activate="true">
+ <parameter name="circuit.id" value="$uni-circuit-id" />
+ <parameter name="subscriber.name" value="$subscriber-name" />
+ <parameter name="emt.clli" value="$edge-device-clli" />
+ <parameter name="port.tagging" value="$port-tagging" />
+ <parameter name="port.mediaSpeed" value="$media-speed" />
+ <parameter name="location.state" value="$uni-location-state" />
+ <parameter name="location.city" value="$uni-location-city" />
+ <parameter name="cosCategory" value="$cos-category" />
+ <parameter name="gosProfile" value="$gos-profile" />
+ <parameter name="lldp" value="$asePort.resource-lldp" />
+ <parameter name="mtu" value="$asePort.resource-mtu" />
+ <outcome value="success">
+ <block>
+ <record plugin="org.onap.ccsdk.sli.core.sli.recording.FileRecorder">
+ <parameter name="file" value="/tmp/sample_r1.log" />
+ <parameter name="field1" value="__TIMESTAMP__"/>
+ <parameter name="field2" value="ACTIVE"/>
+ <parameter name="field3" value="$uni-circuit-id"/>
+ </record>
+ <return status="success">
+ <parameter name="edge-device-clli" value="$asePort.resource-emt-clli" />
+ </return>
+ </block>
+ </outcome>
+ <outcome value="already-active">
+ <return status="failure">
+ <parameter name="error-code" value="1590" />
+ <parameter name="error-message" value="Port already active" />
+ </return>
+ </outcome>
+ <outcome value="Other">
+ <return status="failure">
+ <parameter name="error-code" value="1542" />
+ <parameter name="error-message" value="Activation failure" />
+ </return>
+ </outcome>
+</configure>
++-------------------+
+
+* Java Plugin Support
+
+**Execute node
+
+*** Description
+
+ An <<execute>> node is used to execute Java code supplied as a plugin
+
+*** Attributes
+
+*--------------*-------+
+| <<plugin>> | Fully qualified Java class of plugin to be used
+*--------------*-------+
+| <<method>> | Name of method in the plugin class to execute. Method must return void, and take 2 arguments: a Map (for parameters) and a SvcLogicContext (to allow plugin read/write access to context memory)
+*--------------*-------+
+
+*** Parameters
+
+ Specific to plugin / method
+
+*** Outcomes
+
+*-----------*-------+
+| <<success>> | Device successfully configured
+*-----------*-------+
+| <<not-found>> | Plugin class could not be loaded
+*-----------*--------+
+| <<unsupported-method>> | Named method taking (Map, SvcLogicContext) could not be found
+*-----------*-------+
+| <<failure>> | Configure failed for some other reason
+*-----------*-------+
+
+*** Example
+
++-------------------+
+<execute plugin="org.onap.ccsdk.sli.plugins.HelloWorld"
+ method="log">
+ <parameter name="message" value="Hello, world!" />
+ <outcome value="success">
+ <return status="success"/>
+ </outcome>
+ <outcome value="not-found">
+ <return status="failure">
+ <parameter name="error-code" value="1590" />
+ <parameter name="error-message" value="Could not locate plugin" />
+ </return>
+ </outcome>
+ <outcome value="Other">
+ <return status="failure">
+ <parameter name="error-code" value="1542" />
+ <parameter name="error-message" value="Internal error" />
+ </return>
+ </outcome>
+</execute>
++-------------------+
+
+* Recording
+
+** Record node
+
+*** Description
+
+ A <<record>> node is used to record an event. For example, this might be used
+ to log provisioning events.
+
+*** Attributes
+
+*--------------*-------+
+| <<plugin>> | Fully qualified Java class to handle recording.
+*--------------*-------+
+
+
+*** Parameters
+
+ Parameters will depend on the plugin being used. For the FileRecorder class,
+ the parameters are as follows
+
+*------------*-----------+
+| <<file>> | The file to which the record should be written
+*------------*-----------+
+| <<field1>> | First field to write. There will be <<field>> parameters for each field to write, from <<field1>> through <<fieldN>>. A special value __TIMESTAMP__ may be assigned to a field to insert the current timestamp
+*------------*-----------+
+
+
+*** Outcomes
+
+*----------*---------+
+| <<success>> | Record successfully written
+*----------*---------+
+| <<failure>> | Record could not be successfully written
+*----------*---------+
+
+*** Example
+
++-------------------+
+<record plugin="org.onap.ccsdk.sli.core.sli.recording.FileRecorder">
+ <parameter name="file" value="/tmp/sample_r1.log" />
+ <parameter name="field1" value="__TIMESTAMP__"/>
+ <parameter name="field2" value="ACTIVE"/>
+ <parameter name="field3" value="$uni-circuit-id"/>
+</record>
++-------------------+
+
+* Resource Management
+
+** Delete node
+
+*** Description
+
+ A <<delete>> node is used to delete a resource from the local resource inventory.
+
+*** Attributes
+
+*--------------*-------+
+| <<plugin>> | Fully qualified Java class of resource adaptor to be used
+*--------------*-------+
+| <<resource>> | Type of resource to delete
+*--------------*-------+
+| <<key>> | SQL-like string specifying key to delete
+*--------------*-------+
+
+*** Parameters
+
+ None
+
+*** Outcomes
+
+*-----------*-------+
+| <<success>> | Resource specified deleted successfully.
+*-----------*-------+
+| <failure>> | Resource specified was not deleted
+*-----------*-------+
+
+*** Example
+
++-------------------+
+<delete plugin="org.onap.ccsdk.sli.adaptors.samplesvc.SampleServiceResource"
+ resource="ase-port"
+ key="uni_circuit_id == $uni-circuit-id">
+ <outcome value="true">
+ <return status="success"/>
+ </outcome>
+ <outcome value="false">
+ <return status="failure"/>
+ </outcome>
+</delete>
++-------------------+
+
+
+** Exists node
+
+*** Description
+
+ An <<exists>> node is used to determine whether a particular
+ instance of a resource exists. For example, this might be
+ used to test whether a particular switch CLLI is provisioned.
+
+*** Attributes
+
+*--------------*-------+
+| <<plugin>> | Fully qualified Java class of resource adaptor to be used
+*--------------*-------+
+| <<resource>> | Type of resource to check
+*--------------*-------+
+| <<key>> | SQL-like string specifying key to check for
+*--------------*-------+
+
+*** Parameters
+
+ None
+
+*** Outcomes
+
+*-----------*-------+
+| <<true>> | Resource specified exists.
+*-----------*-------+
+| <<false>> | Resource specified is unknown
+*-----------*-------+
+
+*** Example
+
++-------------------+
+<exists plugin="org.onap.ccsdk.sli.adaptors.samplesvc.SampleServiceResource"
+ resource="ase-port"
+ key="uni_circuit_id == $uni-circuit-id">
+ <outcome value="true">
+ <return status="success"/>
+ </outcome>
+ <outcome value="false">
+ <return status="failure"/>
+ </outcome>
+</exists>
++-------------------+
+
+** Get-resource node
+
+*** Description
+
+ A <<get-resource>> node is used to retrieve information about a
+ particular resource and make it available to other nodes in the
+ service logic tree. For example, this might be used to
+ retrieve information about a particular uni-port.
+
+*** Attributes
+
+*--------------*-------+
+| <<plugin>> | Fully qualified Java class of resource adaptor to be used
+*--------------*-------+
+| <<resource>> | Type of resource to retrieve
+*--------------*-------+
+| <<key>> | SQL-like string specifying criteria for retrieval
+*--------------*-------+
+| <<pfx>> | Prefix to add to context variable names set for data retrieved
+*--------------*-------+
+| <<select>> | String to specify, if key matches multiple entries, which entry should take precedence
+*--------------*-------+
+| <<order-by>> | Prefix to add to context variable names set for data retrieved
+*--------------*-------+
+
+*** Parameters
+
+ None
+
+
+*** Outcomes
+
+*-----------*-------+
+| <<success>> | Resource successfully retrieved
+*-----------*-------+
+| <<not-found>> | Resource referenced does not exist
+*-----------*-------+
+| <<failure>> | Resource retrieve failed for some other reason
+*-----------*-------+
+
+*** Example
+
++-------------------+
+<get-resource plugin="org.onap.ccsdk.sli.adaptors.samplesvc.SampleServiceResource"
+ resource="ase-port"
+ key="uni_circuit_id == $uni-circuit-id"
+ pfx="current-port">
+ <outcome value="success">
+ <return status="success"/>
+ </outcome>
+ <outcome value="not-found">
+ <return status="failure"/>
+ </outcome>
+ <outcome value="failure">
+ <return status="failure"/>
+ </outcome>
+</get-resource>
++-------------------+
+
+** Is-available node
+
+*** Description
+
+ An <<is-available>> node is used to determine whether a particular
+ type of resource is available. For example, this might be used to
+ test whether any ports are available for assignment on a particular switch.
+
+*** Attributes
+
+*--------------*-------+
+| <<plugin>> | Fully qualified Java class of resource adaptor to be used
+*--------------*-------+
+| <<resource>> | Type of resource to check
+*--------------*-------+
+| <<key>> | SQL-like string specifying key to check for
+*--------------*-------+
+| <<pfx>> | Prefix to add to context variable names set for data retrieved
+*--------------*-------+
+
+*** Parameters
+
+ None
+
+*** Outcomes
+
+*-----------*-------+
+| <<true>> | Resource requested is available
+*-----------*-------+
+| <<false>> | Resource requested is not available
+*-----------*-------+
+
+*** Example
+
++-------------------+
+<is-available plugin="org.onap.ccsdk.sli.adaptors.samplesvc.SampleServiceResource"
+ resource="ase-port"
+ key="resource-emt-clli == $edge-device-clli and speed >= $uni-cir-value">
+ <outcome value="true">
+ <return status="success"/>
+ </outcome>
+ <outcome value="false">
+ <return status="failure"/>
+ </outcome>
+</is-available>
++-------------------+
+
+** Notify node
+
+*** Description
+
+ A <<notify>> node is used to inform an external application (e.g. A&AI) that a resource was
+ updated.
+
+*** Attributes
+
+*--------------*-------+
+| <<plugin>> | Fully qualified Java class of resource adaptor to be used
+*--------------*-------+
+| <<resource>> | Identifies resource that was updated
+*--------------*-------+
+| <<action>> | Action that triggered notification to be sent (ADD/UPDATE/DELETE)
+*--------------*-------+
+
+*** Parameters
+
+ None
+
+*** Outcomes
+
+*-----------*-------+
+| <<success>> | Notification was successful
+*-----------*-------+
+| <<failure>> | Notification failed is not available
+*-----------*-------+
+
+*** Example
+
++-------------------+
+<notify plugin="org.onap.ccsdk.sli.adaptors.samplesvc.SampleServiceResource"
+ resource="ase-port"
+ action="ADD">
+ <outcome value="success">
+ <return status="success"/>
+ </outcome>
+ <outcome value="Other">
+ <return status="failure"/>
+ </outcome>
+</notify>
++-------------------+
+
+** Release node
+
+*** Description
+
+ A <<release>> node is used to mark a resource as no longer in use, and thus
+ available for assignment.
+
+*** Attributes
+
+*--------------*-------+
+| <<plugin>> | Fully qualified Java class of resource adaptor to be used
+*--------------*-------+
+| <<resource>> | Type of resource to release
+*--------------*-------+
+| <<key>> | SQL-like string specifying key to check of resource to release
+*--------------*-------+
+
+*** Parameters
+
+ None
+
+*** Outcomes
+
+*-----------*-------+
+| <<success>> | Resource successfully released
+*-----------*-------+
+| <<not-found>> | Resource referenced does not exist
+*-----------*-------+
+| <<failure>> | Resource release failed for some other reason
+*-----------*-------+
+
+*** Example
+
++-------------------+
+<release plugin="org.onap.ccsdk.sli.adaptors.SampleServiceResource"
+ resource="ase-port"
+ key="uni_circuit_id == $uni-circuit-id">
+ <outcome value="success">
+ <return status="success"/>
+ </outcome>
+ <outcome value="not-found">
+ <return status="failure"/>
+ </outcome>
+ <outcome value="failure">
+ <return status="failure"/>
+ </outcome>
+</release>
++-------------------+
+
+
+** Reserve node
+
+*** Description
+
+ A <<reserve>> node is used to reserve a particular
+ type of resource.. For example, this might be used to
+ reserve a port on a particular switch.
+
+*** Attributes
+
+*--------------*-------+
+| <<plugin>> | Fully qualified Java class of resource adaptor to be used
+*--------------*-------+
+| <<resource>> | Type of resource to reserve
+*--------------*-------+
+| <<key>> | SQL-like string specifying criteria for reservation
+*--------------*-------+
+| <<select>> | String to specify, if <<key>> matches multiple entries, which entry should take precedence
+*--------------*-------+
+
+*** Parameters
+
+ None
+
+*** Outcomes
+
+*-----------*-------+
+| <<success>> | Resource requested was successfully reserved
+*-----------*-------+
+| <<failure>> | Resource requested was not successfully reserved
+*-----------*-------+
+
+*** Example
+
++-------------------+
+<reserve plugin="org.onap.ccsdk.sli.adaptors.samplesvc.SampleServiceResource"
+ resource="ase-port"
+ key="resource-emt-clli == $edge-device-clli and speed >= $uni-cir-value"
+ select="min(speed)">
+ <outcome value="success">
+ <return status="success"/>
+ </outcome>
+ <outcome value="failure">
+ <return status="failure"/>
+ </outcome>
+</reserve>
++-------------------+
+
+** Save node
+
+*** Description
+
+ A <<save>> node is used to save information about a
+ particular resource to persistent storage. For example, this might be used to
+ save information about a particular uni-port.
+
+*** Attributes
+
+*--------------*-------+
+| <<plugin>> | Fully qualified Java class of resource adaptor to be used
+*--------------*-------+
+| <<resource>> | Type of resource to save
+*--------------*-------+
+| <<key>> | SQL-like string specifying criteria for retrieval
+*--------------*-------+
+| <<force>> | If "true", save resource even if this resource is already stored in persistent storage
+*--------------*-------+
+| <<pfx>> | Prefix to be prepended to variable names, when attributes are set in SvcLogicContext
+*--------------*-------+
+
+*** Parameters
+
+ Values to save (columns) are specified as parameters, with each name
+ corresponding to a column name and each value corresponding to the
+ value to set.
+
+*** Outcomes
+
+*-----------*-------+
+| <<success>> | Resource successfully saved
+*-----------*-------+
+| <<failure>> | Resource save failed
+*-----------*-------+
+
+*** Example
+
++-------------------+
+<save plugin="`$sample-resource-plugin`" resource="vnf"
+ key="vnf-name = $requests.vnf.vnf-name" force="true"
+ pfx="requests.vnf">
+ <parameter name="vnf-name"
+ value="`$requests.cust-country-code + $requests.cust-id + $requests.cust-city + $requests.cust-state + '001VCE'`" />
+ <parameter name="vnf-type" value="vce" />
+ <parameter name="orchestration-status" value="pending-create" />
+ <parameter name="heat-stack-id" value="`$requests.heat-stack-id`" />
+ <parameter name="mso-catalog-key" value="`$requests.mso-catalog-key`" />
+ <parameter name="oam-ipv4-address" value="`$vce-ipv4-oam-addr.ipv4-addr`" />
+</save>
++-------------------+
+
+** Update node
+
+*** Description
+
+ An <<update>> node is used to update information about a
+ particular resource to persistent storage.
+
+*** Attributes
+
+*--------------*-------+
+| <<plugin>> | Fully qualified Java class of resource adaptor to be used
+*--------------*-------+
+| <<resource>> | Type of resource to update
+*--------------*-------+
+| <<key>> | SQL-like string specifying criteria for retrieval
+*--------------*-------+
+| <<pfx>> | Prefix to be prepended to variable names, when attributes are set in SvcLogicContext
+*--------------*-------+
+
+*** Parameters
+
+ Values to save (columns) are specified as parameters, with each name
+ corresponding to a column name and each value corresponding to the
+ value to set.
+
+*** Outcomes
+
+*-----------*-------+
+| <<success>> | Resource successfully saved
+*-----------*-------+
+| <<failure>> | Resource save failed
+*-----------*-------+
+
+*** Example
+
++-------------------+
+<update plugin="`$sample-resource-plugin`" resource="vnf"
+ key="vnf-name = $requests.vnf.vnf-name"
+ pfx="requests.vnf">
+ <parameter name="vnf-name"
+ value="`$requests.cust-country-code + $requests.cust-id + $requests.cust-city + $requests.cust-state + '001VCE'`" />
+ <parameter name="vnf-type" value="vce" />
+ <parameter name="orchestration-status" value="pending-create" />
+ <parameter name="heat-stack-id" value="`$requests.heat-stack-id`" />
+ <parameter name="mso-catalog-key" value="`$requests.mso-catalog-key`" />
+ <parameter name="oam-ipv4-address" value="`$vce-ipv4-oam-addr.ipv4-addr`" />
+</update>
++-------------------+
+
diff --git a/core/src/site/site.xml b/core/src/site/site.xml
new file mode 100644
index 000000000..af081b167
--- /dev/null
+++ b/core/src/site/site.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+ ============LICENSE_START=======================================================
+ ONAP : CCSDK
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property. All rights
+ reserved.
+ ================================================================================
+ 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.
+ ============LICENSE_END=========================================================
+ -->
+
+<project>
+ <body>
+ <links>
+ <item name="Built-in Nodes" href="nodes.html" />
+ </links>
+ <menu ref="modules"/>
+
+ <menu ref="reports"/>
+
+ </body>
+</project>
diff --git a/core/utils/installer/pom.xml b/core/utils/installer/pom.xml
new file mode 100755
index 000000000..829a33051
--- /dev/null
+++ b/core/utils/installer/pom.xml
@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>odlparent-lite</artifactId>
+ <version>2.1.0-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>utils-installer</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>pom</packaging>
+
+ <name>ccsdk-sli-core :: utils :: ${project.artifactId}</name>
+
+ <properties>
+ <application.name>ccsdk-slicore-utils</application.name>
+ <features.boot>${application.name}</features.boot>
+ <features.repositories>mvn:org.onap.ccsdk.sli.core/${features.boot}/${project.version}/xml/features</features.repositories>
+ <include.transitive.dependencies>false</include.transitive.dependencies>
+ </properties>
+
+ <dependencies>
+
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>utils-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>maven-repo-zip</id>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ <phase>package</phase>
+ <configuration>
+ <attach>true</attach>
+ <finalName>stage/${application.name}-${project.version}</finalName>
+ <descriptors>
+ <descriptor>src/assembly/assemble_mvnrepo_zip.xml</descriptor>
+ </descriptors>
+ <appendAssemblyId>true</appendAssemblyId>
+ </configuration>
+ </execution>
+ <execution>
+ <id>installer-zip</id>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ <phase>package</phase>
+ <configuration>
+ <attach>true</attach>
+ <finalName>${application.name}-${project.version}-installer</finalName>
+ <descriptors>
+ <descriptor>src/assembly/assemble_installer_zip.xml</descriptor>
+ </descriptors>
+ <appendAssemblyId>false</appendAssemblyId>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>copy-dependencies</id>
+ <goals>
+ <goal>copy-dependencies</goal>
+ </goals>
+ <phase>prepare-package</phase>
+ <configuration>
+ <transitive>false</transitive>
+ <outputDirectory>${project.build.directory}/assembly/system</outputDirectory>
+ <overWriteReleases>false</overWriteReleases>
+ <overWriteSnapshots>true</overWriteSnapshots>
+ <overWriteIfNewer>true</overWriteIfNewer>
+ <useRepositoryLayout>true</useRepositoryLayout>
+ <addParentPoms>false</addParentPoms>
+ <copyPom>false</copyPom>
+ <includeGroupIds>org.onap.ccsdk.sli,org.apache.tomcat</includeGroupIds>
+ <excludeArtifactIds>sli-common,sli-provider</excludeArtifactIds>
+ <scope>provided</scope>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <artifactId>maven-resources-plugin</artifactId>
+ <version>2.6</version>
+ <executions>
+ <execution>
+ <id>copy-version</id>
+ <goals>
+ <goal>copy-resources</goal>
+ </goals><!-- here the phase you need -->
+ <phase>validate</phase>
+ <configuration>
+ <outputDirectory>${basedir}/target/stage</outputDirectory>
+ <resources>
+ <resource>
+ <directory>src/main/resources/scripts</directory>
+ <includes>
+ <include>install-feature.sh</include>
+ </includes>
+ <filtering>true</filtering>
+ </resource>
+ </resources>
+ </configuration>
+ </execution>
+
+ </executions>
+ </plugin>
+
+ </plugins>
+ </build>
+</project>
diff --git a/core/utils/installer/src/assembly/assemble_installer_zip.xml b/core/utils/installer/src/assembly/assemble_installer_zip.xml
new file mode 100755
index 000000000..a6a22a9ba
--- /dev/null
+++ b/core/utils/installer/src/assembly/assemble_installer_zip.xml
@@ -0,0 +1,39 @@
+<!-- Defines how we build the .zip file which is our distribution. -->
+
+<assembly
+ xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
+ <id>bin</id>
+
+ <formats>
+ <format>zip</format>
+ </formats>
+
+ <!-- we want "system" and related files right at the root level
+ as this file is suppose to be unzip on top of a karaf
+ distro. -->
+ <includeBaseDirectory>false</includeBaseDirectory>
+
+ <fileSets>
+ <fileSet>
+ <directory>target/stage/</directory>
+ <outputDirectory>${application.name}</outputDirectory>
+ <fileMode>755</fileMode>
+ <includes>
+ <include>*.sh</include>
+ </includes>
+ </fileSet>
+ <fileSet>
+ <directory>target/stage/</directory>
+ <outputDirectory>${application.name}</outputDirectory>
+ <fileMode>644</fileMode>
+ <excludes>
+ <exclude>*.sh</exclude>
+ </excludes>
+ </fileSet>
+ </fileSets>
+
+
+
+</assembly>
diff --git a/core/utils/installer/src/assembly/assemble_mvnrepo_zip.xml b/core/utils/installer/src/assembly/assemble_mvnrepo_zip.xml
new file mode 100755
index 000000000..86b07f1f3
--- /dev/null
+++ b/core/utils/installer/src/assembly/assemble_mvnrepo_zip.xml
@@ -0,0 +1,29 @@
+<!-- Defines how we build the .zip file which is our distribution. -->
+
+<assembly
+ xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
+ <id>repo</id>
+
+ <formats>
+ <format>zip</format>
+ </formats>
+
+ <!-- we want "system" and related files right at the root level
+ as this file is suppose to be unzip on top of a karaf
+ distro. -->
+ <includeBaseDirectory>false</includeBaseDirectory>
+
+ <fileSets>
+ <fileSet>
+ <directory>target/assembly/</directory>
+ <outputDirectory>.</outputDirectory>
+ <excludes>
+ </excludes>
+ </fileSet>
+ </fileSets>
+
+
+
+</assembly>
diff --git a/core/utils/installer/src/main/resources/scripts/install-feature.sh b/core/utils/installer/src/main/resources/scripts/install-feature.sh
new file mode 100644
index 000000000..e16e79a12
--- /dev/null
+++ b/core/utils/installer/src/main/resources/scripts/install-feature.sh
@@ -0,0 +1,18 @@
+#!/bin/bash
+
+ODL_HOME=${ODL_HOME:-/opt/opendaylight/current}
+ODL_KARAF_CLIENT=${ODL_KARAF_CLIENT:-${ODL_HOME}/bin/client}
+INSTALLERDIR=$(dirname $0)
+
+REPOZIP=${INSTALLERDIR}/${features.boot}-${project.version}.zip
+
+if [ -f ${REPOZIP} ]
+then
+ unzip -d ${ODL_HOME} ${REPOZIP}
+else
+ echo "ERROR : repo zip ($REPOZIP) not found"
+ exit 1
+fi
+
+${ODL_KARAF_CLIENT} feature:repo-add ${features.repositories}
+${ODL_KARAF_CLIENT} feature:install ${features.boot}
diff --git a/core/utils/pom.xml b/core/utils/pom.xml
new file mode 100755
index 000000000..b8c196cff
--- /dev/null
+++ b/core/utils/pom.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>odlparent-lite</artifactId>
+ <version>2.1.0-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>utils</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>pom</packaging>
+
+ <name>ccsdk-sli-core :: utils</name>
+ <description>Utilities used across sli-core</description>
+ <organization>
+ <name>ONAP</name>
+ </organization>
+
+ <modules>
+ <module>provider</module>
+ <module>installer</module>
+ </modules>
+</project>
diff --git a/core/utils/provider/pom.xml b/core/utils/provider/pom.xml
new file mode 100644
index 000000000..3d4fd856d
--- /dev/null
+++ b/core/utils/provider/pom.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>binding-parent</artifactId>
+ <version>2.1.0-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>utils-provider</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>bundle</packaging>
+
+ <name>ccsdk-sli-core :: utils :: ${project.artifactId}</name>
+ <description>
+ The SLI Core Utilities Package provides common functionality for setting up SLI connectivity.
+ </description>
+ <organization>
+ <name>ONAP</name>
+ </organization>
+
+ <dependencies>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.core</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ <!-- Testing Dependencies -->
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>${junit.version}</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/DefaultFileResolver.java b/core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/DefaultFileResolver.java
new file mode 100644
index 000000000..8938aa6e7
--- /dev/null
+++ b/core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/DefaultFileResolver.java
@@ -0,0 +1,61 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * onap
+ * ================================================================================
+ * Copyright (C) 2016 - 2017 ONAP
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.utils;
+
+import java.io.File;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Optional;
+
+/**
+ * Resolves dblib properties files relative to the default file path. In Unix, this is represented by:
+ * <code>/opt/sdnc/data/properties</code>
+ */
+public abstract class DefaultFileResolver implements PropertiesFileResolver {
+
+ private final String successMessage;
+
+ private final Path propertyPath;
+
+ public DefaultFileResolver(final String successMessage, final Path propertyPath) {
+ this.successMessage = successMessage;
+ this.propertyPath = propertyPath;
+ }
+
+ /**
+ * Parse a properties file location based on the default properties location
+ *
+ * @return an Optional File containing the location if it exists, or an empty Optional
+ */
+ @Override
+ public Optional<File> resolveFile(final String filename) {
+ final File fileFromDefaultDblibDir = propertyPath.resolve(filename).toFile();
+ if (fileFromDefaultDblibDir.exists()) {
+ return Optional.of(fileFromDefaultDblibDir);
+ }
+ return Optional.empty();
+ }
+
+ @Override
+ public String getSuccessfulResolutionMessage() {
+ return this.successMessage;
+ }
+}
diff --git a/core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/EnvVarFileResolver.java b/core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/EnvVarFileResolver.java
new file mode 100755
index 000000000..518fb30d3
--- /dev/null
+++ b/core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/EnvVarFileResolver.java
@@ -0,0 +1,76 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * onap
+ * ================================================================================
+ * Copyright (C) 2016 - 2017 ONAP
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.utils;
+
+import com.google.common.base.Strings;
+
+import java.io.File;
+import java.nio.file.Paths;
+import java.util.Optional;
+
+/**
+ * Resolves properties files relative to the directory identified by the <code>SDNC_CONFIG_DIR</code>
+ * environment variable. If a system property with the same name is set it is given precedence.
+ */
+public abstract class EnvVarFileResolver implements PropertiesFileResolver {
+
+ /**
+ * Key for environment variable representing the configuration directory
+ */
+ private final String propertyKey;
+
+ private final String successMessage;
+
+ public EnvVarFileResolver(final String successMessage, final String propertyKey) {
+ this.successMessage = successMessage;
+ this.propertyKey = propertyKey;
+ }
+
+ /**
+ * Parse a properties file location based on System environment variable
+ *
+ * @return an Optional File containing the location if it exists, or an empty Optional
+ */
+ @Override
+ public Optional<File> resolveFile(final String filename) {
+ // attempt to read the system property first
+ String propDirectoryFromEnvVariable = System.getProperty(propertyKey);
+
+ if(propDirectoryFromEnvVariable == null) {
+ // attempt to resolve the property directory from the corresponding environment variable
+ propDirectoryFromEnvVariable = System.getenv(propertyKey);
+ }
+
+ final File fileFromEnvVariable;
+ if (!Strings.isNullOrEmpty(propDirectoryFromEnvVariable)) {
+ fileFromEnvVariable = Paths.get(propDirectoryFromEnvVariable).resolve(filename).toFile();
+ if(PathValidator.isValidPropertiesPath(fileFromEnvVariable.getAbsolutePath()) && fileFromEnvVariable.exists()) {
+ return Optional.of(fileFromEnvVariable);
+ }
+ }
+ return Optional.empty();
+ }
+
+ @Override
+ public String getSuccessfulResolutionMessage() {
+ return this.successMessage;
+ }
+}
diff --git a/core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/JREFileResolver.java b/core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/JREFileResolver.java
new file mode 100755
index 000000000..c4a4fca47
--- /dev/null
+++ b/core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/JREFileResolver.java
@@ -0,0 +1,111 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * onap
+ * ================================================================================
+ * Copyright (C) 2016 - 2017 ONAP
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.utils;
+
+import java.io.File;
+import java.io.InputStream;
+import java.net.URL;
+import java.nio.file.CopyOption;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.StandardCopyOption;
+import java.util.Optional;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.FrameworkUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Resolves project properties files relative to the directory identified by the JRE property
+ * <code>dblib.properties</code>.
+ */
+public class JREFileResolver implements PropertiesFileResolver {
+
+ /**
+ * Key for JRE argument representing the configuration directory
+ */
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(JREFileResolver.class);
+ private final String successMessage;
+ private final Class<?> clazz;
+
+ public JREFileResolver(final String successMessage, final Class<?> clazz) {
+ this.successMessage = successMessage;
+ this.clazz = clazz;
+ }
+
+ /**
+ * Parse a properties file location based on JRE argument
+ *
+ * @return an Optional File containing the location if it exists, or an empty Optional
+ */
+ @Override
+ public Optional<File> resolveFile(final String filename) {
+
+ try {
+
+ final Bundle bundle = FrameworkUtil.getBundle(this.clazz);
+ if (bundle == null) {
+ return Optional.empty();
+ }
+
+ URL jreArgumentEntry = bundle.getEntry(filename);
+ if (jreArgumentEntry == null) {
+ return Optional.empty();
+ }
+
+
+ final File dataFile = bundle.getDataFile(filename);
+ if(dataFile.exists()) {
+ dataFile.delete();
+ }
+
+ try (InputStream input = jreArgumentEntry.openStream()){
+ Files.copy(input, dataFile.toPath());
+ } catch(Exception exc) {
+ return Optional.empty();
+ }
+
+ return Optional.of(dataFile);
+ } catch (final NoClassDefFoundError e) {
+ LOGGER.info("Getting /{} embedded with {}", filename, clazz.getCanonicalName());
+ try (InputStream input = clazz.getResourceAsStream("/"+filename)) {
+ File propFile = File.createTempFile("tmp", ".properties", null);
+ LOGGER.info("Copying /{} to {}", filename, propFile.getAbsolutePath());
+ Files.copy(input, propFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
+ return Optional.of(propFile);
+ } catch (Exception e1) {
+ LOGGER.info("Caught exception getting {} embedded in jar", filename, e1);
+ return Optional.empty();
+ }
+ }
+ catch(final Exception e) {
+ return Optional.empty();
+ }
+
+ }
+
+ @Override
+ public String getSuccessfulResolutionMessage() {
+ return this.successMessage;
+ }
+}
diff --git a/core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/KarafRootFileResolver.java b/core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/KarafRootFileResolver.java
new file mode 100644
index 000000000..0cb754504
--- /dev/null
+++ b/core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/KarafRootFileResolver.java
@@ -0,0 +1,63 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * onap
+ * ================================================================================
+ * Copyright (C) 2016 - 2017 ONAP
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.utils;
+
+import java.io.File;
+import java.net.URL;
+import java.util.Optional;
+
+/**
+ * Resolves dblib properties files relative to the karaf root directory.
+ */
+public class KarafRootFileResolver implements PropertiesFileResolver {
+
+ final Object provider;
+
+ private final String successMessage;
+
+ public KarafRootFileResolver(final String successMessage, final Object provider) {
+ this.successMessage = successMessage;
+ this.provider = provider;
+ }
+
+ /**
+ * Parse a properties file location relative to the karaf root
+ *
+ * @return an Optional File containing the location if it exists, or an empty Optional
+ */
+ @Override
+ public Optional<File> resolveFile(final String filename) {
+ final URL fromKarafRoot = provider.getClass().getResource(filename);
+ if (fromKarafRoot != null) {
+ final File propertiesFile = new File(fromKarafRoot.getFile());
+ if (propertiesFile.exists()) {
+ return Optional.of(propertiesFile);
+ }
+ return Optional.empty();
+ }
+ return Optional.empty();
+ }
+
+ @Override
+ public String getSuccessfulResolutionMessage() {
+ return this.successMessage;
+ }
+}
diff --git a/core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/PathValidator.java b/core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/PathValidator.java
new file mode 100644
index 000000000..08f0fc050
--- /dev/null
+++ b/core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/PathValidator.java
@@ -0,0 +1,17 @@
+package org.onap.ccsdk.sli.core.utils;
+import java.util.regex.Pattern;
+
+public class PathValidator {
+ public static boolean isValidXmlPath(String path) {
+ Pattern allowList = Pattern.compile("[-.\\w/\\/]+\\.xml$");
+ return (allowList.matcher(path).matches());
+ }
+ public static boolean isValidPropertiesPath(String path) {
+ Pattern allowList = Pattern.compile("[-.\\w/\\/]+\\.properties$");
+ return (allowList.matcher(path).matches());
+ }
+ public static boolean isValidFilePath(String path) {
+ Pattern allowList = Pattern.compile("[-.\\w/\\/]+$");
+ return (allowList.matcher(path).matches());
+ }
+}
diff --git a/core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/PropertiesFileResolver.java b/core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/PropertiesFileResolver.java
new file mode 100644
index 000000000..bfb417dca
--- /dev/null
+++ b/core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/PropertiesFileResolver.java
@@ -0,0 +1,45 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * onap
+ * ================================================================================
+ * Copyright (C) 2016 - 2017 ONAP
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.utils;
+
+import java.io.File;
+import java.util.Optional;
+
+/**
+ * Strategy for resolving dblib properties.
+ */
+public interface PropertiesFileResolver {
+
+ /**
+ * Resolve dblib properties file.
+ *
+ * @param filename the name of the file to look for at the specific location.
+ * @return An optional File or empty.
+ */
+ Optional<File> resolveFile(final String filename);
+
+ /**
+ * A success message, used only for logging now.
+ *
+ * @return a success message, used only for logging now.
+ */
+ String getSuccessfulResolutionMessage();
+}
diff --git a/core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/common/BundleContextFileResolver.java b/core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/common/BundleContextFileResolver.java
new file mode 100755
index 000000000..356009f3f
--- /dev/null
+++ b/core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/common/BundleContextFileResolver.java
@@ -0,0 +1,82 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * onap
+ * ================================================================================
+ * Copyright (C) 2016 - 2017 ONAP
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.utils.common;
+
+import java.io.File;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Optional;
+
+import org.onap.ccsdk.sli.core.utils.PropertiesFileResolver;
+import org.osgi.framework.FrameworkUtil;
+import org.slf4j.LoggerFactory;
+
+import com.google.common.base.Strings;
+
+/**
+ * Resolves properties files from runtime property value <code>SDNC_CONFIG_DIR</code> defined in the osgi properties.
+ */
+public class BundleContextFileResolver implements PropertiesFileResolver {
+
+ /**
+ * Key for osgi variable representing the configuration directory
+ */
+ private static final String SDNC_CONFIG_DIR_PROP_KEY = "SDNC_CONFIG_DIR";
+
+ private final String successMessage;
+ private final Class<?> clazz;
+
+ public BundleContextFileResolver(final String successMessage, final Class<?> clazz) {
+ this.successMessage = successMessage;
+ this.clazz = clazz;
+ }
+
+ /**
+ * Parse a properties file location based on JRE argument
+ *
+ * @return an Optional File containing the location if it exists, or an empty Optional
+ */
+ @Override
+ public Optional<File> resolveFile(final String filename) {
+ try {
+ if (FrameworkUtil.getBundle(clazz) == null) {
+ return Optional.empty();
+ } else {
+ final String pathProperty = FrameworkUtil.getBundle(this.clazz).getBundleContext()
+ .getProperty(SDNC_CONFIG_DIR_PROP_KEY);
+ if (Strings.isNullOrEmpty(pathProperty)) {
+ return Optional.empty();
+ }
+ final Path dblibPath = Paths.get(pathProperty);
+ return Optional.of(dblibPath.resolve(filename).toFile());
+
+ }
+ } catch (Exception|NoClassDefFoundError e) {
+ LoggerFactory.getLogger(this.getClass()).error("", e);
+ return Optional.empty();
+ }
+ }
+
+ @Override
+ public String getSuccessfulResolutionMessage() {
+ return this.successMessage;
+ }
+}
diff --git a/core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/common/CoreDefaultFileResolver.java b/core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/common/CoreDefaultFileResolver.java
new file mode 100755
index 000000000..4d7e90261
--- /dev/null
+++ b/core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/common/CoreDefaultFileResolver.java
@@ -0,0 +1,41 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * onap
+ * ================================================================================
+ * Copyright (C) 2016 - 2017 ONAP
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.utils.common;
+
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import org.onap.ccsdk.sli.core.utils.DefaultFileResolver;
+
+/**
+ * Resolve properties file location based on the default directory name.
+ */
+public class CoreDefaultFileResolver extends DefaultFileResolver {
+
+ /**
+ * Default path to look for the configuration directory
+ */
+ private static final Path DEFAULT_DBLIB_PROP_DIR = Paths.get("/opt", "sdnc", "data", "properties");
+
+ public CoreDefaultFileResolver(final String successMessage) {
+ super(successMessage, DEFAULT_DBLIB_PROP_DIR);
+ }
+}
diff --git a/core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/common/SdncConfigEnvVarFileResolver.java b/core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/common/SdncConfigEnvVarFileResolver.java
new file mode 100755
index 000000000..51b6134f7
--- /dev/null
+++ b/core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/common/SdncConfigEnvVarFileResolver.java
@@ -0,0 +1,38 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * onap
+ * ================================================================================
+ * Copyright (C) 2016 - 2017 ONAP
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.core.utils.common;
+
+import org.onap.ccsdk.sli.core.utils.EnvVarFileResolver;
+
+/**
+ * Resolve properties file location based on the default directory name.
+ */
+public class SdncConfigEnvVarFileResolver extends EnvVarFileResolver {
+
+ /**
+ * Key for environment variable representing the configuration directory
+ */
+ private static final String SDNC_CONFIG_DIR_PROP_KEY = "SDNC_CONFIG_DIR";
+
+ public SdncConfigEnvVarFileResolver(final String successMessage) {
+ super(successMessage, SDNC_CONFIG_DIR_PROP_KEY);
+ }
+}
diff --git a/core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/dblib/DblibDefaultFileResolver.java b/core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/dblib/DblibDefaultFileResolver.java
new file mode 100755
index 000000000..082bdf403
--- /dev/null
+++ b/core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/dblib/DblibDefaultFileResolver.java
@@ -0,0 +1,25 @@
+package org.onap.ccsdk.sli.core.utils.dblib;
+
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import org.onap.ccsdk.sli.core.utils.DefaultFileResolver;
+
+/**
+ * Resolve properties file location based on the default directory name.
+ *
+ * @deprecated
+ * This class has been replaced by generic version of this class
+ * {@link #CoreDefaultFileResolver} in common package.
+ */
+@Deprecated
+public class DblibDefaultFileResolver extends DefaultFileResolver {
+
+ /**
+ * Default path to look for the configuration directory
+ */
+ private static final Path DEFAULT_DBLIB_PROP_DIR = Paths.get("/opt", "sdnc", "data", "properties");
+
+ public DblibDefaultFileResolver(final String successMessage) {
+ super(successMessage, DEFAULT_DBLIB_PROP_DIR);
+ }
+}
diff --git a/core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/dblib/DblibEnvVarFileResolver.java b/core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/dblib/DblibEnvVarFileResolver.java
new file mode 100644
index 000000000..959271cb7
--- /dev/null
+++ b/core/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/dblib/DblibEnvVarFileResolver.java
@@ -0,0 +1,23 @@
+package org.onap.ccsdk.sli.core.utils.dblib;
+
+import org.onap.ccsdk.sli.core.utils.EnvVarFileResolver;
+
+/**
+ * Resolve properties file location based on the default directory name.
+ *
+ * @deprecated
+ * This class has been replaced by generic version of this class
+ * {@link #SdncConfigEnvVarFileResolver} in common package.
+ */
+@Deprecated
+public class DblibEnvVarFileResolver extends EnvVarFileResolver {
+
+ /**
+ * Key for environment variable representing the configuration directory
+ */
+ private static final String SDNC_CONFIG_DIR_PROP_KEY = "SDNC_CONFIG_DIR";
+
+ public DblibEnvVarFileResolver(final String successMessage) {
+ super(successMessage, SDNC_CONFIG_DIR_PROP_KEY);
+ }
+}
diff --git a/core/utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/JREFileResolverTest.java b/core/utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/JREFileResolverTest.java
new file mode 100644
index 000000000..8a066f057
--- /dev/null
+++ b/core/utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/JREFileResolverTest.java
@@ -0,0 +1,14 @@
+package org.onap.ccsdk.sli.core.utils;
+
+import static org.junit.Assert.assertEquals;
+import org.junit.Test;
+
+public class JREFileResolverTest {
+
+ @Test
+ public void getSuccessfulResolutionMessage() throws Exception {
+ final PropertiesFileResolver resolver = new JREFileResolver("success", JREFileResolverTest.class);
+ assertEquals("success", resolver.getSuccessfulResolutionMessage());
+ }
+
+} \ No newline at end of file
diff --git a/core/utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/KarafRootFileResolverTest.java b/core/utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/KarafRootFileResolverTest.java
new file mode 100644
index 000000000..df16b41d0
--- /dev/null
+++ b/core/utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/KarafRootFileResolverTest.java
@@ -0,0 +1,13 @@
+package org.onap.ccsdk.sli.core.utils;
+
+import static org.junit.Assert.assertEquals;
+import org.junit.Test;
+
+public class KarafRootFileResolverTest {
+ @Test
+ public void getSuccessfulResolutionMessage() throws Exception {
+ final PropertiesFileResolver resolver = new KarafRootFileResolver("success", null);
+ assertEquals("success", resolver.getSuccessfulResolutionMessage());
+ }
+
+} \ No newline at end of file
diff --git a/core/utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/common/BundleContexFileResolverTest.java b/core/utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/common/BundleContexFileResolverTest.java
new file mode 100644
index 000000000..7ddf550b0
--- /dev/null
+++ b/core/utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/common/BundleContexFileResolverTest.java
@@ -0,0 +1,16 @@
+package org.onap.ccsdk.sli.core.utils.common;
+
+import static org.junit.Assert.assertEquals;
+import org.junit.Test;
+import org.onap.ccsdk.sli.core.utils.PropertiesFileResolver;
+
+public class BundleContexFileResolverTest {
+
+ @Test
+ public void getSuccessfulResolutionMessage() throws Exception {
+ final PropertiesFileResolver resolver =
+ new BundleContextFileResolver("success", BundleContexFileResolverTest.class);
+ assertEquals("success", resolver.getSuccessfulResolutionMessage());
+ }
+
+} \ No newline at end of file
diff --git a/core/utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/common/CoreDefaultFileResolverTest.java b/core/utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/common/CoreDefaultFileResolverTest.java
new file mode 100644
index 000000000..f1f5f2244
--- /dev/null
+++ b/core/utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/common/CoreDefaultFileResolverTest.java
@@ -0,0 +1,25 @@
+package org.onap.ccsdk.sli.core.utils.common;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import java.io.File;
+import java.util.Optional;
+import org.junit.Test;
+import org.onap.ccsdk.sli.core.utils.PropertiesFileResolver;
+
+public class CoreDefaultFileResolverTest {
+
+ @Test
+ public void resolveFile() throws Exception {
+ final PropertiesFileResolver resolver = new CoreDefaultFileResolver("success");
+ final Optional<File> file = resolver.resolveFile("doesnotexist.cfg");
+ assertFalse(file.isPresent());
+ }
+
+ @Test
+ public void getSuccessfulResolutionMessage() throws Exception {
+ final PropertiesFileResolver resolver = new CoreDefaultFileResolver("success");
+ assertEquals("success", resolver.getSuccessfulResolutionMessage());
+ }
+
+} \ No newline at end of file
diff --git a/core/utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/common/SdncConfigEnvVarFileResolverTest.java b/core/utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/common/SdncConfigEnvVarFileResolverTest.java
new file mode 100644
index 000000000..130dc0a1e
--- /dev/null
+++ b/core/utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/common/SdncConfigEnvVarFileResolverTest.java
@@ -0,0 +1,24 @@
+package org.onap.ccsdk.sli.core.utils.common;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import java.io.File;
+import java.util.Optional;
+import org.junit.Test;
+import org.onap.ccsdk.sli.core.utils.PropertiesFileResolver;
+
+public class SdncConfigEnvVarFileResolverTest {
+ @Test
+ public void resolveFile() throws Exception {
+ final PropertiesFileResolver resolver = new SdncConfigEnvVarFileResolver("success");
+ final Optional<File> file = resolver.resolveFile("doesnotexist.cfg");
+ assertFalse(file.isPresent());
+ }
+
+ @Test
+ public void getSuccessfulResolutionMessage() throws Exception {
+ final PropertiesFileResolver resolver = new SdncConfigEnvVarFileResolver("success");
+ assertEquals("success", resolver.getSuccessfulResolutionMessage());
+ }
+
+} \ No newline at end of file
diff --git a/core/utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/dblib/DblibDefaultFileResolverTest.java b/core/utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/dblib/DblibDefaultFileResolverTest.java
new file mode 100644
index 000000000..834a8c449
--- /dev/null
+++ b/core/utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/dblib/DblibDefaultFileResolverTest.java
@@ -0,0 +1,25 @@
+package org.onap.ccsdk.sli.core.utils.dblib;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import java.io.File;
+import java.util.Optional;
+import org.junit.Test;
+import org.onap.ccsdk.sli.core.utils.PropertiesFileResolver;
+
+public class DblibDefaultFileResolverTest {
+
+ @Test
+ public void resolveFile() throws Exception {
+ final PropertiesFileResolver resolver = new DblibDefaultFileResolver("success");
+ final Optional<File> file = resolver.resolveFile("doesnotexist.cfg");
+ assertFalse(file.isPresent());
+ }
+
+ @Test
+ public void getSuccessfulResolutionMessage() throws Exception {
+ final PropertiesFileResolver resolver = new DblibDefaultFileResolver("success");
+ assertEquals("success", resolver.getSuccessfulResolutionMessage());
+ }
+
+} \ No newline at end of file
diff --git a/core/utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/dblib/DblibEnvVarFileResolverTest.java b/core/utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/dblib/DblibEnvVarFileResolverTest.java
new file mode 100644
index 000000000..b5150ab67
--- /dev/null
+++ b/core/utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/dblib/DblibEnvVarFileResolverTest.java
@@ -0,0 +1,24 @@
+package org.onap.ccsdk.sli.core.utils.dblib;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import java.io.File;
+import java.util.Optional;
+import org.junit.Test;
+import org.onap.ccsdk.sli.core.utils.PropertiesFileResolver;
+
+public class DblibEnvVarFileResolverTest {
+ @Test
+ public void resolveFile() throws Exception {
+ final PropertiesFileResolver resolver = new DblibEnvVarFileResolver("success");
+ final Optional<File> file = resolver.resolveFile("doesnotexist.cfg");
+ assertFalse(file.isPresent());
+ }
+
+ @Test
+ public void getSuccessfulResolutionMessage() throws Exception {
+ final PropertiesFileResolver resolver = new DblibEnvVarFileResolver("success");
+ assertEquals("success", resolver.getSuccessfulResolutionMessage());
+ }
+
+} \ No newline at end of file
diff --git a/plugins/LICENSE.txt b/plugins/LICENSE.txt
new file mode 100644
index 000000000..3ea5081a0
--- /dev/null
+++ b/plugins/LICENSE.txt
@@ -0,0 +1,22 @@
+/*
+ * ============LICENSE_START==========================================
+ * ===================================================================
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * ===================================================================
+ * 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.
+ * ============LICENSE_END============================================
+ *
+ * ECOMP and OpenECOMP are trademarks
+ * and service marks of AT&T Intellectual Property.
+ *
+ */
diff --git a/plugins/README.md b/plugins/README.md
new file mode 100644
index 000000000..05e536b16
--- /dev/null
+++ b/plugins/README.md
@@ -0,0 +1,20 @@
+This source repository contains the code for the CCSDK plugins.
+
+To compile this code:
+
+1. Make sure your local Maven settings file ($HOME/.m2/settings.xml) contains references to the ONAP repositories and OpenDaylight repositories. See example-settings.xml for an example.
+
+2. To compile, run "mvn clean install".
+
+
+PropertyNode:
+1) Takes any file then parses it and puts it to the context memory for Directed Graphs access.
+2) Various parameters it takes:
+
+ public String fileName; //Name of the file to put to properties
+
+ public String contextPrefix; //Any prefix to add for your keys in the Properties context
+
+ public Set<String> listNameList;//only applies to XML based file parsing, you can use this to exclude a specific tree to be put to context.
+
+ public boolean fileBasedParsing;//enable to do a file based parsing, currently supports JSON and XML. \ No newline at end of file
diff --git a/plugins/artifacts/pom.xml b/plugins/artifacts/pom.xml
new file mode 100755
index 000000000..fd52035b6
--- /dev/null
+++ b/plugins/artifacts/pom.xml
@@ -0,0 +1,105 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>parent</artifactId>
+ <version>2.1.0</version>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.plugins</groupId>
+ <artifactId>sli-plugins-artifacts</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>pom</packaging>
+
+ <name>ccsdk-sli-plugins :: sli-plugins-artifacts</name>
+ <description>CCSDK plugins components Bill of Materials (BOM)</description>
+ <url>https://wiki.onap.org</url>
+ <organization>
+ <name>ONAP</name>
+ </organization>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.plugins</groupId>
+ <artifactId>ccsdk-properties-node</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>feature</classifier>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.plugins</groupId>
+ <artifactId>ccsdk-restapi-call-node</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>feature</classifier>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.plugins</groupId>
+ <artifactId>ccsdk-restconf-client</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>feature</classifier>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.plugins</groupId>
+ <artifactId>ccsdk-template-node</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>feature</classifier>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.plugins</groupId>
+ <artifactId>fabric-discovery-plugin-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.plugins</groupId>
+ <artifactId>fabric-discovery-plugin-installer</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.plugins</groupId>
+ <artifactId>properties-node-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.plugins</groupId>
+ <artifactId>properties-node-installer</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.plugins</groupId>
+ <artifactId>restapi-call-node-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.plugins</groupId>
+ <artifactId>restapi-call-node-installer</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.plugins</groupId>
+ <artifactId>restconf-client-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.plugins</groupId>
+ <artifactId>restconf-client-installer</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.plugins</groupId>
+ <artifactId>template-node-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.plugins</groupId>
+ <artifactId>template-node-installer</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+</project>
diff --git a/plugins/features/ccsdk-gr-toolkit/pom.xml b/plugins/features/ccsdk-gr-toolkit/pom.xml
new file mode 100644
index 000000000..21464ef94
--- /dev/null
+++ b/plugins/features/ccsdk-gr-toolkit/pom.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>single-feature-parent</artifactId>
+ <version>2.1.0</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.plugins</groupId>
+ <artifactId>ccsdk-gr-toolkit</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>feature</packaging>
+
+ <name>ccsdk-sli-plugins :: gr-toolkit :: ${project.artifactId}</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>odl-mdsal-broker</artifactId>
+ <type>xml</type>
+ <classifier>features</classifier>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>gr-toolkit-model</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>gr-toolkit-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/plugins/features/ccsdk-properties-node/pom.xml b/plugins/features/ccsdk-properties-node/pom.xml
new file mode 100644
index 000000000..e11366986
--- /dev/null
+++ b/plugins/features/ccsdk-properties-node/pom.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>single-feature-parent</artifactId>
+ <version>2.1.0</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.plugins</groupId>
+ <artifactId>ccsdk-properties-node</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>feature</packaging>
+
+ <name>ccsdk-sli-plugins :: properties-node :: ${project.artifactId}</name>
+
+ <dependencies>
+
+
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>properties-node-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ </dependencies>
+</project>
diff --git a/plugins/features/ccsdk-restapi-call-node/pom.xml b/plugins/features/ccsdk-restapi-call-node/pom.xml
new file mode 100644
index 000000000..c5dcf096e
--- /dev/null
+++ b/plugins/features/ccsdk-restapi-call-node/pom.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>single-feature-parent</artifactId>
+ <version>2.1.0</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.plugins</groupId>
+ <artifactId>ccsdk-restapi-call-node</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>feature</packaging>
+
+ <name>ccsdk-sli-plugins :: restapi-call-node :: ${project.artifactId}</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>javax.ws.rs</groupId>
+ <artifactId>javax.ws.rs-api</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>restapi-call-node-provider</artifactId>
+ <version>${project.version}</version>
+ <exclusions>
+ <!-- let the filter module start and manage the common code -->
+ <exclusion>
+ <groupId>org.onap.logging-analytics</groupId>
+ <artifactId>logging-filter-base</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/plugins/features/ccsdk-restconf-client/pom.xml b/plugins/features/ccsdk-restconf-client/pom.xml
new file mode 100644
index 000000000..3d2e6d0e8
--- /dev/null
+++ b/plugins/features/ccsdk-restconf-client/pom.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>single-feature-parent</artifactId>
+ <version>2.1.0</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.plugins</groupId>
+ <artifactId>ccsdk-restconf-client</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>feature</packaging>
+
+ <name>ccsdk-sli-plugins :: restconf-client :: ${project.artifactId}</name>
+
+ <properties>
+ <skip.karaf.featureTest>true</skip.karaf.featureTest>
+ </properties>
+
+ <dependencies>
+
+
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>restconf-client-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/plugins/features/ccsdk-sli-plugins-all/pom.xml b/plugins/features/ccsdk-sli-plugins-all/pom.xml
new file mode 100644
index 000000000..fb73584f5
--- /dev/null
+++ b/plugins/features/ccsdk-sli-plugins-all/pom.xml
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>single-feature-parent</artifactId>
+ <version>2.1.0</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.plugins</groupId>
+ <artifactId>ccsdk-sli-plugins-all</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>feature</packaging>
+
+ <name>ccsdk-sli-plugins :: features :: ${project.artifactId}</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>ccsdk-properties-node</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ </dependency>
+
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>ccsdk-restapi-call-node</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ </dependency>
+
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>ccsdk-restconf-client</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ </dependency>
+
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>ccsdk-template-node</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ </dependency>
+
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>ccsdk-sshapi-call-node</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/plugins/features/ccsdk-sshapi-call-node/pom.xml b/plugins/features/ccsdk-sshapi-call-node/pom.xml
new file mode 100644
index 000000000..0441c12cd
--- /dev/null
+++ b/plugins/features/ccsdk-sshapi-call-node/pom.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>single-feature-parent</artifactId>
+ <version>2.1.0</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.plugins</groupId>
+ <artifactId>ccsdk-sshapi-call-node</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>feature</packaging>
+
+ <name>ccsdk-sli-plugins :: sshapi-call-node :: ${project.artifactId}</name>
+ <!--
+
+ <dependencies>
+
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>ccsdk-sli</artifactId>
+ <version>${ccsdk.sli.core.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>sshapi-call-node-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+ -->
+</project>
diff --git a/plugins/features/ccsdk-template-node/pom.xml b/plugins/features/ccsdk-template-node/pom.xml
new file mode 100644
index 000000000..4c6721643
--- /dev/null
+++ b/plugins/features/ccsdk-template-node/pom.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>single-feature-parent</artifactId>
+ <version>2.1.0</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.plugins</groupId>
+ <artifactId>ccsdk-template-node</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>feature</packaging>
+
+ <name>ccsdk-sli-plugins :: template-node :: ${project.artifactId}</name>
+
+ <dependencies>
+
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>template-node-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/plugins/features/features-sli-plugins/pom.xml b/plugins/features/features-sli-plugins/pom.xml
new file mode 100644
index 000000000..f91c1bd56
--- /dev/null
+++ b/plugins/features/features-sli-plugins/pom.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>feature-repo-parent</artifactId>
+ <version>2.1.0</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.plugins</groupId>
+ <artifactId>features-sli-plugins</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>feature</packaging>
+
+ <name>ccsdk-sli-plugins :: features :: ${project.artifactId}</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.plugins</groupId>
+ <artifactId>ccsdk-gr-toolkit</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ <exclusions>
+ <exclusion>
+ <groupId>*</groupId>
+ <artifactId>*</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.plugins</groupId>
+ <artifactId>ccsdk-properties-node</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ <exclusions>
+ <exclusion>
+ <groupId>*</groupId>
+ <artifactId>*</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.plugins</groupId>
+ <artifactId>ccsdk-restapi-call-node</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ <exclusions>
+ <exclusion>
+ <groupId>*</groupId>
+ <artifactId>*</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>${project.groupId}</groupId>
+ <artifactId>ccsdk-sli-plugins-all</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ </dependency>
+
+ </dependencies>
+</project>
diff --git a/plugins/features/installer/pom.xml b/plugins/features/installer/pom.xml
new file mode 100755
index 000000000..f58851eca
--- /dev/null
+++ b/plugins/features/installer/pom.xml
@@ -0,0 +1,213 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>odlparent-lite</artifactId>
+ <version>2.1.0</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.plugins</groupId>
+ <artifactId>sliplugins-features-installer</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>pom</packaging>
+
+ <name>ccsdk-sli-plugins :: features :: ${project.artifactId}</name>
+
+ <properties>
+ <application.name>ccsdk-sli-plugins-all</application.name>
+ <features.boot>${application.name}</features.boot>
+ <features.repositories>mvn:org.onap.ccsdk.sli.plugins/${features.boot}/${project.version}/xml/features</features.repositories>
+ <include.transitive.dependencies>false</include.transitive.dependencies>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.plugins</groupId>
+ <artifactId>ccsdk-gr-toolkit</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ <exclusions>
+ <exclusion>
+ <groupId>*</groupId>
+ <artifactId>*</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.plugins</groupId>
+ <artifactId>ccsdk-properties-node</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ <exclusions>
+ <exclusion>
+ <groupId>*</groupId>
+ <artifactId>*</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.plugins</groupId>
+ <artifactId>ccsdk-restapi-call-node</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ <exclusions>
+ <exclusion>
+ <groupId>*</groupId>
+ <artifactId>*</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.plugins</groupId>
+ <artifactId>ccsdk-restconf-client</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ <exclusions>
+ <exclusion>
+ <groupId>*</groupId>
+ <artifactId>*</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.plugins</groupId>
+ <artifactId>ccsdk-sshapi-call-node</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ <exclusions>
+ <exclusion>
+ <groupId>*</groupId>
+ <artifactId>*</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.plugins</groupId>
+ <artifactId>ccsdk-template-node</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ <exclusions>
+ <exclusion>
+ <groupId>*</groupId>
+ <artifactId>*</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.plugins</groupId>
+ <artifactId>${application.name}</artifactId>
+ <version>${project.version}</version>
+ <type>xml</type>
+ <classifier>features</classifier>
+ <exclusions>
+ <exclusion>
+ <groupId>*</groupId>
+ <artifactId>*</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+
+
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>maven-repo-zip</id>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ <phase>package</phase>
+ <configuration>
+ <attach>true</attach>
+ <finalName>stage/${application.name}-${project.version}</finalName>
+ <descriptors>
+ <descriptor>src/assembly/assemble_mvnrepo_zip.xml</descriptor>
+ </descriptors>
+ <appendAssemblyId>true</appendAssemblyId>
+ </configuration>
+ </execution>
+ <execution>
+ <id>installer-zip</id>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ <phase>package</phase>
+ <configuration>
+ <attach>true</attach>
+ <finalName>${application.name}-${project.version}-installer</finalName>
+ <descriptors>
+ <descriptor>src/assembly/assemble_installer_zip.xml</descriptor>
+ </descriptors>
+ <appendAssemblyId>false</appendAssemblyId>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>copy-dependencies</id>
+ <goals>
+ <goal>copy-dependencies</goal>
+ </goals>
+ <phase>prepare-package</phase>
+ <configuration>
+ <transitive>false</transitive>
+ <outputDirectory>${project.build.directory}/assembly/system</outputDirectory>
+ <overWriteReleases>false</overWriteReleases>
+ <overWriteSnapshots>true</overWriteSnapshots>
+ <overWriteIfNewer>true</overWriteIfNewer>
+ <useRepositoryLayout>true</useRepositoryLayout>
+ <addParentPoms>false</addParentPoms>
+ <copyPom>false</copyPom>
+ <includeGroupIds>org.onap.ccsdk.sli.plugins</includeGroupIds>
+ <scope>provided</scope>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <artifactId>maven-resources-plugin</artifactId>
+ <version>2.6</version>
+ <executions>
+ <execution>
+ <id>copy-version</id>
+ <goals>
+ <goal>copy-resources</goal>
+ </goals><!-- here the phase you need -->
+ <phase>validate</phase>
+ <configuration>
+ <outputDirectory>${basedir}/target/stage</outputDirectory>
+ <resources>
+ <resource>
+ <directory>src/main/resources/scripts</directory>
+ <includes>
+ <include>install-feature.sh</include>
+ </includes>
+ <filtering>true</filtering>
+ </resource>
+ </resources>
+ </configuration>
+ </execution>
+
+ </executions>
+ </plugin>
+
+ </plugins>
+ </build>
+</project>
diff --git a/plugins/features/installer/src/assembly/assemble_installer_zip.xml b/plugins/features/installer/src/assembly/assemble_installer_zip.xml
new file mode 100755
index 000000000..a6a22a9ba
--- /dev/null
+++ b/plugins/features/installer/src/assembly/assemble_installer_zip.xml
@@ -0,0 +1,39 @@
+<!-- Defines how we build the .zip file which is our distribution. -->
+
+<assembly
+ xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
+ <id>bin</id>
+
+ <formats>
+ <format>zip</format>
+ </formats>
+
+ <!-- we want "system" and related files right at the root level
+ as this file is suppose to be unzip on top of a karaf
+ distro. -->
+ <includeBaseDirectory>false</includeBaseDirectory>
+
+ <fileSets>
+ <fileSet>
+ <directory>target/stage/</directory>
+ <outputDirectory>${application.name}</outputDirectory>
+ <fileMode>755</fileMode>
+ <includes>
+ <include>*.sh</include>
+ </includes>
+ </fileSet>
+ <fileSet>
+ <directory>target/stage/</directory>
+ <outputDirectory>${application.name}</outputDirectory>
+ <fileMode>644</fileMode>
+ <excludes>
+ <exclude>*.sh</exclude>
+ </excludes>
+ </fileSet>
+ </fileSets>
+
+
+
+</assembly>
diff --git a/plugins/features/installer/src/assembly/assemble_mvnrepo_zip.xml b/plugins/features/installer/src/assembly/assemble_mvnrepo_zip.xml
new file mode 100755
index 000000000..86b07f1f3
--- /dev/null
+++ b/plugins/features/installer/src/assembly/assemble_mvnrepo_zip.xml
@@ -0,0 +1,29 @@
+<!-- Defines how we build the .zip file which is our distribution. -->
+
+<assembly
+ xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
+ <id>repo</id>
+
+ <formats>
+ <format>zip</format>
+ </formats>
+
+ <!-- we want "system" and related files right at the root level
+ as this file is suppose to be unzip on top of a karaf
+ distro. -->
+ <includeBaseDirectory>false</includeBaseDirectory>
+
+ <fileSets>
+ <fileSet>
+ <directory>target/assembly/</directory>
+ <outputDirectory>.</outputDirectory>
+ <excludes>
+ </excludes>
+ </fileSet>
+ </fileSets>
+
+
+
+</assembly>
diff --git a/plugins/features/installer/src/main/resources/scripts/install-feature.sh b/plugins/features/installer/src/main/resources/scripts/install-feature.sh
new file mode 100644
index 000000000..e16e79a12
--- /dev/null
+++ b/plugins/features/installer/src/main/resources/scripts/install-feature.sh
@@ -0,0 +1,18 @@
+#!/bin/bash
+
+ODL_HOME=${ODL_HOME:-/opt/opendaylight/current}
+ODL_KARAF_CLIENT=${ODL_KARAF_CLIENT:-${ODL_HOME}/bin/client}
+INSTALLERDIR=$(dirname $0)
+
+REPOZIP=${INSTALLERDIR}/${features.boot}-${project.version}.zip
+
+if [ -f ${REPOZIP} ]
+then
+ unzip -d ${ODL_HOME} ${REPOZIP}
+else
+ echo "ERROR : repo zip ($REPOZIP) not found"
+ exit 1
+fi
+
+${ODL_KARAF_CLIENT} feature:repo-add ${features.repositories}
+${ODL_KARAF_CLIENT} feature:install ${features.boot}
diff --git a/plugins/features/pom.xml b/plugins/features/pom.xml
new file mode 100755
index 000000000..e95874196
--- /dev/null
+++ b/plugins/features/pom.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>odlparent-lite</artifactId>
+ <version>2.1.0</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.plugins</groupId>
+ <artifactId>sliplugins-feature-aggregator</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>pom</packaging>
+
+ <name>ccsdk-sli-plugins :: features</name>
+
+ <modules>
+ <module>ccsdk-gr-toolkit</module>
+ <module>ccsdk-properties-node</module>
+ <module>ccsdk-restapi-call-node</module>
+ <module>ccsdk-restconf-client</module>
+ <module>ccsdk-sshapi-call-node</module>
+ <module>ccsdk-template-node</module>
+ <module>ccsdk-sli-plugins-all</module>
+ <module>features-sli-plugins</module>
+ <module>installer</module>
+ </modules>
+</project>
diff --git a/plugins/grToolkit/.gitignore b/plugins/grToolkit/.gitignore
new file mode 100755
index 000000000..a01e90efe
--- /dev/null
+++ b/plugins/grToolkit/.gitignore
@@ -0,0 +1,38 @@
+tandard .git ignore entries#####
+
+## IDE Specific Files ##
+org.eclipse.core.resources.prefs
+.classpath
+.project
+.settings
+.idea
+.externalToolBuilders
+maven-eclipse.xml
+workspace
+
+## Compilation Files ##
+*.class
+**/target
+target
+target-ide
+MANIFEST.MF
+
+## Misc Ignores (OS specific etc) ##
+bin/
+dist
+*~
+*.ipr
+*.iml
+*.iws
+classes
+out/
+.DS_STORE
+.metadata
+
+## Folders which contain auto generated source code ##
+yang-gen-config
+yang-gen-sal
+
+#####Archetype specific .git ignore entries#######
+generate
+Archetype_Next_Steps.README
diff --git a/plugins/grToolkit/README.md b/plugins/grToolkit/README.md
new file mode 100755
index 000000000..84594496b
--- /dev/null
+++ b/plugins/grToolkit/README.md
@@ -0,0 +1,316 @@
+Introduction
+======================
+You have generated an MD-SAL module.
+
+* You should be able to successfully run ```mvn clean install``` on this project.
+
+Next Steps
+======================
+* Run a ```mvn clean install``` if you haven't already. This will generate some code from the yang models.
+* Modify the model yang file under the model project.
+* Follow the comments in the generated provider class to wire your new provider into the generated
+code.
+* Modify the generated provider model to respond to and handle the yang model. Depending on what
+you added to your model you may need to inherit additional interfaces or make other changes to
+the provider model.
+
+Generated Bundles
+======================
+* model
+ - Provides the yang model for your application. This is your primary northbound interface.
+* provider
+ - Provides a template implementation for a provider to respond to your yang model.
+* features
+ - Defines a karaf feature. If you add dependencies on third-party bundles then you will need to
+ modify the features.xml to list out the dependencies.
+* installer
+ - Bundles all of the jars and third party dependencies (minus ODL dependencies) into a single
+ .zip file.
+
+Usage
+======================
+## Purpose
+The purpose of this ODL feature is to support geo-redundancy through a series of ODL integrated health checks and tools.
+
+## Properties File
+On initialization gr-toolkit expects to find a file named ```gr-toolkit.properties``` located in the ```SDNC_CONFIG``` directory. The properties file should contain:
+- ```akka.conf.location```
+ - The path to the akka.conf configuration file.
+- ```adm.useSsl```
+ - true/false; Determines whether or not to use http or https when making requests to the Admin Portal.
+- ```adm.fqdn```
+ - The FQDN or url of the site's Admin Portal.
+- ```adm.healthcheck```
+ - The url path of the Admin Portal's health check page.
+- ```adm.port.http```
+ - The HTTP port for the Admin Portal.
+- ```adm.port.ssl```
+ - The HTTPS port for the Admin Portal.
+- ```controller.credentials```
+ - username:password; The credentials used to make requests to the ODL controller.
+- ```controller.useSsl```
+ - true/false; Determines whether or not to use http or https when making requests to the controller.
+- ```controller.port.http```
+ - The HTTP port for the ODL Controller.
+- ```controller.port.ssl```
+ - The HTTPS port for the ODL Controller.
+- ```controller.port.akka```
+ - The port used for Akka communications on the ODL Controller.
+- ```mbean.cluster```
+ - The Jolokia path for the Akka Cluster MBean.
+- ```mbean.shardManager```
+ - The Jolokia path for the Akka ShardManager MBean.
+- ```mbean.shard.config```
+ - The Jolokia path for the Akka Shard MBean. This should be templated to look like ```/jolokia/read/org.opendaylight.controller:Category=Shards,name=%s,type=DistributedConfigDatastore```. GR Toolkit will use this template with information pulled from the Akka ShardManager MBean.
+- ```site.identifier```
+ - A unique identifier for the site the ODL Controller resides on.
+
+## Site Identifier
+Returns a unique site identifier of the site the ODL resides on.
+
+> ### Input: None
+>
+> ### Output
+> ```json
+> {
+> "output": {
+> "id": "UNIQUE_IDENTIFIER_HERE",
+> "status": "200"
+> }
+> }
+> ```
+
+## Admin Health
+Returns HEALTHY/FAULTY based on whether or not a 200 response is received from the Admin Portal's health check page.
+
+> ### Input: None
+>
+> ### Output
+> ```json
+> {
+> "output": {
+> "status": "200",
+> "health": "HEALTHY"
+> }
+> }
+> ```
+
+## Database Health
+Returns HEALTHY/FAULTY based on if DbLib can obtain a writeable connection from its pool.
+
+> ### Input: None
+>
+> ### Output
+> ```json
+> {
+> "output": {
+> "status": "200",
+> "health": "HEALTHY"
+> }
+> }
+> ```
+
+## Cluster Health
+Uses Jolokia queries to determine shard health and voting status. In a 3 ODL node configuration, 2 FAULTY nodes constitutes a FAULTY site. In a 6 node configuration it is assumed that there are 2 sites consiting of 3 nodes each.
+
+> ### Input: None
+>
+> ### Output
+> ```json
+> {
+> "output": {
+> "site1-health": "HEALTHY",
+> "members": [
+> {
+> "address": "member-3.node",
+> "role": "member-3",
+> "unreachable": false,
+> "voting": true,
+> "up": true,
+> "replicas": [
+> {
+> "shard": "member-3-shard-default-config"
+> }
+> ]
+> },
+> {
+> "address": "member-1.node",
+> "role": "member-1",
+> "unreachable": false,
+> "voting": true,
+> "up": true,
+> "replicas": [
+> {
+> "shard": "member-1-shard-default-config"
+> }
+> ]
+> },
+> {
+> "address": "member-5.node",
+> "role": "member-5",
+> "unreachable": false,
+> "voting": false,
+> "up": true,
+> "replicas": [
+> {
+> "shard": "member-5-shard-default-config"
+> }
+> ]
+> },
+> {
+> "address": "member-2.node",
+> "role": "member-2",
+> "unreachable": false,
+> "leader": [
+> {
+> "shard": "member-2-shard-default-config"
+> }
+> ],
+> "commit-status": [
+> {
+> "shard": "member-5-shard-default-config",
+> "delta": 148727
+> },
+> {
+> "shard": "member-4-shard-default-config",
+> "delta": 148869
+> }
+> ],
+> "voting": true,
+> "up": true,
+> "replicas": [
+> {
+> "shard": "member-2-shard-default-config"
+> }
+> ]
+> },
+> {
+> "address": "member-4.node",
+> "role": "member-4",
+> "unreachable": false,
+> "voting": false,
+> "up": true,
+> "replicas": [
+> {
+> "shard": "member-4-shard-default-config"
+> }
+> ]
+> },
+> {
+> "address": "member-6.node",
+> "role": "member-6",
+> "unreachable": false,
+> "voting": false,
+> "up": true,
+> "replicas": [
+> {
+> "shard": "member-6-shard-default-config"
+> }
+> ]
+> }
+> ],
+> "status": "200",
+> "site2-health": "HEALTHY"
+> }
+> }
+> ```
+
+## Site Health
+Aggregates data from Admin Health, Database Health, and Cluster Health and returns a simplified payload containing the health of a site. A FAULTY Admin Portal or Database health status will constitute a FAULTY site; in a 3 ODL node configuration, 2 FAULTY nodes constitutes a FAULTY site. If any portion of the health check registers as FAULTY, the entire site will be designated as FAULTY. In a 6 node configuration these health checks are performed cross site as well.
+
+> ### Input: None
+>
+> ### Output
+> ```json
+> {
+> "output": {
+> "sites": [
+> {
+> "id": "SITE_1",
+> "role": "ACTIVE",
+> "health": "HEALTHY"
+> },
+> {
+> "id": "SITE_2",
+> "role": "STANDBY",
+> "health": "FAULTY"
+> }
+> ],
+> "status": "200"
+> }
+> }
+> ```
+
+## Halt Akka Traffic
+Places rules in IP Tables to block Akka traffic to/from a specific node on a specified port.
+
+> ### Input:
+> ```json
+> {
+> "input": {
+> "node-info": [
+> {
+> "node": "your.odl.node",
+> "port": "2550"
+> }
+> ]
+> }
+> }
+> ```
+>
+> ### Output
+> ```json
+> {
+> "output": {
+> "status": "200"
+> }
+> }
+> ```
+
+## Resume Akka Traffic
+Removes rules in IP Tables to allow Akka traffic to/from a specifc node on a specified port.
+
+> ### Input:
+> ```json
+> {
+> "input": {
+> "node-info": [
+> {
+> "node": "your.odl.node",
+> "port": "2550"
+> }
+> ]
+> }
+> }
+> ```
+>
+> ### Output
+> ```json
+> {
+> "output": {
+> "status": "200"
+> }
+> }
+> ```
+
+## Failover
+Only usable in a 6 ODL node configuration. Determines which site is active/standby, switches voting to the standby site, and isolates the old active site. If backupData=true an MD-SAL export will be scheduled and backed up to a Nexus server (requires ccsdk.sli.northbound.daexim-offsite-backup feature).
+
+> ### Input:
+> ```json
+> {
+> "input": {
+> "backupData": "true"
+> }
+> }
+> ```
+>
+> ### Output
+> ```json
+> {
+> "output": {
+> "status": "200",
+> "message": "Failover complete."
+> }
+> }
+> ``` \ No newline at end of file
diff --git a/plugins/grToolkit/installer/pom.xml b/plugins/grToolkit/installer/pom.xml
new file mode 100755
index 000000000..d0392a65d
--- /dev/null
+++ b/plugins/grToolkit/installer/pom.xml
@@ -0,0 +1,129 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>odlparent-lite</artifactId>
+ <version>2.1.0</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.plugins</groupId>
+ <artifactId>gr-toolkit-installer</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>pom</packaging>
+
+ <name>ccsdk-sli-plugins :: gr-toolkit :: ${project.artifactId}</name>
+
+ <properties>
+ <application.name>ccsdk-gr-toolkit</application.name>
+ <features.boot>${application.name}</features.boot>
+ <features.repositories>mvn:org.onap.ccsdk.sli.plugins/${features.boot}/${project.version}/xml/features</features.repositories>
+ <include.transitive.dependencies>false</include.transitive.dependencies>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.plugins</groupId>
+ <artifactId>gr-toolkit-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.plugins</groupId>
+ <artifactId>gr-toolkit-model</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <version>2.6</version>
+ <executions>
+ <execution>
+ <id>maven-repo-zip</id>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ <phase>package</phase>
+ <configuration>
+ <attach>true</attach>
+ <finalName>stage/${application.name}-${project.version}</finalName>
+ <descriptors>
+ <descriptor>src/assembly/assemble_mvnrepo_zip.xml</descriptor>
+ </descriptors>
+ <appendAssemblyId>true</appendAssemblyId>
+ </configuration>
+ </execution>
+ <execution>
+ <id>installer-zip</id>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ <phase>package</phase>
+ <configuration>
+ <attach>true</attach>
+ <finalName>${application.name}-${project.version}-installer</finalName>
+ <descriptors>
+ <descriptor>src/assembly/assemble_installer_zip.xml</descriptor>
+ </descriptors>
+ <appendAssemblyId>false</appendAssemblyId>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>copy-dependencies</id>
+ <goals>
+ <goal>copy-dependencies</goal>
+ </goals>
+ <phase>prepare-package</phase>
+ <configuration>
+ <transitive>false</transitive>
+ <outputDirectory>${project.build.directory}/assembly/system</outputDirectory>
+ <overWriteReleases>false</overWriteReleases>
+ <overWriteSnapshots>true</overWriteSnapshots>
+ <overWriteIfNewer>true</overWriteIfNewer>
+ <useRepositoryLayout>true</useRepositoryLayout>
+ <addParentPoms>false</addParentPoms>
+ <copyPom>false</copyPom>
+ <includeGroupIds>org.onap.ccsdk.sli.plugins</includeGroupIds>
+ <scope>provided</scope>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <artifactId>maven-resources-plugin</artifactId>
+ <version>2.6</version>
+ <executions>
+ <execution>
+ <id>copy-version</id>
+ <goals>
+ <goal>copy-resources</goal>
+ </goals>
+ <phase>validate</phase>
+ <configuration>
+ <outputDirectory>${basedir}/target/stage</outputDirectory>
+ <resources>
+ <resource>
+ <directory>src/main/resources/scripts</directory>
+ <includes>
+ <include>install-feature.sh</include>
+ </includes>
+ <filtering>true</filtering>
+ </resource>
+ </resources>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/plugins/grToolkit/installer/src/assembly/assemble_installer_zip.xml b/plugins/grToolkit/installer/src/assembly/assemble_installer_zip.xml
new file mode 100755
index 000000000..41d23e88a
--- /dev/null
+++ b/plugins/grToolkit/installer/src/assembly/assemble_installer_zip.xml
@@ -0,0 +1,56 @@
+<!--
+ ============LICENSE_START=======================================================
+ openECOMP : SDN-C
+ ================================================================================
+ Copyright (C) 2018 AT&T Intellectual Property. All rights
+ reserved.
+ ================================================================================
+ 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.
+ ============LICENSE_END=========================================================
+ -->
+
+<!-- Defines how we build the .zip file which is our distribution. -->
+
+<assembly
+ xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
+ <id>installer_zip</id>
+ <formats>
+ <format>zip</format>
+ </formats>
+
+ <!-- we want "system" and related files right at the root level
+ as this file is suppose to be unzip on top of a karaf
+ distro. -->
+ <includeBaseDirectory>false</includeBaseDirectory>
+
+ <fileSets>
+ <fileSet>
+ <directory>target/stage/</directory>
+ <outputDirectory>${application.name}</outputDirectory>
+ <fileMode>755</fileMode>
+ <includes>
+ <include>*.sh</include>
+ </includes>
+ </fileSet>
+ <fileSet>
+ <directory>target/stage/</directory>
+ <outputDirectory>${application.name}</outputDirectory>
+ <fileMode>644</fileMode>
+ <excludes>
+ <exclude>*.sh</exclude>
+ </excludes>
+ </fileSet>
+ </fileSets>
+</assembly>
diff --git a/plugins/grToolkit/installer/src/assembly/assemble_mvnrepo_zip.xml b/plugins/grToolkit/installer/src/assembly/assemble_mvnrepo_zip.xml
new file mode 100755
index 000000000..fe7a90ce5
--- /dev/null
+++ b/plugins/grToolkit/installer/src/assembly/assemble_mvnrepo_zip.xml
@@ -0,0 +1,45 @@
+<!--
+ ============LICENSE_START=======================================================
+ openECOMP : SDN-C
+ ================================================================================
+ Copyright (C) 2018 AT&T Intellectual Property. All rights
+ reserved.
+ ================================================================================
+ 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.
+ ============LICENSE_END=========================================================
+ -->
+
+<!-- Defines how we build the .zip file which is our distribution. -->
+
+<assembly
+ xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
+ <id>repo</id>
+ <formats>
+ <format>zip</format>
+ </formats>
+
+ <!-- we want "system" and related files right at the root level
+ as this file is suppose to be unzip on top of a karaf
+ distro. -->
+ <includeBaseDirectory>false</includeBaseDirectory>
+
+ <fileSets>
+ <fileSet>
+ <directory>target/assembly/</directory>
+ <outputDirectory>.</outputDirectory>
+ </fileSet>
+ </fileSets>
+
+</assembly>
diff --git a/plugins/grToolkit/installer/src/main/resources/scripts/install-feature.sh b/plugins/grToolkit/installer/src/main/resources/scripts/install-feature.sh
new file mode 100755
index 000000000..1d7be149e
--- /dev/null
+++ b/plugins/grToolkit/installer/src/main/resources/scripts/install-feature.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+
+###
+# ============LICENSE_START=======================================================
+# openECOMP : SDN-C
+# ================================================================================
+# Copyright (C) 2018 AT&T Intellectual Property. All rights
+# reserved.
+# ================================================================================
+# 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.
+# ============LICENSE_END=========================================================
+###
+
+ODL_HOME=${ODL_HOME:-/opt/opendaylight/current}
+ODL_KARAF_CLIENT=${ODL_KARAF_CLIENT:-${ODL_HOME}/bin/client}
+INSTALLERDIR=$(dirname $0)
+
+REPOZIP=${INSTALLERDIR}/${features.boot}-${project.version}-repo.zip
+
+if [ -f ${REPOZIP} ]
+then
+ unzip -d ${ODL_HOME} ${REPOZIP}
+else
+ echo "ERROR : repo zip ($REPOZIP) not found"
+ exit 1
+fi
+
+${ODL_KARAF_CLIENT} feature:repo-add ${features.repositories}
+${ODL_KARAF_CLIENT} feature:install ${features.boot}
diff --git a/plugins/grToolkit/model/.gitignore b/plugins/grToolkit/model/.gitignore
new file mode 100755
index 000000000..eacf31a67
--- /dev/null
+++ b/plugins/grToolkit/model/.gitignore
@@ -0,0 +1 @@
+/target-ide/
diff --git a/plugins/grToolkit/model/pom.xml b/plugins/grToolkit/model/pom.xml
new file mode 100755
index 000000000..5d518d744
--- /dev/null
+++ b/plugins/grToolkit/model/pom.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>binding-parent</artifactId>
+ <version>2.1.0</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.plugins</groupId>
+ <artifactId>gr-toolkit-model</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>bundle</packaging>
+
+ <name>ccsdk-sli-plugins :: gr-toolkit :: ${project.artifactId}</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.opendaylight.mdsal.binding.model.ietf</groupId>
+ <artifactId>rfc6991</artifactId>
+ </dependency>
+
+
+ </dependencies>
+</project>
diff --git a/plugins/grToolkit/model/scripts/python/yang2props.py b/plugins/grToolkit/model/scripts/python/yang2props.py
new file mode 100755
index 000000000..85daccfbd
--- /dev/null
+++ b/plugins/grToolkit/model/scripts/python/yang2props.py
@@ -0,0 +1,78 @@
+#!/usr/bin/python
+
+###
+# ============LICENSE_START=======================================================
+# openECOMP : SDN-C
+# ================================================================================
+# Copyright (C) 2018 AT&T Intellectual Property. All rights
+# reserved.
+# ================================================================================
+# 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.
+# ============LICENSE_END=========================================================
+###
+
+import re
+import sys
+
+
+# Convert word from foo-bar to FooBar
+# words begining with a digit will be converted to _digit
+def to_enum(s):
+ if s[0].isdigit():
+ s = "_" + s
+ else:
+ s = s[0].upper() + s[1:]
+ return re.sub(r'(?!^)-([a-zA-Z])', lambda m: m.group(1).upper(), s)
+
+leaf = ""
+val = ""
+li = []
+
+if len(sys.argv) < 3:
+ print 'yang2props.py <input yang> <output properties>'
+ sys.exit(2)
+
+with open(sys.argv[1], "r") as ins:
+ for line in ins:
+ # if we see a leaf save the name for later
+ if "leaf " in line:
+ match = re.search(r'leaf (\S+)', line)
+ if match:
+ leaf = match.group(1)
+
+ # if we see enum convert the value to enum format and see if it changed
+ # if the value is different write a property entry
+ if "enum " in line:
+ match = re.search(r'enum "(\S+)";', line)
+ if match:
+ val = match.group(1)
+ enum = to_enum(val)
+
+ # see if converting to enum changed the string
+ if val != enum:
+ property = "yang."+leaf+"."+enum+"="+val
+ if property not in li:
+ li.append( property)
+
+
+# Open output file
+fo = open(sys.argv[2], "wb")
+fo.write("# yang conversion properties \n")
+fo.write("# used to convert Enum back to the original yang value \n")
+fo.write("\n".join(li))
+fo.write("\n")
+
+# Close opend file
+fo.close()
+
+
diff --git a/plugins/grToolkit/model/src/main/yang/gr-toolkit.yang b/plugins/grToolkit/model/src/main/yang/gr-toolkit.yang
new file mode 100755
index 000000000..cc21400a7
--- /dev/null
+++ b/plugins/grToolkit/model/src/main/yang/gr-toolkit.yang
@@ -0,0 +1,199 @@
+module gr-toolkit{
+ namespace "org:onap:ccsdk:sli:plugins:gr-toolkit";
+ prefix gr-toolkit;
+
+ import ietf-inet-types {
+ prefix inet;
+ }
+ import ietf-yang-types {
+ prefix yang;
+ }
+ description
+ "This ODL feature is designed to gauge the health of all cluster members.";
+ revision "2018-09-26" {
+ description
+ "Release 19.02 draft";
+ }
+
+ grouping member {
+ leaf address {
+ type string;
+ mandatory true;
+ }
+ leaf role {
+ type string;
+ mandatory true;
+ }
+ leaf up {
+ type boolean;
+ mandatory true;
+ }
+ leaf unreachable {
+ type boolean;
+ mandatory true;
+ }
+ leaf voting {
+ type boolean;
+ mandatory true;
+ }
+ list leader {
+ leaf shard {
+ type string;
+ mandatory true;
+ }
+ }
+ list replicas {
+ leaf shard {
+ type string;
+ mandatory true;
+ }
+ }
+ list commit-status {
+ leaf shard {
+ type string;
+ mandatory true;
+ }
+ leaf delta {
+ type int32;
+ mandatory true;
+ }
+ }
+ }
+
+ grouping site {
+ leaf id {
+ type string;
+ mandatory true;
+ }
+ leaf role {
+ type string;
+ mandatory true;
+ }
+ leaf health {
+ type string;
+ mandatory true;
+ }
+ }
+
+ grouping node {
+ leaf node {
+ type string;
+ mandatory true;
+ }
+ leaf port {
+ type string;
+ mandatory true;
+ }
+ }
+
+ rpc cluster-health {
+ description
+ "Parses akka.conf for seed nodes and queries Jolokia for the health
+ of each node.";
+ output {
+ leaf status { type string; }
+ leaf message { type string; }
+ leaf served-by { type string; }
+ leaf site1-health { type string; }
+ leaf site2-health { type string; }
+ list members {
+ uses member;
+ }
+ }
+ }
+
+ rpc database-health {
+ description
+ "Uses DbLibService connection info to determine if the database is reachable.";
+ output {
+ leaf status { type string; }
+ leaf health { type string; }
+ leaf served-by { type string; }
+ }
+ }
+
+ rpc admin-health {
+ description
+ "Pings the admin portal health check to determine if the admin portal is reachable.";
+ output {
+ leaf status { type string; }
+ leaf health { type string; }
+ leaf served-by { type string; }
+ }
+ }
+
+ rpc site-health {
+ description
+ "Gathers health information on the ODL cluster, database, and admin portal
+ to determine if the entire site is in a healthy state.";
+ output {
+ leaf status { type string; }
+ leaf served-by { type string; }
+ list sites {
+ uses site;
+ }
+ }
+ }
+
+ rpc site-identifier {
+ description
+ "Returns the unique site identifier.";
+ output {
+ leaf status { type string; }
+ leaf served-by { type string; }
+ leaf id { type string; mandatory true; }
+ }
+ }
+
+ rpc halt-akka-traffic {
+ description
+ "Executes IP Tables commands to halt traffic to the akka port.";
+ input {
+ list node-info {
+ uses node;
+ }
+ }
+ output {
+ leaf status { type string; }
+ leaf served-by { type string; }
+ }
+ }
+
+ rpc resume-akka-traffic {
+ description
+ "Executes IP Tables commands to resume traffic to the akka port.";
+ input {
+ list node-info {
+ uses node;
+ }
+ }
+ output {
+ leaf status { type string; }
+ leaf served-by { type string; }
+ }
+ }
+
+ rpc failover {
+ description
+ "Performs a failover from primary site to standby site.";
+ input {
+ leaf backupData {
+ type string;
+ default "false";
+ }
+ leaf isolate {
+ type string;
+ default "false";
+ }
+ leaf downUnreachable {
+ type string;
+ default "false";
+ }
+ }
+ output {
+ leaf status { type string; }
+ leaf message { type string; }
+ leaf served-by { type string; }
+ }
+ }
+}
diff --git a/plugins/grToolkit/pom.xml b/plugins/grToolkit/pom.xml
new file mode 100755
index 000000000..499876b3b
--- /dev/null
+++ b/plugins/grToolkit/pom.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>odlparent-lite</artifactId>
+ <version>2.1.0</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.plugins</groupId>
+ <artifactId>gr-toolkit</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>pom</packaging>
+
+ <name>ccsdk-sli-plugins :: gr-toolkit</name>
+ <description>ODL bundle used to judge health of SDN-C application.</description>
+
+ <modules>
+ <module>model</module>
+ <module>installer</module>
+ <module>provider</module>
+ </modules>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.plugins</groupId>
+ <artifactId>gr-toolkit-model</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.plugins</groupId>
+ <artifactId>gr-toolkit-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+</project>
diff --git a/plugins/grToolkit/provider/.gitignore b/plugins/grToolkit/provider/.gitignore
new file mode 100755
index 000000000..eacf31a67
--- /dev/null
+++ b/plugins/grToolkit/provider/.gitignore
@@ -0,0 +1 @@
+/target-ide/
diff --git a/plugins/grToolkit/provider/pom.xml b/plugins/grToolkit/provider/pom.xml
new file mode 100755
index 000000000..2fc981b46
--- /dev/null
+++ b/plugins/grToolkit/provider/pom.xml
@@ -0,0 +1,122 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>binding-parent</artifactId>
+ <version>2.1.0</version>
+ <relativePath/>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.plugins</groupId>
+ <artifactId>gr-toolkit-provider</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>bundle</packaging>
+
+ <name>ccsdk-sli-plugins :: gr-toolkit :: ${project.artifactId}</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.plugins</groupId>
+ <artifactId>gr-toolkit-model</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-binding-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>dblib-provider</artifactId>
+ <version>${ccsdk.sli.core.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sli-common</artifactId>
+ <version>${ccsdk.sli.core.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sli-provider</artifactId>
+ <version>${ccsdk.sli.core.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.google.code.findbugs</groupId>
+ <artifactId>annotations</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-test-model</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-binding-broker-impl</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-binding-broker-impl</artifactId>
+ <type>test-jar</type>
+ <classifier>tests</classifier>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <!-- WireMock used to create test web server -->
+ <!-- Using same dependency found in MSO Utils -->
+ <dependency>
+ <groupId>org.springframework.cloud</groupId>
+ <artifactId>spring-cloud-contract-wiremock</artifactId>
+ <version>1.2.4.RELEASE</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.json</groupId>
+ <artifactId>json</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.controller</groupId>
+ <artifactId>sal-distributed-datastore</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.typesafe.akka</groupId>
+ <artifactId>akka-cluster_2.12</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.github.stefanbirkner</groupId>
+ <artifactId>system-rules</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Export-Package>org.opendaylight.controller.config.yang.config.gr-toolkit_provider</Export-Package>
+ <Import-Package>*</Import-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/plugins/grToolkit/provider/src/main/java/org/onap/ccsdk/sli/plugins/grtoolkit/GrToolkitProvider.java b/plugins/grToolkit/provider/src/main/java/org/onap/ccsdk/sli/plugins/grtoolkit/GrToolkitProvider.java
new file mode 100755
index 000000000..7a8b3deb0
--- /dev/null
+++ b/plugins/grToolkit/provider/src/main/java/org/onap/ccsdk/sli/plugins/grtoolkit/GrToolkitProvider.java
@@ -0,0 +1,765 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2018 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.grtoolkit;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Properties;
+import java.util.List;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import javax.annotation.Nonnull;
+
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
+
+import org.apache.commons.lang.StringUtils;
+
+import org.onap.ccsdk.sli.core.dblib.DbLibService;
+import org.onap.ccsdk.sli.plugins.grtoolkit.connection.ConnectionManager;
+import org.onap.ccsdk.sli.plugins.grtoolkit.connection.ConnectionResponse;
+import org.onap.ccsdk.sli.plugins.grtoolkit.data.AdminHealth;
+import org.onap.ccsdk.sli.plugins.grtoolkit.data.ClusterActor;
+import org.onap.ccsdk.sli.plugins.grtoolkit.data.DatabaseHealth;
+import org.onap.ccsdk.sli.plugins.grtoolkit.data.FailoverStatus;
+import org.onap.ccsdk.sli.plugins.grtoolkit.data.Health;
+import org.onap.ccsdk.sli.plugins.grtoolkit.data.MemberBuilder;
+import org.onap.ccsdk.sli.plugins.grtoolkit.data.PropertyKeys;
+import org.onap.ccsdk.sli.plugins.grtoolkit.data.SiteHealth;
+import org.onap.ccsdk.sli.plugins.grtoolkit.resolver.HealthResolver;
+import org.onap.ccsdk.sli.plugins.grtoolkit.resolver.SingleNodeHealthResolver;
+import org.onap.ccsdk.sli.plugins.grtoolkit.resolver.SixNodeHealthResolver;
+import org.onap.ccsdk.sli.plugins.grtoolkit.resolver.ThreeNodeHealthResolver;
+
+import org.json.JSONArray;
+import org.json.JSONObject;
+
+import org.opendaylight.controller.cluster.datastore.DistributedDataStoreInterface;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.DataTreeChangeListener;
+import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
+import org.opendaylight.controller.sal.binding.api.BindingAwareBroker;
+import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.plugins.gr.toolkit.rev180926.AdminHealthInput;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.plugins.gr.toolkit.rev180926.AdminHealthOutput;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.plugins.gr.toolkit.rev180926.AdminHealthOutputBuilder;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.plugins.gr.toolkit.rev180926.ClusterHealthInput;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.plugins.gr.toolkit.rev180926.ClusterHealthOutput;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.plugins.gr.toolkit.rev180926.ClusterHealthOutputBuilder;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.plugins.gr.toolkit.rev180926.DatabaseHealthInput;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.plugins.gr.toolkit.rev180926.DatabaseHealthOutput;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.plugins.gr.toolkit.rev180926.DatabaseHealthOutputBuilder;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.plugins.gr.toolkit.rev180926.FailoverInput;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.plugins.gr.toolkit.rev180926.FailoverOutput;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.plugins.gr.toolkit.rev180926.FailoverOutputBuilder;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.plugins.gr.toolkit.rev180926.GrToolkitService;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.plugins.gr.toolkit.rev180926.HaltAkkaTrafficInput;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.plugins.gr.toolkit.rev180926.HaltAkkaTrafficOutput;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.plugins.gr.toolkit.rev180926.HaltAkkaTrafficOutputBuilder;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.plugins.gr.toolkit.rev180926.Member;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.plugins.gr.toolkit.rev180926.ResumeAkkaTrafficInput;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.plugins.gr.toolkit.rev180926.ResumeAkkaTrafficOutput;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.plugins.gr.toolkit.rev180926.ResumeAkkaTrafficOutputBuilder;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.plugins.gr.toolkit.rev180926.Site;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.plugins.gr.toolkit.rev180926.SiteHealthInput;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.plugins.gr.toolkit.rev180926.SiteHealthOutput;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.plugins.gr.toolkit.rev180926.SiteHealthOutputBuilder;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.plugins.gr.toolkit.rev180926.SiteIdentifierInput;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.plugins.gr.toolkit.rev180926.SiteIdentifierOutput;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.plugins.gr.toolkit.rev180926.SiteIdentifierOutputBuilder;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.plugins.gr.toolkit.rev180926.site.health.output.SitesBuilder;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+import org.opendaylight.yangtools.yang.common.RpcResultBuilder;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * API implementation of the {@code GrToolkitService} interface generated from
+ * the gr-toolkit.yang model. The RPCs contained within this class are meant to
+ * run in an architecture agnostic fashion, where the response is repeatable
+ * and predictable across any given node configuration. To facilitate this,
+ * health checking and failover logic has been abstracted into the
+ * {@code HealthResolver} classes.
+ * <p>
+ * Anyone who wishes to write a custom resolver for use with GR Toolkit should
+ * extend the {@code HealthResolver} class. The currently provided resolvers
+ * are useful references for further implementation.
+ *
+ * @author Anthony Haddox
+ * @see GrToolkitService
+ * @see HealthResolver
+ * @see SingleNodeHealthResolver
+ * @see ThreeNodeHealthResolver
+ * @see SixNodeHealthResolver
+ */
+public class GrToolkitProvider implements AutoCloseable, GrToolkitService, DataTreeChangeListener {
+ private static final String APP_NAME = "gr-toolkit";
+ private static final String PROPERTIES_FILE = System.getenv("SDNC_CONFIG_DIR") + "/gr-toolkit.properties";
+ private String akkaConfig;
+ private String httpProtocol;
+ private String siteIdentifier = System.getenv("SITE_NAME");
+ private final Logger log = LoggerFactory.getLogger(GrToolkitProvider.class);
+ private final ExecutorService executor;
+ protected DataBroker dataBroker;
+ protected NotificationPublishService notificationService;
+ protected RpcProviderRegistry rpcRegistry;
+ protected BindingAwareBroker.RpcRegistration<GrToolkitService> rpcRegistration;
+ protected DbLibService dbLib;
+ private String member;
+ private ClusterActor self;
+ private HashMap<String, ClusterActor> memberMap;
+ private Properties properties;
+ private DistributedDataStoreInterface configDatastore;
+ private HealthResolver resolver;
+
+ /**
+ * Constructs the provider for the GR Toolkit API. Dependencies are
+ * injected using the GrToolkit.xml blueprint.
+ *
+ * @param dataBroker The Data Broker
+ * @param notificationProviderService The Notification Service
+ * @param rpcProviderRegistry The RPC Registry
+ * @param configDatastore The Configuration Data Store provided by the controller
+ * @param dbLibService Reference to the controller provided DbLibService
+ */
+ public GrToolkitProvider(DataBroker dataBroker,
+ NotificationPublishService notificationProviderService,
+ RpcProviderRegistry rpcProviderRegistry,
+ DistributedDataStoreInterface configDatastore,
+ DbLibService dbLibService) {
+ log.info("Creating provider for {}", APP_NAME);
+ this.executor = Executors.newFixedThreadPool(1);
+ this.dataBroker = dataBroker;
+ this.notificationService = notificationProviderService;
+ this.rpcRegistry = rpcProviderRegistry;
+ this.configDatastore = configDatastore;
+ this.dbLib = dbLibService;
+ initialize();
+ }
+
+ /**
+ * Initializes some structures necessary to hold health check information
+ * and perform failovers.
+ */
+ private void initialize() {
+ log.info("Initializing provider for {}", APP_NAME);
+ createContainers();
+ setProperties();
+ defineMembers();
+ rpcRegistration = rpcRegistry.addRpcImplementation(GrToolkitService.class, this);
+ log.info("Initialization complete for {}", APP_NAME);
+ }
+
+ /**
+ * Creates the {@code Properties} object with the contents of
+ * gr-toolkit.properties, found at the {@code SDNC_CONFIG_DIR} directory,
+ * which should be set as an environment variable. If the properties file
+ * is not found, GR Toolkit will not function.
+ */
+ private void setProperties() {
+ log.info("Loading properties from {}", PROPERTIES_FILE);
+ properties = new Properties();
+ File propertiesFile = new File(PROPERTIES_FILE);
+ if(!propertiesFile.exists()) {
+ log.warn("setProperties(): Properties file not found.");
+ } else {
+ try(FileInputStream fileInputStream = new FileInputStream(propertiesFile)) {
+ properties.load(fileInputStream);
+ if(!properties.containsKey(PropertyKeys.SITE_IDENTIFIER)) {
+ properties.put(PropertyKeys.SITE_IDENTIFIER, "Unknown Site");
+ }
+ httpProtocol = "true".equals(properties.getProperty(PropertyKeys.CONTROLLER_USE_SSL).trim()) ? "https://" : "http://";
+ akkaConfig = properties.getProperty(PropertyKeys.AKKA_CONF_LOCATION).trim();
+ if(StringUtils.isEmpty(siteIdentifier)) {
+ siteIdentifier = properties.getProperty(PropertyKeys.SITE_IDENTIFIER).trim();
+ }
+ log.info("setProperties(): Loaded properties.");
+ } catch(IOException e) {
+ log.error("setProperties(): Error loading properties.", e);
+ }
+ }
+ }
+
+ /**
+ * Parses the akka.conf file used by the controller to define an akka
+ * cluster. This method requires the <i>seed-nodes</i> definition to exist
+ * on a single line.
+ */
+ private void defineMembers() {
+ member = configDatastore.getActorUtils().getCurrentMemberName().getName();
+ log.info("defineMembers(): Cluster member: {}", member);
+
+ log.info("defineMembers(): Parsing akka.conf for cluster memberMap...");
+ try {
+ File akkaConfigFile = new File(this.akkaConfig);
+ try(FileReader fileReader = new FileReader(akkaConfigFile);
+ BufferedReader bufferedReader = new BufferedReader(fileReader)) {
+ String line;
+ while((line = bufferedReader.readLine()) != null) {
+ if(line.contains("seed-nodes =")) {
+ parseSeedNodes(line);
+ break;
+ }
+ }
+ }
+ } catch(IOException e) {
+ log.error("defineMembers(): Couldn't load akka", e);
+ } catch(NullPointerException e) {
+ log.error("defineMembers(): akkaConfig is null. Check properties file and restart {} bundle.", APP_NAME);
+ log.error("defineMembers(): NullPointerException", e);
+ }
+ log.info("self:\n{}", self);
+ }
+
+ /**
+ * Sets up the {@code InstanceIdentifier}s for Data Store transactions.
+ */
+ private void createContainers() {
+ // Replace with MD-SAL write for FailoverStatus
+ }
+
+ /**
+ * Shuts down the {@code ExecutorService} and closes the RPC Provider Registry.
+ */
+ @Override
+ public void close() throws Exception {
+ log.info("Closing provider for {}", APP_NAME);
+ executor.shutdown();
+ rpcRegistration.close();
+ log.info("close(): Successfully closed provider for {}", APP_NAME);
+ }
+
+ /**
+ * Listens for changes to the Data tree.
+ *
+ * @param changes Data tree changes.
+ */
+ @Override
+ public void onDataTreeChanged(@Nonnull Collection changes) {
+ log.info("onDataTreeChanged(): No changes.");
+ }
+
+ /**
+ * Makes a call to {@code resolver.getClusterHealth()} to determine the
+ * health of the akka clustered controllers.
+ *
+ * @param input request body adhering to the model for
+ * {@code ClusterHealthInput}
+ * @return response adhering to the model for {@code ClusterHealthOutput}
+ * @see HealthResolver
+ * @see ClusterHealthInput
+ * @see ClusterHealthOutput
+ */
+ @Override
+ public ListenableFuture<RpcResult<ClusterHealthOutput>> clusterHealth(ClusterHealthInput input) {
+ log.info("{}:cluster-health invoked.", APP_NAME);
+ resolver.getClusterHealth();
+ return buildClusterHealthOutput();
+ }
+
+ /**
+ * Makes a call to {@code resolver.getSiteHealth()} to determine the health
+ * of all of the application components of a site. In a multi-site config,
+ * this will gather the health of all sites.
+ *
+ * @param input request body adhering to the model for
+ * {@code SiteHealthInput}
+ * @return response adhering to the model for {@code SiteHealthOutput}
+ * @see HealthResolver
+ * @see SiteHealthInput
+ * @see SiteHealthOutput
+ */
+ @Override
+ public ListenableFuture<RpcResult<SiteHealthOutput>> siteHealth(SiteHealthInput input) {
+ log.info("{}:site-health invoked.", APP_NAME);
+ List<SiteHealth> sites = resolver.getSiteHealth();
+ return buildSiteHealthOutput(sites);
+ }
+
+ /**
+ * Makes a call to {@code resolver.getDatabaseHealth()} to determine the
+ * health of the database(s) used by the controller.
+ *
+ * @param input request body adhering to the model for
+ * {@code DatabaseHealthInput}
+ * @return response adhering to the model for {@code DatabaseHealthOutput}
+ * @see HealthResolver
+ * @see DatabaseHealthInput
+ * @see DatabaseHealthOutput
+ */
+ @Override
+ public ListenableFuture<RpcResult<DatabaseHealthOutput>> databaseHealth(DatabaseHealthInput input) {
+ log.info("{}:database-health invoked.", APP_NAME);
+ DatabaseHealthOutputBuilder outputBuilder = new DatabaseHealthOutputBuilder();
+ DatabaseHealth health = resolver.getDatabaseHealth();
+ outputBuilder.setStatus(health.getHealth().equals(Health.HEALTHY) ? "200" : "500");
+ outputBuilder.setHealth(health.getHealth().toString());
+ outputBuilder.setServedBy(member);
+ log.info("databaseHealth(): Health: {}", health.getHealth());
+ return Futures.immediateFuture(RpcResultBuilder.<DatabaseHealthOutput>status(true).withResult(outputBuilder.build()).build());
+ }
+
+ /**
+ * Makes a call to {@code resolver.getAdminHealth()} to determine the
+ * health of the administrative portal(s) used by the controller.
+ *
+ * @param input request body adhering to the model for
+ * {@code AdminHealthInput}
+ * @return response adhering to the model for {@code AdminHealthOutput}
+ * @see HealthResolver
+ * @see AdminHealthInput
+ * @see AdminHealthOutput
+ */
+ @Override
+ public ListenableFuture<RpcResult<AdminHealthOutput>> adminHealth(AdminHealthInput input) {
+ log.info("{}:admin-health invoked.", APP_NAME);
+ AdminHealthOutputBuilder outputBuilder = new AdminHealthOutputBuilder();
+ AdminHealth adminHealth = resolver.getAdminHealth();
+ outputBuilder.setStatus(Integer.toString(adminHealth.getStatusCode()));
+ outputBuilder.setHealth(adminHealth.getHealth().toString());
+ outputBuilder.setServedBy(member);
+ log.info("adminHealth(): Status: {} | Health: {}", adminHealth.getStatusCode(), adminHealth.getHealth());
+ return Futures.immediateFuture(RpcResultBuilder.<AdminHealthOutput>status(true).withResult(outputBuilder.build()).build());
+ }
+
+ /**
+ * Places IP Tables rules in place to drop akka communications traffic with
+ * one or mode nodes. This method does not not perform any checks to see if
+ * rules currently exist, and assumes success.
+ *
+ * @param input request body adhering to the model for
+ * {@code HaltAkkaTrafficInput}
+ * @return response adhering to the model for {@code HaltAkkaTrafficOutput}
+ * @see HaltAkkaTrafficInput
+ * @see HaltAkkaTrafficOutput
+ */
+ @Override
+ public ListenableFuture<RpcResult<HaltAkkaTrafficOutput>> haltAkkaTraffic(HaltAkkaTrafficInput input) {
+ log.info("{}:halt-akka-traffic invoked.", APP_NAME);
+ HaltAkkaTrafficOutputBuilder outputBuilder = new HaltAkkaTrafficOutputBuilder();
+ outputBuilder.setStatus("200");
+ modifyIpTables(IpTables.ADD, input.getNodeInfo().toArray());
+ outputBuilder.setServedBy(member);
+
+ return Futures.immediateFuture(RpcResultBuilder.<HaltAkkaTrafficOutput>status(true).withResult(outputBuilder.build()).build());
+ }
+
+ /**
+ * Removes IP Tables rules in place to permit akka communications traffic
+ * with one or mode nodes. This method does not not perform any checks to
+ * see if rules currently exist, and assumes success.
+ *
+ * @param input request body adhering to the model for
+ * {@code ResumeAkkaTrafficInput}
+ * @return response adhering to the model for {@code ResumeAkkaTrafficOutput}
+ * @see ResumeAkkaTrafficInput
+ * @see ResumeAkkaTrafficOutput
+ */
+ @Override
+ public ListenableFuture<RpcResult<ResumeAkkaTrafficOutput>> resumeAkkaTraffic(ResumeAkkaTrafficInput input) {
+ log.info("{}:resume-akka-traffic invoked.", APP_NAME);
+ ResumeAkkaTrafficOutputBuilder outputBuilder = new ResumeAkkaTrafficOutputBuilder();
+ outputBuilder.setStatus("200");
+ modifyIpTables(IpTables.DELETE, input.getNodeInfo().toArray());
+ outputBuilder.setServedBy(member);
+
+ return Futures.immediateFuture(RpcResultBuilder.<ResumeAkkaTrafficOutput>status(true).withResult(outputBuilder.build()).build());
+ }
+
+ /**
+ * Returns a canned response containing the identifier for this
+ * controller's site.
+ *
+ * @param input request body adhering to the model for
+ * {@code SiteIdentifierInput}
+ * @return response adhering to the model for {@code SiteIdentifierOutput}
+ * @see SiteIdentifierInput
+ * @see SiteIdentifierOutput
+ */
+ @Override
+ public ListenableFuture<RpcResult<SiteIdentifierOutput>> siteIdentifier(SiteIdentifierInput input) {
+ log.info("{}:site-identifier invoked.", APP_NAME);
+ SiteIdentifierOutputBuilder outputBuilder = new SiteIdentifierOutputBuilder();
+ outputBuilder.setStatus("200");
+ outputBuilder.setId(siteIdentifier);
+ outputBuilder.setServedBy(member);
+ return Futures.immediateFuture(RpcResultBuilder.<SiteIdentifierOutput>status(true).withResult(outputBuilder.build()).build());
+ }
+
+ /**
+ * Makes a call to {@code resolver.tryFailover()} to try a failover defined
+ * by the active {@code HealthResolver}.
+ *
+ * @param input request body adhering to the model for
+ * {@code FailoverInput}
+ * @return response adhering to the model for {@code FailoverOutput}
+ * @see HealthResolver
+ * @see FailoverInput
+ * @see FailoverOutput
+ */
+ @Override
+ public ListenableFuture<RpcResult<FailoverOutput>> failover(FailoverInput input) {
+ log.info("{}:failover invoked.", APP_NAME);
+ FailoverOutputBuilder outputBuilder = new FailoverOutputBuilder();
+ FailoverStatus failoverStatus = resolver.tryFailover(input);
+ outputBuilder.setServedBy(member);
+ outputBuilder.setMessage(failoverStatus.getMessage());
+ outputBuilder.setStatus(Integer.toString(failoverStatus.getStatusCode()));
+ log.info("{}:{}.", APP_NAME, failoverStatus.getMessage());
+ return Futures.immediateFuture(RpcResultBuilder.<FailoverOutput>status(true).withResult(outputBuilder.build()).build());
+ }
+
+ /**
+ * Performs an akka traffic isolation of the active site from the standby
+ * site in an Active/Standby architecture. Invokes the
+ * {@code halt-akka-traffic} RPC against the standby site nodes using the
+ * information of the active site nodes.
+ *
+ * @param activeSite list of nodes in the active site
+ * @param standbySite list of nodes in the standby site
+ * @param port http or https port of the controller
+ * @deprecated No longer used since the refactor to use the HealthResolver
+ * pattern. Retained so the logic can be replicated later.
+ */
+ @Deprecated
+ private void isolateSiteFromCluster(ArrayList<ClusterActor> activeSite, ArrayList<ClusterActor> standbySite, String port) {
+ log.info("isolateSiteFromCluster(): Halting Akka traffic...");
+ for(ClusterActor actor : standbySite) {
+ try {
+ log.info("Halting Akka traffic for: {}", actor.getNode());
+ // Build JSON with activeSite actor Node and actor AkkaPort
+ JSONObject akkaInput = new JSONObject();
+ JSONObject inputBlock = new JSONObject();
+ JSONArray votingStateArray = new JSONArray();
+ JSONObject nodeInfo;
+ for(ClusterActor node : activeSite) {
+ nodeInfo = new JSONObject();
+ nodeInfo.put("node", node.getNode());
+ nodeInfo.put("port", node.getAkkaPort());
+ votingStateArray.put(nodeInfo);
+ }
+ inputBlock.put("node-info", votingStateArray);
+ akkaInput.put("input", inputBlock);
+ ConnectionResponse response = ConnectionManager.getConnectionResponse(httpProtocol + actor.getNode() + ":" + port + "/restconf/operations/gr-toolkit:halt-akka-traffic", ConnectionManager.HttpMethod.POST, akkaInput.toString(), "");
+ } catch(IOException e) {
+ log.error("isolateSiteFromCluster(): Could not halt Akka traffic for: " + actor.getNode(), e);
+ }
+ }
+ }
+
+ /**
+ * Invokes the down unreachable action through the Jolokia mbean API.
+ *
+ * @param activeSite list of nodes in the active site
+ * @param standbySite list of nodes in the standby site
+ * @param port http or https port of the controller
+ * @deprecated No longer used since the refactor to use the HealthResolver
+ * pattern. Retained so the logic can be replicated later.
+ */
+ @Deprecated
+ private void downUnreachableNodes(ArrayList<ClusterActor> activeSite, ArrayList<ClusterActor> standbySite, String port) {
+ log.info("downUnreachableNodes(): Setting site unreachable...");
+ JSONObject jolokiaInput = new JSONObject();
+ jolokiaInput.put("type", "EXEC");
+ jolokiaInput.put("mbean", "akka:type=Cluster");
+ jolokiaInput.put("operation", "down");
+ JSONArray arguments = new JSONArray();
+ for(ClusterActor actor : activeSite) {
+ // Build Jolokia input
+ // May need to change from akka port to actor.getAkkaPort()
+ arguments.put("akka.tcp://opendaylight-cluster-data@" + actor.getNode() + ":" + properties.getProperty(PropertyKeys.CONTROLLER_PORT_AKKA));
+ }
+ jolokiaInput.put("arguments", arguments);
+ log.debug("downUnreachableNodes(): {}", jolokiaInput);
+ try {
+ log.info("downUnreachableNodes(): Setting nodes unreachable");
+ ConnectionResponse response = ConnectionManager.getConnectionResponse(httpProtocol + standbySite.get(0).getNode() + ":" + port + "/jolokia", ConnectionManager.HttpMethod.POST, jolokiaInput.toString(), "");
+ } catch(IOException e) {
+ log.error("downUnreachableNodes(): Error setting nodes unreachable", e);
+ }
+ }
+
+ /**
+ * Triggers a data backup and export sequence of MD-SAL data. Invokes the
+ * {@code data-export-import:schedule-export} RPC to schedule a data export
+ * and subsequently the {@code daexim-offsite-backup:backup-data} RPC
+ * against the active site to export and backup the data. Assumes the
+ * controllers have the org.onap.ccsdk.sli.northbound.daeximoffsitebackup
+ * bundle installed.
+ *
+ * @param activeSite list of nodes in the active site
+ * @param port http or https port of the controller
+ * @deprecated No longer used since the refactor to use the HealthResolver
+ * pattern. Retained so the logic can be replicated later.
+ */
+ @Deprecated
+ private void backupMdSal(ArrayList<ClusterActor> activeSite, String port) {
+ log.info("backupMdSal(): Backing up data...");
+ try {
+ log.info("backupMdSal(): Scheduling backup for: {}", activeSite.get(0).getNode());
+ ConnectionResponse response = ConnectionManager.getConnectionResponse(httpProtocol + activeSite.get(0).getNode() + ":" + port + "/restconf/operations/data-export-import:schedule-export", ConnectionManager.HttpMethod.POST, "{ \"input\": { \"run-at\": \"30\" } }", "");
+ } catch(IOException e) {
+ log.error("backupMdSal(): Error backing up MD-SAL", e);
+ }
+ for(ClusterActor actor : activeSite) {
+ try {
+ // Move data offsite
+ log.info("backupMdSal(): Backing up data for: {}", actor.getNode());
+ ConnectionResponse response = ConnectionManager.getConnectionResponse(httpProtocol + actor.getNode() + ":" + port + "/restconf/operations/daexim-offsite-backup:backup-data", ConnectionManager.HttpMethod.POST, null, "");
+ } catch(IOException e) {
+ log.error("backupMdSal(): Error backing up data.", e);
+ }
+ }
+ }
+
+ /**
+ * Builds a response object for {@code clusterHealth()}. Sorts and iterates
+ * over the contents of the {@code memberMap}, which contains the health
+ * information of the cluster, and adds them to the {@code outputBuilder}.
+ * If the ClusterActor is healthy, according to
+ * {@code resolver.isControllerHealthy()}, the {@code ClusterHealthOutput}
+ * status has a {@code 0} appended, otherwise a {@code 1} is appended. A
+ * status of all zeroes denotes a healthy cluster. This status should be
+ * easily decoded by tools which use the output.
+ *
+ * @return future containing a completed {@code ClusterHealthOutput}
+ * @see ClusterActor
+ * @see ClusterHealthOutput
+ * @see HealthResolver
+ */
+ @SuppressWarnings("unchecked")
+ private ListenableFuture<RpcResult<ClusterHealthOutput>> buildClusterHealthOutput() {
+ ClusterHealthOutputBuilder outputBuilder = new ClusterHealthOutputBuilder();
+ outputBuilder.setServedBy(member);
+ List memberList = new ArrayList<Member>();
+ StringBuilder stat = new StringBuilder();
+ memberMap.values()
+ .stream()
+ .sorted(Comparator.comparingInt(member -> Integer.parseInt(member.getMember().split("-")[1])))
+ .forEach(member -> {
+ memberList.add(new MemberBuilder(member).build());
+ // 0 is a healthy controller, 1 is unhealthy.
+ // The list is sorted so users can decode to find unhealthy nodes
+ // This will also let them figure out health on a per-site basis
+ // Depending on any tools they use with this API
+ if(resolver.isControllerHealthy(member)) {
+ stat.append("0");
+ } else {
+ stat.append("1");
+ }
+ });
+ outputBuilder.setStatus(stat.toString());
+ outputBuilder.setMembers(memberList);
+ RpcResult<ClusterHealthOutput> rpcResult = RpcResultBuilder.<ClusterHealthOutput>status(true).withResult(outputBuilder.build()).build();
+ return Futures.immediateFuture(rpcResult);
+ }
+
+ /**
+ * Builds a response object for {@code siteHealth()}. Iterates over a list
+ * of {@code SiteHealth} objects and populates the {@code SiteHealthOutput}
+ * with the information.
+ *
+ * @param sites list of sites
+ * @return future containing a completed {@code SiteHealthOutput}
+ * @see SiteHealth
+ * @see HealthResolver
+ */
+ @SuppressWarnings("unchecked")
+ private ListenableFuture<RpcResult<SiteHealthOutput>> buildSiteHealthOutput(List<SiteHealth> sites) {
+ SiteHealthOutputBuilder outputBuilder = new SiteHealthOutputBuilder();
+ SitesBuilder siteBuilder = new SitesBuilder();
+ outputBuilder.setStatus("200");
+ outputBuilder.setSites((List) new ArrayList<Site>());
+
+ for(SiteHealth site : sites) {
+ siteBuilder.setHealth(site.getHealth().toString());
+ siteBuilder.setRole(site.getRole());
+ siteBuilder.setId(site.getId());
+ outputBuilder.getSites().add(siteBuilder.build());
+ log.info("buildSiteHealthOutput(): Health for {}: {}", site.getId(), site.getHealth().getHealth());
+ }
+
+ outputBuilder.setServedBy(member);
+ RpcResult<SiteHealthOutput> rpcResult = RpcResultBuilder.<SiteHealthOutput>status(true).withResult(outputBuilder.build()).build();
+ return Futures.immediateFuture(rpcResult);
+ }
+
+ /**
+ * Parses a line containing the akka networking information of the akka
+ * controller cluster. Assumes entries of the format:
+ * <p>
+ * akka.tcp://opendaylight-cluster-data@<FQDN>:<AKKA_PORT>
+ * <p>
+ * The information is stored in a {@code ClusterActor} object, and then
+ * added to the memberMap HashMap, with the {@code FQDN} as the key. The
+ * final step is a call to {@code createHealthResolver} to create the
+ * health resolver for the provider.
+ *
+ * @param line the line containing all of the seed nodes
+ * @see ClusterActor
+ * @see HealthResolver
+ */
+ private void parseSeedNodes(String line) {
+ memberMap = new HashMap<>();
+ line = line.substring(line.indexOf("[\""), line.indexOf(']'));
+ String[] splits = line.split(",");
+
+ for(int ndx = 0; ndx < splits.length; ndx++) {
+ String nodeName = splits[ndx];
+ int delimLocation = nodeName.indexOf('@');
+ String port = nodeName.substring(splits[ndx].indexOf(':', delimLocation) + 1, splits[ndx].indexOf('"', splits[ndx].indexOf(':')));
+ splits[ndx] = nodeName.substring(delimLocation + 1, splits[ndx].indexOf(':', delimLocation));
+ log.info("parseSeedNodes(): Adding node: {}:{}", splits[ndx], port);
+ ClusterActor clusterActor = new ClusterActor();
+ clusterActor.setNode(splits[ndx]);
+ clusterActor.setAkkaPort(port);
+ clusterActor.setMember("member-" + (ndx + 1));
+ if(member.equals(clusterActor.getMember())) {
+ self = clusterActor;
+ }
+ memberMap.put(clusterActor.getNode(), clusterActor);
+ log.info("parseSeedNodes(): {}", clusterActor);
+ }
+
+ createHealthResolver();
+ }
+
+ /**
+ * Creates the specific health resolver requested by the user, as specified
+ * in the gr-toolkit.properties file. If a resolver is not specified, or
+ * there is an issue creating the resolver, it will use a fallback resolver
+ * based on how many nodes are added to the memberMap HashMap.
+ *
+ * @see HealthResolver
+ * @see SingleNodeHealthResolver
+ * @see ThreeNodeHealthResolver
+ * @see SixNodeHealthResolver
+ */
+ private void createHealthResolver() {
+ log.info("createHealthResolver(): Creating health resolver...");
+ try {
+ Class resolverClass = null;
+ String userDefinedResolver = properties.getProperty(PropertyKeys.RESOLVER);
+ if(StringUtils.isEmpty(userDefinedResolver)) {
+ throw new InstantiationException();
+ }
+ resolverClass = Class.forName(userDefinedResolver);
+ Class[] types = { Map.class , properties.getClass(), DbLibService.class };
+ Constructor<HealthResolver> constructor = resolverClass.getConstructor(types);
+ Object[] parameters = { memberMap, properties, dbLib };
+ resolver = constructor.newInstance(parameters);
+ log.info("createHealthResolver(): Created resolver from name {}", resolver.toString());
+ } catch(ClassNotFoundException | InstantiationException | InvocationTargetException | NoSuchMethodException | IllegalAccessException e) {
+ log.warn("createHealthResolver(): Could not create user defined resolver", e);
+ if(memberMap.size() == 1) {
+ log.info("createHealthResolver(): FALLBACK: Initializing SingleNodeHealthResolver...");
+ resolver = new SingleNodeHealthResolver(memberMap, properties, dbLib);
+ } else if(memberMap.size() == 3) {
+ log.info("createHealthResolver(): FALLBACK: Initializing ThreeNodeHealthResolver...");
+ resolver = new ThreeNodeHealthResolver(memberMap, properties, dbLib);
+ } else if(memberMap.size() == 6) {
+ log.info("createHealthResolver(): FALLBACK: Initializing SixNodeHealthResolver...");
+ resolver = new SixNodeHealthResolver(memberMap, properties, dbLib);
+ }
+ }
+ }
+
+ /**
+ * Adds or drops IPTables rules to block or resume akka traffic for a node
+ * in the akka cluster. Assumes that the user or group that the controller
+ * is run as has the ability to run sudo /sbin/iptables without requiring a
+ * password. This method will run indefinitely if that assumption is not
+ * correct. This method does not check to see if any rules around the node
+ * are preexisting, so multiple uses will result in multiple additions and
+ * removals from IPTables.
+ *
+ * @param task the operation to be performed against IPTables
+ * @param nodeInfo array containing the nodes to be added or dropped from
+ * IPTables
+ */
+ private void modifyIpTables(IpTables task, Object[] nodeInfo) {
+ log.info("modifyIpTables(): Modifying IPTables rules...");
+ if(task == IpTables.ADD) {
+ for(Object node : nodeInfo) {
+ org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.plugins.gr.toolkit.rev180926.halt.akka.traffic.input.NodeInfo n =
+ (org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.plugins.gr.toolkit.rev180926.halt.akka.traffic.input.NodeInfo) node;
+ log.info("modifyIpTables(): Isolating {}", n.getNode());
+ executeCommand(String.format("sudo /sbin/iptables -A INPUT -p tcp --destination-port %s -j DROP -s %s", properties.get(PropertyKeys.CONTROLLER_PORT_AKKA), n.getNode()));
+ executeCommand(String.format("sudo /sbin/iptables -A OUTPUT -p tcp --destination-port %s -j DROP -d %s", n.getPort(), n.getNode()));
+ }
+ } else if(task == IpTables.DELETE) {
+ for(Object node : nodeInfo) {
+ org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.plugins.gr.toolkit.rev180926.resume.akka.traffic.input.NodeInfo n =
+ (org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.plugins.gr.toolkit.rev180926.resume.akka.traffic.input.NodeInfo) node;
+ log.info("modifyIpTables(): De-isolating {}", n.getNode());
+ executeCommand(String.format("sudo /sbin/iptables -D INPUT -p tcp --destination-port %s -j DROP -s %s", properties.get(PropertyKeys.CONTROLLER_PORT_AKKA), n.getNode()));
+ executeCommand(String.format("sudo /sbin/iptables -D OUTPUT -p tcp --destination-port %s -j DROP -d %s", n.getPort(), n.getNode()));
+ }
+ }
+ if(nodeInfo.length > 0) {
+ executeCommand("sudo /sbin/iptables -L");
+ }
+ }
+
+ /**
+ * Opens a shell session and executes a command.
+ *
+ * @param command the shell command to execute
+ */
+ private void executeCommand(String command) {
+ log.info("executeCommand(): Executing command: {}", command);
+ String[] cmd = command.split(" ");
+ try {
+ Process p = Runtime.getRuntime().exec(cmd);
+ BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(p.getInputStream()));
+ String inputLine;
+ StringBuilder content = new StringBuilder();
+ while((inputLine = bufferedReader.readLine()) != null) {
+ content.append(inputLine);
+ }
+ bufferedReader.close();
+ log.info("executeCommand(): {}", content);
+ } catch(IOException e) {
+ log.error("executeCommand(): Error executing command", e);
+ }
+ }
+
+ /**
+ * The IPTables operations this module can perform.
+ */
+ enum IpTables {
+ ADD,
+ DELETE
+ }
+} \ No newline at end of file
diff --git a/plugins/grToolkit/provider/src/main/java/org/onap/ccsdk/sli/plugins/grtoolkit/connection/ConnectionManager.java b/plugins/grToolkit/provider/src/main/java/org/onap/ccsdk/sli/plugins/grtoolkit/connection/ConnectionManager.java
new file mode 100644
index 000000000..99fcd3e04
--- /dev/null
+++ b/plugins/grToolkit/provider/src/main/java/org/onap/ccsdk/sli/plugins/grtoolkit/connection/ConnectionManager.java
@@ -0,0 +1,157 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.grtoolkit.connection;
+
+import org.apache.commons.lang.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.nio.charset.StandardCharsets;
+
+/**
+ * Handles the process for getting HTTP connections to resources. Has the
+ * ability to send JSON payloads. Only supports basic authorization when
+ * sending credentials.
+ *
+ * @author Anthony Haddox
+ * @see ConnectionResponse
+ */
+public interface ConnectionManager {
+ Logger log = LoggerFactory.getLogger(ConnectionManager.class);
+ int CONNECTION_TIMEOUT = 5000; // 5 second timeout
+ enum HttpMethod {
+ GET("GET"),
+ POST("POST");
+
+ private final String method;
+ HttpMethod(String method) {
+ this.method = method;
+ }
+ String getMethod() {
+ return method;
+ }
+ }
+
+ /**
+ * Writes a JSON payload to an {@code HTTPURLConnection OutputStream}.
+ *
+ * @param input the JSON payload to send
+ * @param connection the {@code HTTPURLConnection} to write to
+ * @throws IOException if there is a problem writing to the output stream
+ */
+ static void sendPayload(String input, HttpURLConnection connection) throws IOException {
+ byte[] out = input.getBytes(StandardCharsets.UTF_8);
+ int length = out.length;
+
+ connection.setFixedLengthStreamingMode(length);
+ connection.setRequestProperty("Content-Type", "application/json");
+ connection.setDoOutput(true);
+ connection.connect();
+ try(OutputStream os = connection.getOutputStream()) {
+ os.write(out);
+ }
+ }
+
+ /**
+ * Gets an {@code HTTPURLConnection} to a {@code host}.
+ *
+ * @param host the host to connect to
+ * @return an {@code HTTPURLConnection}
+ * @throws IOException if a connection cannot be opened
+ */
+ static HttpURLConnection getConnection(String host) throws IOException {
+ log.info("getConnection(): Getting connection to: {}", host);
+ URL url = new URL(host);
+ HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+ connection.setRequestProperty("Connection", "keep-alive");
+ connection.setRequestProperty("Proxy-Connection", "keep-alive");
+ connection.setConnectTimeout(CONNECTION_TIMEOUT);
+ connection.setReadTimeout(CONNECTION_TIMEOUT);
+ return connection;
+ }
+
+ /**
+ * Gets an {@code HTTPURLConnection} to a {@code host} and sets the
+ * Authorization header with the supplied credentials. Only supports basic
+ * authentication.
+ *
+ * @param host the host to connect to
+ * @param credentials the authorization credentials
+ * @return an {@code HTTPURLConnection} with Authorization header set
+ * @throws IOException if a connection cannot be opened
+ */
+ static HttpURLConnection getConnection(String host, String credentials) throws IOException {
+ String auth = "Basic " + javax.xml.bind.DatatypeConverter.printBase64Binary(credentials.getBytes());
+ HttpURLConnection connection = getConnection(host);
+ connection.addRequestProperty("Authorization", auth);
+ credentials = null;
+ auth = null;
+ return connection;
+ }
+
+ /**
+ * Opens a connection to a path, sends a payload (if supplied with one),
+ * and returns the response.
+ * @param path the host to connect to
+ * @param method the {@code HttpMethod} to use
+ * @param input the payload to send
+ * @param credentials the credentials to use
+ * @return a {@code ConnectionResponse} containing the response body and
+ * status code of the operation
+ * @throws IOException if a connection cannot be opened or if the payload
+ * cannot be sent
+ * @see HttpMethod
+ */
+ static ConnectionResponse getConnectionResponse(String path, HttpMethod method, String input, String credentials) throws IOException {
+ HttpURLConnection connection = (StringUtils.isEmpty(credentials)) ? getConnection(path) : getConnection(path, credentials);
+ credentials = null;
+ connection.setRequestMethod(method.getMethod());
+ connection.setDoInput(true);
+
+ if(!StringUtils.isEmpty(input)) {
+ sendPayload(input, connection);
+ }
+
+ StringBuilder content = new StringBuilder();
+ try(BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(connection.getInputStream()))) {
+ String inputLine;
+ while((inputLine = bufferedReader.readLine()) != null) {
+ content.append(inputLine);
+ }
+ } finally {
+ connection.disconnect();
+ }
+
+ ConnectionResponse connectionResponse = new ConnectionResponse();
+ connectionResponse.content = content.toString();
+ connectionResponse.statusCode = connection.getResponseCode();
+ log.info("getConnectionResponse(): {} response code from {}", connectionResponse.statusCode, path);
+ log.debug("getConnectionResponse(): Response:\n{}", connectionResponse.content);
+ return connectionResponse;
+ }
+}
diff --git a/plugins/grToolkit/provider/src/main/java/org/onap/ccsdk/sli/plugins/grtoolkit/connection/ConnectionResponse.java b/plugins/grToolkit/provider/src/main/java/org/onap/ccsdk/sli/plugins/grtoolkit/connection/ConnectionResponse.java
new file mode 100644
index 000000000..fb16d2a12
--- /dev/null
+++ b/plugins/grToolkit/provider/src/main/java/org/onap/ccsdk/sli/plugins/grtoolkit/connection/ConnectionResponse.java
@@ -0,0 +1,43 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.grtoolkit.connection;
+
+/**
+ * A data container for HTTP connection requests.
+ *
+ * @author Anthony Haddox
+ * @see ConnectionManager
+ */
+public class ConnectionResponse {
+ public int statusCode;
+ public String content;
+
+ public ConnectionResponse withStatusCode(int statusCode) {
+ this.statusCode = statusCode;
+ return this;
+ }
+
+ @Override
+ public String toString() {
+ return "Status: " + statusCode + "\nContent: " + content;
+ }
+}
diff --git a/plugins/grToolkit/provider/src/main/java/org/onap/ccsdk/sli/plugins/grtoolkit/data/AdminHealth.java b/plugins/grToolkit/provider/src/main/java/org/onap/ccsdk/sli/plugins/grtoolkit/data/AdminHealth.java
new file mode 100644
index 000000000..0e88df55e
--- /dev/null
+++ b/plugins/grToolkit/provider/src/main/java/org/onap/ccsdk/sli/plugins/grtoolkit/data/AdminHealth.java
@@ -0,0 +1,58 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.grtoolkit.data;
+
+/**
+ * A data container for Admin health.
+ *
+ * @author Anthony Haddox
+ * @see org.onap.ccsdk.sli.plugins.grtoolkit.resolver.HealthResolver
+ */
+public class AdminHealth {
+ private Health health;
+ private int statusCode;
+
+ public AdminHealth(Health health) {
+ this.health = health;
+ }
+
+ public AdminHealth(Health health, int statusCode) {
+ this.health = health;
+ this.statusCode = statusCode;
+ }
+
+ public Health getHealth() {
+ return health;
+ }
+
+ public void setHealth(Health health) {
+ this.health = health;
+ }
+
+ public int getStatusCode() {
+ return statusCode;
+ }
+
+ public void setStatusCode(int statusCode) {
+ this.statusCode = statusCode;
+ }
+}
diff --git a/plugins/grToolkit/provider/src/main/java/org/onap/ccsdk/sli/plugins/grtoolkit/data/ClusterActor.java b/plugins/grToolkit/provider/src/main/java/org/onap/ccsdk/sli/plugins/grtoolkit/data/ClusterActor.java
new file mode 100644
index 000000000..d039c865e
--- /dev/null
+++ b/plugins/grToolkit/provider/src/main/java/org/onap/ccsdk/sli/plugins/grtoolkit/data/ClusterActor.java
@@ -0,0 +1,222 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2018 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.grtoolkit.data;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * A data container with information about an actor in the Akka cluster.
+ *
+ * @author Anthony Haddox
+ */
+public class ClusterActor {
+ private String node;
+ private String member;
+ private String site;
+ private String akkaPort;
+ private boolean voting;
+ private boolean up;
+ private boolean unreachable;
+ private ArrayList<String> shardLeader;
+ private ArrayList<String> replicaShards;
+ private ArrayList<String> nonReplicaShards;
+ private HashMap<String, Integer> commits;
+
+ public static final String SITE_1 = "Site 1";
+ public static final String SITE_2 = "Site 2";
+
+ public ClusterActor() {
+ node = "";
+ member = "";
+ site = "";
+ voting = false;
+ up = false;
+ unreachable = false;
+ shardLeader = new ArrayList<>();
+ replicaShards = new ArrayList<>();
+ nonReplicaShards = new ArrayList<>();
+ commits = new HashMap<>();
+ }
+
+ public String getNode() {
+ return node;
+ }
+
+ public void setNode(String node) {
+ this.node = node;
+ }
+
+ public String getMember() {
+ return member;
+ }
+
+ public void setMember(String member) {
+ this.member = member;
+ }
+
+ public String getSite() {
+ return site;
+ }
+
+ public void setSite(String site) {
+ this.site = site;
+ }
+
+ public String getAkkaPort() {
+ return akkaPort;
+ }
+
+ public void setAkkaPort(String akkaPort) {
+ this.akkaPort = akkaPort;
+ }
+
+ public boolean isVoting() {
+ return voting;
+ }
+
+ public void setVoting(boolean voting) {
+ this.voting = voting;
+ }
+
+ public boolean isUp() {
+ return up;
+ }
+
+ public void setUp(boolean up) {
+ this.up = up;
+ }
+
+ public boolean isUnreachable() {
+ return unreachable;
+ }
+
+ public void setUnreachable(boolean unreachable) {
+ this.unreachable = unreachable;
+ }
+
+ public List<String> getShardLeader() {
+ return shardLeader;
+ }
+
+ public void setShardLeader(List<String> shardLeader) {
+ this.shardLeader = (ArrayList<String>) shardLeader;
+ }
+
+ public List<String> getReplicaShards() {
+ return replicaShards;
+ }
+
+ public void setReplicaShards(List<String> replicaShards) {
+ this.replicaShards = (ArrayList<String>) replicaShards;
+ }
+
+ public List<String> getNonReplicaShards() {
+ return nonReplicaShards;
+ }
+
+ public void setNonReplicaShards(List<String> nonReplicaShards) {
+ this.nonReplicaShards = (ArrayList<String>) nonReplicaShards;
+ }
+
+ public Map<String, Integer> getCommits() {
+ return commits;
+ }
+
+ public void setCommits(Map<String, Integer> commits) {
+ this.commits = (HashMap<String, Integer>) commits;
+ }
+
+ public void flush() {
+ shardLeader.clear();
+ replicaShards.clear();
+ nonReplicaShards.clear();
+ commits.clear();
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder builder = new StringBuilder();
+ builder.append("[ ");
+ builder.append(this.member);
+ builder.append(" ] ");
+
+ builder.append(this.node);
+ builder.append(":");
+ builder.append(this.akkaPort);
+ builder.append(" is");
+ if(up)
+ builder.append(" Up");
+ else
+ builder.append(" Down");
+ if(unreachable) {
+ builder.append(" [ UNREACHABLE ]");
+ return builder.toString();
+ }
+
+ if(voting)
+ builder.append(" (Voting)");
+
+ builder.append("\n");
+
+ for(String l : this.shardLeader) {
+ builder.append("\tLeader: ");
+ builder.append(l);
+ builder.append("\n");
+ }
+
+ for(String r : this.replicaShards) {
+ builder.append("\tReplicating: ");
+ builder.append(r);
+ builder.append("\n");
+ }
+
+ for(String n : this.nonReplicaShards) {
+ builder.append("\tNot replicating: ");
+ builder.append(n);
+ builder.append("\n");
+ }
+
+ for(Map.Entry<String, Integer> entry : commits.entrySet()) {
+ String key = entry.getKey();
+ int value = entry.getValue();
+ if(value > 0) {
+ builder.append("\t");
+ builder.append(value);
+ builder.append(" commits ahead of ");
+ builder.append(key);
+ builder.append("\n");
+ }
+ else if(value < 0) {
+ builder.append("\t");
+ builder.append(value);
+ builder.append(" commits behind ");
+ builder.append(key);
+ builder.append("\n");
+ }
+ }
+
+ return builder.toString();
+ }
+}
diff --git a/plugins/grToolkit/provider/src/main/java/org/onap/ccsdk/sli/plugins/grtoolkit/data/ClusterHealth.java b/plugins/grToolkit/provider/src/main/java/org/onap/ccsdk/sli/plugins/grtoolkit/data/ClusterHealth.java
new file mode 100644
index 000000000..52198225d
--- /dev/null
+++ b/plugins/grToolkit/provider/src/main/java/org/onap/ccsdk/sli/plugins/grtoolkit/data/ClusterHealth.java
@@ -0,0 +1,49 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.grtoolkit.data;
+
+/**
+ * A data container for Akka Cluster health.
+ *
+ * @author Anthony Haddox
+ * @see org.onap.ccsdk.sli.plugins.grtoolkit.resolver.HealthResolver
+ */
+public class ClusterHealth {
+ private Health health;
+
+ public ClusterHealth() {
+ health = Health.FAULTY;
+ }
+
+ public ClusterHealth withHealth(Health h) {
+ this.health = h;
+ return this;
+ }
+
+ public Health getHealth() {
+ return health;
+ }
+
+ public void setHealth(Health health) {
+ this.health = health;
+ }
+}
diff --git a/plugins/grToolkit/provider/src/main/java/org/onap/ccsdk/sli/plugins/grtoolkit/data/DatabaseHealth.java b/plugins/grToolkit/provider/src/main/java/org/onap/ccsdk/sli/plugins/grtoolkit/data/DatabaseHealth.java
new file mode 100644
index 000000000..14c11b51a
--- /dev/null
+++ b/plugins/grToolkit/provider/src/main/java/org/onap/ccsdk/sli/plugins/grtoolkit/data/DatabaseHealth.java
@@ -0,0 +1,44 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.grtoolkit.data;
+
+/**
+ * A data container for Database health.
+ *
+ * @author Anthony Haddox
+ * @see org.onap.ccsdk.sli.plugins.grtoolkit.resolver.HealthResolver
+ */
+public class DatabaseHealth {
+ private Health health;
+
+ public DatabaseHealth(Health health) {
+ this.health = health;
+ }
+
+ public Health getHealth() {
+ return health;
+ }
+
+ public void setHealth(Health health) {
+ this.health = health;
+ }
+}
diff --git a/plugins/grToolkit/provider/src/main/java/org/onap/ccsdk/sli/plugins/grtoolkit/data/FailoverStatus.java b/plugins/grToolkit/provider/src/main/java/org/onap/ccsdk/sli/plugins/grtoolkit/data/FailoverStatus.java
new file mode 100644
index 000000000..7366ede43
--- /dev/null
+++ b/plugins/grToolkit/provider/src/main/java/org/onap/ccsdk/sli/plugins/grtoolkit/data/FailoverStatus.java
@@ -0,0 +1,64 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.grtoolkit.data;
+
+/**
+ * A data container for the status of a controller-level failover.
+ *
+ * @author Anthony Haddox
+ * @see org.onap.ccsdk.sli.plugins.grtoolkit.resolver.HealthResolver
+ */
+public class FailoverStatus {
+ private int statusCode;
+ private String message;
+
+ public FailoverStatus() {
+ this.statusCode = 200;
+ this.message = "Failover complete.";
+ }
+
+ public FailoverStatus withStatusCode(int code) {
+ this.statusCode = code;
+ return this;
+ }
+
+ public FailoverStatus withMessage(String message) {
+ this.message = message;
+ return this;
+ }
+
+ public int getStatusCode() {
+ return statusCode;
+ }
+
+ public void setStatusCode(int statusCode) {
+ this.statusCode = statusCode;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public void setMessage(String message) {
+ this.message = message;
+ }
+}
diff --git a/plugins/grToolkit/provider/src/main/java/org/onap/ccsdk/sli/plugins/grtoolkit/data/Health.java b/plugins/grToolkit/provider/src/main/java/org/onap/ccsdk/sli/plugins/grtoolkit/data/Health.java
new file mode 100644
index 000000000..deb5cb444
--- /dev/null
+++ b/plugins/grToolkit/provider/src/main/java/org/onap/ccsdk/sli/plugins/grtoolkit/data/Health.java
@@ -0,0 +1,40 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.grtoolkit.data;
+
+/**
+ * Potential health values.
+ *
+ * @author Anthony Haddox
+ */
+public enum Health {
+ HEALTHY("HEALTHY"),
+ FAULTY("FAULTY");
+
+ private final String health;
+ Health(String health) {
+ this.health = health;
+ }
+ public String getHealth() {
+ return health;
+ }
+}
diff --git a/plugins/grToolkit/provider/src/main/java/org/onap/ccsdk/sli/plugins/grtoolkit/data/MemberBuilder.java b/plugins/grToolkit/provider/src/main/java/org/onap/ccsdk/sli/plugins/grtoolkit/data/MemberBuilder.java
new file mode 100644
index 000000000..863b56674
--- /dev/null
+++ b/plugins/grToolkit/provider/src/main/java/org/onap/ccsdk/sli/plugins/grtoolkit/data/MemberBuilder.java
@@ -0,0 +1,88 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2018 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.grtoolkit.data;
+
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.plugins.gr.toolkit.rev180926.cluster.health.output.MembersBuilder;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.plugins.gr.toolkit.rev180926.member.CommitStatusBuilder;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.plugins.gr.toolkit.rev180926.member.ReplicasBuilder;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.plugins.gr.toolkit.rev180926.member.LeaderBuilder;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Extends the {@code MembersBuilder} generated from the gr-toolkit.yang model.
+ * Uses information from a {@code ClusterActor} to populate the builder fields.
+ *
+ * @author Anthony Haddox
+ * @see ClusterActor
+ * @see org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.plugins.gr.toolkit.rev180926.cluster.health.output.MembersBuilder
+ */
+public class MemberBuilder extends MembersBuilder {
+ public MemberBuilder(ClusterActor actor) {
+ super();
+ this.setAddress(actor.getNode());
+ this.setRole(actor.getMember());
+ this.setVoting(actor.isVoting());
+ this.setUp(actor.isUp());
+ this.setUnreachable(actor.isUnreachable());
+ populateReplicas(actor.getReplicaShards());
+ populateCommits(actor.getCommits());
+ populateLeader(actor.getShardLeader());
+ }
+
+ private void populateLeader(List<String> shardLeader) {
+ LeaderBuilder builder;
+ this.setLeader(new ArrayList<>());
+ for(String leader : shardLeader) {
+ builder = new LeaderBuilder();
+ builder.setShard(leader);
+ this.getLeader().add(builder.build());
+ }
+ }
+
+ private void populateCommits(Map<String, Integer> commits) {
+ CommitStatusBuilder builder;
+ this.setCommitStatus(new ArrayList<>());
+ for(Map.Entry<String, Integer> entry : commits.entrySet()) {
+ String key = entry.getKey();
+ Integer value = entry.getValue();
+ if(value != 0) {
+ builder = new CommitStatusBuilder();
+ builder.setShard(key);
+ builder.setDelta(value);
+ this.getCommitStatus().add(builder.build());
+ }
+ }
+ }
+
+ private void populateReplicas(List<String> replicaShards) {
+ ReplicasBuilder builder;
+ this.setReplicas(new ArrayList<>());
+ for(String shard : replicaShards) {
+ builder = new ReplicasBuilder();
+ builder.setShard(shard);
+ this.getReplicas().add(builder.build());
+ }
+ }
+}
diff --git a/plugins/grToolkit/provider/src/main/java/org/onap/ccsdk/sli/plugins/grtoolkit/data/PropertyKeys.java b/plugins/grToolkit/provider/src/main/java/org/onap/ccsdk/sli/plugins/grtoolkit/data/PropertyKeys.java
new file mode 100644
index 000000000..f2ad90a7f
--- /dev/null
+++ b/plugins/grToolkit/provider/src/main/java/org/onap/ccsdk/sli/plugins/grtoolkit/data/PropertyKeys.java
@@ -0,0 +1,40 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.ccsdk.sli.plugins.grtoolkit.data;
+
+public interface PropertyKeys {
+ String RESOLVER = "resolver";
+ String SITE_IDENTIFIER = "site.identifier";
+ String CONTROLLER_USE_SSL = "controller.useSsl";
+ String CONTROLLER_PORT_SSL = "controller.port.ssl";
+ String CONTROLLER_PORT_HTTP = "controller.port.http";
+ String CONTROLLER_PORT_AKKA = "controller.port.akka";
+ String CONTROLLER_CREDENTIALS = "controller.credentials";
+ String AKKA_CONF_LOCATION = "akka.conf.location";
+ String MBEAN_CLUSTER = "mbean.cluster";
+ String MBEAN_SHARD_MANAGER = "mbean.shardManager";
+ String MBEAN_SHARD_CONFIG = "mbean.shard.config";
+ String ADM_USE_SSL = "adm.useSsl";
+ String ADM_PORT_SSL = "adm.port.ssl";
+ String ADM_PORT_HTTP = "adm.port.http";
+ String ADM_FQDN = "adm.fqdn";
+ String ADM_HEALTHCHECK= "adm.healthcheck";
+}
diff --git a/plugins/grToolkit/provider/src/main/java/org/onap/ccsdk/sli/plugins/grtoolkit/data/SiteHealth.java b/plugins/grToolkit/provider/src/main/java/org/onap/ccsdk/sli/plugins/grtoolkit/data/SiteHealth.java
new file mode 100644
index 000000000..8407032d5
--- /dev/null
+++ b/plugins/grToolkit/provider/src/main/java/org/onap/ccsdk/sli/plugins/grtoolkit/data/SiteHealth.java
@@ -0,0 +1,125 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.grtoolkit.data;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+
+/**
+ * A data container for Site health.
+ *
+ * @author Anthony Haddox
+ * @see org.onap.ccsdk.sli.plugins.grtoolkit.resolver.HealthResolver
+ */
+public class SiteHealth {
+ private List<AdminHealth> adminHealth;
+ private List<DatabaseHealth> databaseHealth;
+ private List<ClusterHealth> clusterHealth;
+
+ private Health health;
+ private String id;
+ private String role;
+
+ public SiteHealth() {
+ adminHealth = new ArrayList<>();
+ databaseHealth = new ArrayList<>();
+ clusterHealth = new ArrayList<>();
+
+ // Faulty by default, it's up to the health check to affirm the health
+ health = Health.FAULTY;
+ }
+
+ public SiteHealth withAdminHealth(AdminHealth... health) {
+ Collections.addAll(adminHealth, health);
+ return this;
+ }
+
+ public SiteHealth withDatabaseHealth(DatabaseHealth... health) {
+ Collections.addAll(databaseHealth, health);
+ return this;
+ }
+
+ public SiteHealth withClusterHealth(ClusterHealth... health) {
+ Collections.addAll(clusterHealth, health);
+ return this;
+ }
+
+ public SiteHealth withId(String id) {
+ this.id = id;
+ return this;
+ }
+
+ public SiteHealth withRole(String role) {
+ this.role = role;
+ return this;
+ }
+
+ public Health getHealth() {
+ return health;
+ }
+
+ public void setHealth(Health health) {
+ this.health = health;
+ }
+
+ public List<AdminHealth> getAdminHealth() {
+ return adminHealth;
+ }
+
+ public void setAdminHealth(List<AdminHealth> adminHealth) {
+ this.adminHealth = adminHealth;
+ }
+
+ public List<DatabaseHealth> getDatabaseHealth() {
+ return databaseHealth;
+ }
+
+ public void setDatabaseHealth(List<DatabaseHealth> databaseHealth) {
+ this.databaseHealth = databaseHealth;
+ }
+
+ public List<ClusterHealth> getClusterHealth() {
+ return clusterHealth;
+ }
+
+ public void setClusterHealth(List<ClusterHealth> clusterHealth) {
+ this.clusterHealth = clusterHealth;
+ }
+
+ public String getId() {
+ return id;
+ }
+
+ public void setId(String id) {
+ this.id = id;
+ }
+
+ public String getRole() {
+ return role;
+ }
+
+ public void setRole(String role) {
+ this.role = role;
+ }
+}
diff --git a/plugins/grToolkit/provider/src/main/java/org/onap/ccsdk/sli/plugins/grtoolkit/resolver/HealthResolver.java b/plugins/grToolkit/provider/src/main/java/org/onap/ccsdk/sli/plugins/grtoolkit/resolver/HealthResolver.java
new file mode 100644
index 000000000..5c4ed13d7
--- /dev/null
+++ b/plugins/grToolkit/provider/src/main/java/org/onap/ccsdk/sli/plugins/grtoolkit/resolver/HealthResolver.java
@@ -0,0 +1,212 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.grtoolkit.resolver;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import org.onap.ccsdk.sli.core.dblib.DbLibService;
+import org.onap.ccsdk.sli.plugins.grtoolkit.connection.ConnectionManager;
+import org.onap.ccsdk.sli.plugins.grtoolkit.connection.ConnectionResponse;
+import org.onap.ccsdk.sli.plugins.grtoolkit.data.AdminHealth;
+import org.onap.ccsdk.sli.plugins.grtoolkit.data.ClusterActor;
+import org.onap.ccsdk.sli.plugins.grtoolkit.data.ClusterHealth;
+import org.onap.ccsdk.sli.plugins.grtoolkit.data.DatabaseHealth;
+import org.onap.ccsdk.sli.plugins.grtoolkit.data.FailoverStatus;
+import org.onap.ccsdk.sli.plugins.grtoolkit.data.Health;
+import org.onap.ccsdk.sli.plugins.grtoolkit.data.PropertyKeys;
+import org.onap.ccsdk.sli.plugins.grtoolkit.data.SiteHealth;
+
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.plugins.gr.toolkit.rev180926.FailoverInput;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import static org.onap.ccsdk.sli.plugins.grtoolkit.data.Health.HEALTHY;
+
+/**
+ * Abstract class for the Health Resolver system, which allows for custom logic
+ * to be implemented, while leaving inputs/outputs generic and architecture
+ * agnostic. This class provides some simple implementations of both Admin and
+ * Database health checking, but leaves cluster and site health determinations
+ * up to the implementer. Useful implementation examples can be found in the
+ * {@code SingleNodeHealthResolver}, {@code ThreeNodeHealthResolver}, and
+ * {@code SixNodeHealthResolver} classes.
+ *
+ * @author Anthony Haddox
+ * @see org.onap.ccsdk.sli.plugins.grtoolkit.GrToolkitProvider
+ * @see SingleNodeHealthResolver
+ * @see ThreeNodeHealthResolver
+ * @see SixNodeHealthResolver
+ */
+public abstract class HealthResolver {
+ private final Logger log = LoggerFactory.getLogger(HealthResolver.class);
+ static final String OUTPUT = "output";
+ final String httpProtocol;
+ final String controllerPort;
+ final String credentials;
+ final Map<String, ClusterActor> memberMap;
+ private DbLibService dbLib;
+ final ShardResolver shardResolver;
+ private String adminPath;
+ private String siteIdentifier;
+
+ /**
+ * Constructs the health resolver used by the {@code GrToolkitProvider} to
+ * determine the health of the application components.
+ *
+ * @param map a HashMap containing all of the nodes in the akka cluster
+ * @param properties the properties passed ino the provider
+ * @param dbLib a reference to the {@code DbLibService} of the provider
+ * @see org.onap.ccsdk.sli.plugins.grtoolkit.GrToolkitProvider
+ */
+ HealthResolver(Map<String, ClusterActor> map, Properties properties, DbLibService dbLib) {
+ log.info("Creating {}", this.getClass().getCanonicalName());
+ this.memberMap = map;
+ this.dbLib = dbLib;
+ shardResolver = ShardResolver.getInstance(properties);
+
+ String adminProtocol = "true".equals(properties.getProperty(PropertyKeys.ADM_USE_SSL)) ? "https://" : "http://";
+ String adminPort = "true".equals(properties.getProperty(PropertyKeys.ADM_USE_SSL)) ? properties.getProperty(PropertyKeys.ADM_PORT_SSL) : properties.getProperty(PropertyKeys.ADM_PORT_HTTP);
+ adminPath = adminProtocol + properties.getProperty(PropertyKeys.ADM_FQDN) + ":" + adminPort + properties.getProperty(PropertyKeys.ADM_HEALTHCHECK);
+ siteIdentifier = properties.getProperty(PropertyKeys.SITE_IDENTIFIER).trim();
+
+ controllerPort = "true".equals(properties.getProperty(PropertyKeys.CONTROLLER_USE_SSL).trim()) ? properties.getProperty(PropertyKeys.CONTROLLER_PORT_SSL).trim() : properties.getProperty(PropertyKeys.CONTROLLER_PORT_HTTP).trim();
+ httpProtocol = "true".equals(properties.getProperty(PropertyKeys.CONTROLLER_USE_SSL).trim()) ? "https://" : "http://";
+ if(siteIdentifier == null || siteIdentifier.isEmpty()) {
+ siteIdentifier = properties.getProperty(PropertyKeys.SITE_IDENTIFIER).trim();
+ }
+ credentials = properties.getProperty(PropertyKeys.CONTROLLER_CREDENTIALS).trim();
+ }
+
+ public abstract ClusterHealth getClusterHealth();
+ public abstract List<SiteHealth> getSiteHealth();
+ public abstract FailoverStatus tryFailover(FailoverInput input);
+ public abstract void resolveSites();
+
+ /**
+ * Gets a connection to the admin portal. If the status code is 200, the
+ * admin portal is assumed to be healthy.
+ *
+ * @return an {@code AdminHealth} object with health of the admin portal
+ * @see org.onap.ccsdk.sli.plugins.grtoolkit.GrToolkitProvider
+ * @see AdminHealth
+ */
+ public AdminHealth getAdminHealth() {
+ log.info("getAdminHealth(): Requesting health check from {}", adminPath);
+ try {
+ ConnectionResponse response = ConnectionManager.getConnectionResponse(adminPath, ConnectionManager.HttpMethod.GET, null, null);
+ Health health = (response.statusCode == 200) ? HEALTHY : Health.FAULTY;
+ AdminHealth adminHealth = new AdminHealth(health, response.statusCode);
+ log.info("getAdminHealth(): Response: {}", response);
+ return adminHealth;
+ } catch(IOException e) {
+ log.error("getAdminHealth(): Problem getting ADM health.", e);
+ return new AdminHealth(Health.FAULTY, 500);
+ }
+ }
+
+ /**
+ * Uses {@code DbLibService} to get a connection to the database. If
+ * {@code DbLibService} is active and the connection it returns is not read
+ * only, the database(s) is assumed to be healthy.
+ *
+ * @return an {@code DatabaseHealth} object with health of the database
+ * @see org.onap.ccsdk.sli.plugins.grtoolkit.GrToolkitProvider
+ * @see DatabaseHealth
+ */
+ public DatabaseHealth getDatabaseHealth() {
+ log.info("getDatabaseHealth(): Determining database health...");
+ try (Connection connection = dbLib.getConnection()){
+ log.debug("getDatabaseHealth(): DBLib isActive(): {}", dbLib.isActive());
+ log.debug("getDatabaseHealth(): DBLib isReadOnly(): {}", connection.isReadOnly());
+ log.debug("getDatabaseHealth(): DBLib isClosed(): {}", connection.isClosed());
+ if(!dbLib.isActive() || connection.isClosed() || connection.isReadOnly()) {
+ log.warn("getDatabaseHealth(): Database is FAULTY");
+ return new DatabaseHealth(Health.FAULTY);
+ }
+ log.info("getDatabaseHealth(): Database is HEALTHY");
+ } catch(SQLException e) {
+ log.error("getDatabaseHealth(): Database is FAULTY");
+ log.error("getDatabaseHealth(): Error", e);
+ return new DatabaseHealth(Health.FAULTY);
+ }
+
+ return new DatabaseHealth(HEALTHY);
+ }
+
+ /**
+ * Utility method to see if an input is healthy.
+ *
+ * @return true if the input is healthy
+ * @see Health
+ */
+ boolean isHealthy(Health h) {
+ return HEALTHY == h;
+ }
+
+ public String getSiteIdentifier() {
+ return siteIdentifier;
+ }
+
+ public void setSiteIdentifier(String siteIdentifier) {
+ this.siteIdentifier = siteIdentifier;
+ }
+
+ /**
+ * Used to invoke the admin-health or database-health RPC to check if that
+ * component is healthy.
+ *
+ * @param path the path to the admin-health or database-health RPCs
+ * @return true if the component is healthy
+ * @throws IOException if a connection cannot be obtained
+ */
+ boolean isRemoteComponentHealthy(String path) throws IOException {
+ String content = ConnectionManager.getConnectionResponse(path, ConnectionManager.HttpMethod.POST, null, credentials).content;
+ try {
+ JSONObject responseJson = new JSONObject(content);
+ JSONObject responseValue = responseJson.getJSONObject(OUTPUT);
+ return HEALTHY.toString().equals(responseValue.getString("health"));
+ } catch(JSONException e) {
+ log.error("Error parsing JSON", e);
+ throw new IOException();
+ }
+ }
+
+ /**
+ * Checks a {@code ClusterActor} object to see if the node is healthy.
+ *
+ * @param controller the controller to check
+ * @return true if the controller is up and reachable
+ * @see ClusterActor
+ */
+ public boolean isControllerHealthy(ClusterActor controller) {
+ return (controller.isUp() && ! controller.isUnreachable());
+ }
+}
diff --git a/plugins/grToolkit/provider/src/main/java/org/onap/ccsdk/sli/plugins/grtoolkit/resolver/ShardResolver.java b/plugins/grToolkit/provider/src/main/java/org/onap/ccsdk/sli/plugins/grtoolkit/resolver/ShardResolver.java
new file mode 100644
index 000000000..8e96bff0c
--- /dev/null
+++ b/plugins/grToolkit/provider/src/main/java/org/onap/ccsdk/sli/plugins/grtoolkit/resolver/ShardResolver.java
@@ -0,0 +1,177 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.grtoolkit.resolver;
+
+import org.json.JSONArray;
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import org.onap.ccsdk.sli.plugins.grtoolkit.connection.ConnectionManager;
+import org.onap.ccsdk.sli.plugins.grtoolkit.connection.ConnectionResponse;
+import org.onap.ccsdk.sli.plugins.grtoolkit.data.ClusterActor;
+import org.onap.ccsdk.sli.plugins.grtoolkit.data.PropertyKeys;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * Used to perform operations on the data shard information returned as JSON
+ * from Jolokia.
+ *
+ * @author Anthony Haddox
+ * @see org.onap.ccsdk.sli.plugins.grtoolkit.GrToolkitProvider
+ * @see HealthResolver
+ */
+public class ShardResolver {
+ private final Logger log = LoggerFactory.getLogger(ShardResolver.class);
+ private static ShardResolver _shardResolver;
+
+ private String jolokiaClusterPath;
+ private String shardManagerPath;
+ private String shardPathTemplate;
+ private String credentials;
+ private String httpProtocol;
+
+ private static final String VALUE = "value";
+
+ private ShardResolver(Properties properties) {
+ String port = "true".equals(properties.getProperty(PropertyKeys.CONTROLLER_USE_SSL).trim()) ? properties.getProperty(PropertyKeys.CONTROLLER_PORT_SSL).trim() : properties.getProperty(PropertyKeys.CONTROLLER_PORT_HTTP).trim();
+ httpProtocol = "true".equals(properties.getProperty(PropertyKeys.CONTROLLER_USE_SSL).trim()) ? "https://" : "http://";
+ jolokiaClusterPath = ":" + port + properties.getProperty(PropertyKeys.MBEAN_CLUSTER).trim();
+ shardManagerPath = ":" + port + properties.getProperty(PropertyKeys.MBEAN_SHARD_MANAGER).trim();
+ shardPathTemplate = ":" + port + properties.getProperty(PropertyKeys.MBEAN_SHARD_CONFIG).trim();
+ credentials = properties.getProperty(PropertyKeys.CONTROLLER_CREDENTIALS).trim();
+ }
+
+ public static ShardResolver getInstance(Properties properties) {
+ if (_shardResolver == null) {
+ _shardResolver = new ShardResolver(properties);
+ }
+ return _shardResolver;
+ }
+
+ private void getMemberStatus(ClusterActor clusterActor) throws IOException {
+ log.info("getMemberStatus(): Getting member status for {}", clusterActor.getNode());
+ ConnectionResponse response = ConnectionManager.getConnectionResponse(httpProtocol + clusterActor.getNode() + jolokiaClusterPath, ConnectionManager.HttpMethod.GET, null, credentials);
+ try {
+ JSONObject responseJson = new JSONObject(response.content);
+ JSONObject responseValue = responseJson.getJSONObject(VALUE);
+ clusterActor.setUp("Up".equals(responseValue.getString("MemberStatus")));
+ clusterActor.setUnreachable(false);
+ } catch(JSONException e) {
+ log.error("getMemberStatus(): Error parsing response from {}", clusterActor.getNode(), e);
+ clusterActor.setUp(false);
+ clusterActor.setUnreachable(true);
+ }
+ }
+
+ private void getShardStatus(ClusterActor clusterActor) throws IOException {
+ log.info("getShardStatus(): Getting shard status for {}", clusterActor.getNode());
+ ConnectionResponse response = ConnectionManager.getConnectionResponse(httpProtocol + clusterActor.getNode() + shardManagerPath, ConnectionManager.HttpMethod.GET, null, credentials);
+ try {
+ JSONObject responseValue = new JSONObject(response.content).getJSONObject(VALUE);
+ JSONArray shardList = responseValue.getJSONArray("LocalShards");
+
+ String pattern = "-config$";
+ Pattern r = Pattern.compile(pattern);
+ List<String> shards = new ArrayList<>();
+ for(int ndx = 0; ndx < shardList.length(); ndx++) {
+ shards.add(shardList.getString(ndx));
+ }
+ shards.parallelStream().forEach(shard -> {
+ Matcher m = r.matcher(shard);
+ String operationalShardName = m.replaceFirst("-operational");
+ String shardConfigPath = String.format(shardPathTemplate, shard);
+ String shardOperationalPath = String.format(shardPathTemplate, operationalShardName).replace("Config", "Operational");
+ try {
+ extractShardInfo(clusterActor, shard, shardConfigPath);
+ extractShardInfo(clusterActor, operationalShardName, shardOperationalPath);
+ } catch(IOException e) {
+ log.error("getShardStatus(): Error extracting shard info for {}", shard);
+ }
+ });
+ } catch(JSONException e) {
+ log.error("getShardStatus(): Error parsing response from " + clusterActor.getNode(), e);
+ }
+ }
+
+ private void extractShardInfo(ClusterActor clusterActor, String shardName, String shardPath) throws IOException {
+ log.info("extractShardInfo(): Extracting shard info for {}", shardName);
+ String shardPrefix = "";
+// String shardPrefix = clusterActor.getMember() + "-shard-";
+ log.debug("extractShardInfo(): Pulling config info for {} from: {}", shardName, shardPath);
+ ConnectionResponse response = ConnectionManager.getConnectionResponse(httpProtocol + clusterActor.getNode() + shardPath, ConnectionManager.HttpMethod.GET, null, credentials);
+ log.debug("extractShardInfo(): Response: {}", response.content);
+
+ try {
+ JSONObject shardValue = new JSONObject(response.content).getJSONObject(VALUE);
+ clusterActor.setVoting(shardValue.getBoolean("Voting"));
+ if(shardValue.getString("PeerAddresses").length() > 0) {
+ clusterActor.getReplicaShards().add(shardName.replace(shardPrefix, ""));
+ if(shardValue.getString("Leader").startsWith(clusterActor.getMember())) {
+ clusterActor.getShardLeader().add(shardName.replace(shardPrefix, ""));
+ }
+ } else {
+ clusterActor.getNonReplicaShards().add(shardName.replace(shardPrefix, ""));
+ }
+ JSONArray followerInfo = shardValue.getJSONArray("FollowerInfo");
+ for(int followerNdx = 0; followerNdx < followerInfo.length(); followerNdx++) {
+ int commitIndex = shardValue.getInt("CommitIndex");
+ int matchIndex = followerInfo.getJSONObject(followerNdx).getInt("matchIndex");
+ if(commitIndex != -1 && matchIndex != -1) {
+ int commitsBehind = commitIndex - matchIndex;
+ clusterActor.getCommits().put(followerInfo.getJSONObject(followerNdx).getString("id"), commitsBehind);
+ }
+ }
+ } catch(JSONException e) {
+ log.error("extractShardInfo(): Error parsing response from " + clusterActor.getNode(), e);
+ }
+ }
+
+ public void getControllerHealth(Map<String, ClusterActor> memberMap) {
+ memberMap.values().parallelStream().forEach(this::getControllerHealth);
+ }
+
+ // Seen ConcurrentAccess issues, probably related to getting the controller health
+ private synchronized void getControllerHealth(ClusterActor clusterActor) {
+ clusterActor.flush();
+ log.info("getControllerHealth(): Gathering info for {}", clusterActor.getNode());
+ try {
+ // First flush out the old values
+ getMemberStatus(clusterActor);
+ getShardStatus(clusterActor);
+ } catch(IOException e) {
+ log.error("getControllerHealth(): Connection Error", e);
+ clusterActor.setUnreachable(true);
+ clusterActor.setUp(false);
+ }
+ log.info("getControllerHealth(): MemberInfo:\n{}", clusterActor);
+ }
+}
diff --git a/plugins/grToolkit/provider/src/main/java/org/onap/ccsdk/sli/plugins/grtoolkit/resolver/SingleNodeHealthResolver.java b/plugins/grToolkit/provider/src/main/java/org/onap/ccsdk/sli/plugins/grtoolkit/resolver/SingleNodeHealthResolver.java
new file mode 100644
index 000000000..2799df1b0
--- /dev/null
+++ b/plugins/grToolkit/provider/src/main/java/org/onap/ccsdk/sli/plugins/grtoolkit/resolver/SingleNodeHealthResolver.java
@@ -0,0 +1,160 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.grtoolkit.resolver;
+
+import org.onap.ccsdk.sli.core.dblib.DbLibService;
+import org.onap.ccsdk.sli.plugins.grtoolkit.data.AdminHealth;
+import org.onap.ccsdk.sli.plugins.grtoolkit.data.ClusterActor;
+import org.onap.ccsdk.sli.plugins.grtoolkit.data.ClusterHealth;
+import org.onap.ccsdk.sli.plugins.grtoolkit.data.DatabaseHealth;
+import org.onap.ccsdk.sli.plugins.grtoolkit.data.FailoverStatus;
+import org.onap.ccsdk.sli.plugins.grtoolkit.data.Health;
+import org.onap.ccsdk.sli.plugins.grtoolkit.data.SiteHealth;
+
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.plugins.gr.toolkit.rev180926.FailoverInput;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+/**
+ * Implementation of {@code HealthResolver} for a single node controller
+ * architecture.
+ *
+ * @author Anthony Haddox
+ * @see HealthResolver
+ */
+public class SingleNodeHealthResolver extends HealthResolver {
+ private final Logger log = LoggerFactory.getLogger(SingleNodeHealthResolver.class);
+
+ /**
+ * Constructs the health resolver used by the {@code GrToolkitProvider} to
+ * determine the health of the application components.
+ *
+ * @param map a HashMap containing all of the nodes in the akka cluster
+ * @param properties the properties passed ino the provider
+ * @param dbLib a reference to the {@code DbLibService} of the provider
+ * @see HealthResolver
+ * @see org.onap.ccsdk.sli.plugins.grtoolkit.GrToolkitProvider
+ */
+ public SingleNodeHealthResolver(Map<String, ClusterActor> map, Properties properties, DbLibService dbLib) {
+ super(map, properties, dbLib);
+ resolveSites();
+ }
+
+ /**
+ * Implementation of {@code getClusterHealth()}. Uses the
+ * {@code ShardResolver} to gather health information about the controller.
+ * This method assumes the cluster is always healthy since it is a single
+ * node.
+ *
+ * @return an {@code ClusterHealth} object with health of the akka cluster
+ * @see org.onap.ccsdk.sli.plugins.grtoolkit.GrToolkitProvider
+ * @see HealthResolver
+ * @see ClusterHealth
+ * @see ShardResolver
+ */
+ @Override
+ public ClusterHealth getClusterHealth() {
+ log.info("getClusterHealth(): Getting cluster health...");
+ shardResolver.getControllerHealth(memberMap);
+ return new ClusterHealth().withHealth(Health.HEALTHY);
+ }
+
+ /**
+ * Implementation of {@code getSiteHealth()}. Uses the results from
+ * {@code getAdminHealth}, {@code getDatabaseHealth}, and
+ * {@code getClusterHealth} to determine the health of the site. If all
+ * components are healthy, the site is healthy.
+ *
+ * @return a List of {@code SiteHealth} objects with health of the site
+ * @see org.onap.ccsdk.sli.plugins.grtoolkit.GrToolkitProvider
+ * @see HealthResolver
+ * @see SiteHealth
+ * @see ShardResolver
+ */
+ @Override
+ public List<SiteHealth> getSiteHealth() {
+ log.info("getSiteHealth(): Getting site health...");
+ AdminHealth adminHealth = getAdminHealth();
+ DatabaseHealth databaseHealth = getDatabaseHealth();
+ ClusterHealth clusterHealth = getClusterHealth();
+ SiteHealth siteHealth = new SiteHealth()
+ .withAdminHealth(adminHealth)
+ .withDatabaseHealth(databaseHealth)
+ .withClusterHealth(clusterHealth)
+ .withRole("ACTIVE")
+ .withId(getSiteIdentifier());
+ log.info("getSiteHealth(): Admin Health: {}", adminHealth.getHealth().toString());
+ log.info("getSiteHealth(): Database Health: {}", databaseHealth.getHealth().toString());
+ log.info("getSiteHealth(): Cluster Health: {}", clusterHealth.getHealth().toString());
+ if(isHealthy(adminHealth.getHealth()) && isHealthy(databaseHealth.getHealth()) && isHealthy(clusterHealth.getHealth())) {
+ siteHealth.setHealth(Health.HEALTHY);
+ }
+
+ return Collections.singletonList(siteHealth);
+ }
+
+ /**
+ * Implementation of {@code tryFailover()}. No controller-level failover
+ * options are available in a single node architecture, so 400 Bad Request
+ * is returned, and no action is taken.
+ *
+ * @return an {@code SiteHealth} object with health of the site
+ * @see org.onap.ccsdk.sli.plugins.grtoolkit.GrToolkitProvider
+ * @see HealthResolver
+ * @see FailoverStatus
+ * @see FailoverInput
+ */
+ @Override
+ public FailoverStatus tryFailover(FailoverInput input) {
+ log.info("tryFailover(): Failover not supported in the current configuration.");
+ return new FailoverStatus().withStatusCode(400).withMessage("Failover not supported in current configuration.");
+ }
+
+ /**
+ * Implementation of {@code resolveSites()}. Calls
+ * {@code resolveSiteForMember()} to resolve which site a member belongs to.
+ *
+ * @see HealthResolver
+ */
+ @Override
+ public void resolveSites() {
+ log.info("Map contains {} entries", memberMap.size());
+ memberMap.forEach((key, value) -> resolveSiteForMember(value));
+ }
+
+ /**
+ * Resolves which site a member belongs to. Since this is a Single node
+ * architecture, it is defaulted to <i>Site 1</i>.
+ *
+ * @see HealthResolver
+ */
+ private void resolveSiteForMember(ClusterActor actor) {
+ actor.setSite("Site 1");
+ log.info("resolveSiteForMember(): {} belongs to {}", actor.getNode(), actor.getSite());
+ }
+}
diff --git a/plugins/grToolkit/provider/src/main/java/org/onap/ccsdk/sli/plugins/grtoolkit/resolver/SixNodeHealthResolver.java b/plugins/grToolkit/provider/src/main/java/org/onap/ccsdk/sli/plugins/grtoolkit/resolver/SixNodeHealthResolver.java
new file mode 100644
index 000000000..e79262cf3
--- /dev/null
+++ b/plugins/grToolkit/provider/src/main/java/org/onap/ccsdk/sli/plugins/grtoolkit/resolver/SixNodeHealthResolver.java
@@ -0,0 +1,316 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.grtoolkit.resolver;
+
+import org.json.JSONArray;
+import org.json.JSONObject;
+
+import org.onap.ccsdk.sli.core.dblib.DbLibService;
+import org.onap.ccsdk.sli.plugins.grtoolkit.connection.ConnectionManager;
+import org.onap.ccsdk.sli.plugins.grtoolkit.connection.ConnectionResponse;
+import org.onap.ccsdk.sli.plugins.grtoolkit.data.AdminHealth;
+import org.onap.ccsdk.sli.plugins.grtoolkit.data.ClusterActor;
+import org.onap.ccsdk.sli.plugins.grtoolkit.data.ClusterHealth;
+import org.onap.ccsdk.sli.plugins.grtoolkit.data.DatabaseHealth;
+import org.onap.ccsdk.sli.plugins.grtoolkit.data.FailoverStatus;
+import org.onap.ccsdk.sli.plugins.grtoolkit.data.Health;
+import org.onap.ccsdk.sli.plugins.grtoolkit.data.SiteHealth;
+
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.plugins.gr.toolkit.rev180926.FailoverInput;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Properties;
+import java.util.stream.Collectors;
+
+/**
+ * Implementation of {@code HealthResolver} for a six node controller
+ * architecture, where three nodes are located in one data center, and the
+ * other three nodes are located in another. The sites are assumed to be in an
+ * Active/Standby configuration, with the Active site nodes voting and the
+ * Standby site notes non-voting.
+ *
+ * @author Anthony Haddox
+ * @see HealthResolver
+ */
+public class SixNodeHealthResolver extends HealthResolver {
+ private final Logger log = LoggerFactory.getLogger(SixNodeHealthResolver.class);
+
+ /**
+ * Constructs the health resolver used by the {@code GrToolkitProvider} to
+ * determine the health of the application components.
+ *
+ * @param map a HashMap containing all of the nodes in the akka cluster
+ * @param properties the properties passed ino the provider
+ * @param dbLib a reference to the {@code DbLibService} of the provider
+ * @see HealthResolver
+ * @see org.onap.ccsdk.sli.plugins.grtoolkit.GrToolkitProvider
+ */
+ public SixNodeHealthResolver(Map<String, ClusterActor> map, Properties properties, DbLibService dbLib) {
+ super(map, properties, dbLib);
+ resolveSites();
+ }
+
+ /**
+ * Implementation of {@code getClusterHealth()}. Uses the
+ * {@code ShardResolver} to gather health information about the controller.
+ * If 4 of 6 members are healthy, the cluster is deemed healthy.
+ *
+ * @return an {@code ClusterHealth} object with health of the akka cluster
+ * @see org.onap.ccsdk.sli.plugins.grtoolkit.GrToolkitProvider
+ * @see HealthResolver
+ * @see ClusterHealth
+ * @see ShardResolver
+ */
+ @Override
+ public ClusterHealth getClusterHealth() {
+ log.info("getClusterHealth(): Getting cluster health...");
+ shardResolver.getControllerHealth(memberMap);
+ long healthyMembers = memberMap.values().stream().filter(member -> member.isUp() && ! member.isUnreachable()).count();
+ return (healthyMembers > 4) ? new ClusterHealth().withHealth(Health.HEALTHY) : new ClusterHealth().withHealth(Health.FAULTY);
+ }
+
+ /**
+ * Implementation of {@code getSiteHealth()}. Gathers health information on
+ * all of the contollers, then separates the nodes into voting and
+ * non-voting sites. Each site is then checked for its health and the
+ * result is returned as a List.
+ *
+ * @return a List of {@code SiteHealth} objects with health of the site
+ * @see org.onap.ccsdk.sli.plugins.grtoolkit.GrToolkitProvider
+ * @see HealthResolver
+ * @see SiteHealth
+ * @see ShardResolver
+ */
+ @Override
+ public List<SiteHealth> getSiteHealth() {
+ log.info("getSiteHealth(): Getting site health...");
+
+ // Get cluster health to populate memberMap with necessary values
+ getClusterHealth();
+ List<ClusterActor> votingActors = memberMap.values().stream().filter(ClusterActor::isVoting).collect(Collectors.toList());
+ List<ClusterActor> nonVotingActors = memberMap.values().stream().filter(member -> !member.isVoting()).collect(Collectors.toList());
+
+ SiteHealth votingSiteHealth = getSiteHealth(votingActors).withRole("ACTIVE");
+ SiteHealth nonVotingSiteHealth = getSiteHealth(nonVotingActors).withRole("STANDBY");
+ return Arrays.asList(votingSiteHealth, nonVotingSiteHealth);
+ }
+
+ /**
+ * Gathers the site identifier, admin health, and database health of a
+ * site.
+ *
+ * @return a {@code SiteHealth} object with health of the site
+ * @see org.onap.ccsdk.sli.plugins.grtoolkit.GrToolkitProvider
+ * @see ClusterActor
+ * @see SiteHealth
+ * @see ConnectionManager
+ */
+ public SiteHealth getSiteHealth(List<ClusterActor> actorList) {
+ AdminHealth adminHealth = null;
+ DatabaseHealth databaseHealth = null;
+ String siteId = null;
+ int healthyMembers = 0;
+
+ for(ClusterActor actor : actorList) {
+ if(actor.isUp() && !actor.isUnreachable()) {
+ healthyMembers++;
+ }
+ if(siteId == null) {
+ try {
+ String content = ConnectionManager.getConnectionResponse(httpProtocol + actor.getNode() + ":" + controllerPort + "/restconf/operations/gr-toolkit:site-identifier", ConnectionManager.HttpMethod.POST, null, credentials).content;
+ siteId = new JSONObject(content).getJSONObject(OUTPUT).getString("id");
+ } catch(IOException e) {
+ log.error("getSiteHealth(): Error getting site identifier from {}", actor.getNode());
+ log.error("getSiteHealth(): IOException", e);
+ }
+ }
+ if(adminHealth == null) {
+ try {
+ boolean isAdminHealthy = isRemoteComponentHealthy(httpProtocol + actor.getNode() + ":" + controllerPort + "/restconf/operations/gr-toolkit:admin-health");
+ if(isAdminHealthy) {
+ adminHealth = new AdminHealth(Health.HEALTHY, 200);
+ }
+ } catch(IOException e) {
+ log.error("getSiteHealth(): Error getting admin health from {}", actor.getNode());
+ log.error("getSiteHealth(): IOException", e);
+ }
+ }
+ if(databaseHealth == null) {
+ try {
+ boolean isDatabaseHealthy = isRemoteComponentHealthy(httpProtocol + actor.getNode() + ":" + controllerPort + "/restconf/operations/gr-toolkit:database-health");
+ if(isDatabaseHealthy) {
+ databaseHealth = new DatabaseHealth(Health.HEALTHY);
+ }
+ } catch(IOException e) {
+ log.error("getSiteHealth(): Error getting database health from {}", actor.getNode());
+ log.error("getSiteHealth(): IOException", e);
+ }
+ }
+ }
+
+ if(siteId == null) {
+ siteId = "UNKNOWN SITE";
+ }
+ if(adminHealth == null) {
+ adminHealth = new AdminHealth(Health.FAULTY, 500);
+ }
+ if(databaseHealth == null) {
+ databaseHealth = new DatabaseHealth(Health.FAULTY);
+ }
+ SiteHealth health = new SiteHealth()
+ .withAdminHealth(adminHealth)
+ .withDatabaseHealth(databaseHealth)
+ .withId(siteId);
+ if(isHealthy(adminHealth.getHealth()) && isHealthy(databaseHealth.getHealth()) && healthyMembers > 1) {
+ health.setHealth(Health.HEALTHY);
+ }
+
+ return health;
+ }
+
+ /**
+ * Implementation of {@code tryFailover()}. Performs a preliminary call to
+ * {@code getClusterHealth} to populate information about the cluster. If
+ * no voting members can be found, the method terminates immediately. The
+ * nodes are separated into voting and non-voting sites, and a driving
+ * operator is selected from the non-voting nodes to perform requests
+ * against. A payload to swap voting between sites is sent to the operator
+ * to perform a controller-level failover.
+ *
+ * @return an {@code SiteHealth} object with health of the site
+ * @see org.onap.ccsdk.sli.plugins.grtoolkit.GrToolkitProvider
+ * @see HealthResolver
+ * @see FailoverStatus
+ * @see FailoverInput
+ */
+ @Override
+ public FailoverStatus tryFailover(FailoverInput input) {
+ // Get Cluster Health to populate the memberMap with the necessary values
+ log.info("tryFailover(): Performing preliminary health check...");
+ getClusterHealth();
+ FailoverStatus status = new FailoverStatus();
+ ConnectionResponse votingResponse = null;
+ List<ClusterActor> votingActors = memberMap.values().stream().filter(ClusterActor::isVoting).collect(Collectors.toList());
+ List<ClusterActor> nonVotingActors = memberMap.values().stream().filter(member -> !member.isVoting()).collect(Collectors.toList());
+
+ if(nonVotingActors.size() == 0) {
+ status.setStatusCode(500);
+ status.setMessage("No nonvoting members found. Cannot perform voting switch.");
+ return status;
+ }
+
+ ClusterActor operator;
+ try {
+ operator = nonVotingActors.stream().filter(this::isControllerHealthy).findFirst().get();
+ } catch(NoSuchElementException e) {
+ log.error("tryFailover(): Could not find any healthy members.", e);
+ status.setStatusCode(500);
+ status.setMessage("Could not find any healthy members.");
+ return status;
+ }
+
+ // Assuming two 3 node sites, 3 voting and 3 non voting
+ if(votingActors.size() < 3 || nonVotingActors.size() < 3) {
+ log.warn("tryFailover(): Sites do not contain an equal amount of voting and nonvoting members: Voting: {} | NonVoting: {}", votingActors.size(), nonVotingActors.size());
+ }
+ log.info("tryFailover(): Swapping voting...");
+ try {
+ JSONObject votingInput = new JSONObject();
+ JSONObject inputBlock = new JSONObject();
+ JSONArray votingStateArray = new JSONArray();
+ JSONObject memberVotingState;
+ for(ClusterActor actor : votingActors) {
+ memberVotingState = new JSONObject();
+ memberVotingState.put("member-name", actor.getMember());
+ memberVotingState.put("voting", false);
+ votingStateArray.put(memberVotingState);
+ }
+ for(ClusterActor actor : nonVotingActors) {
+ memberVotingState = new JSONObject();
+ memberVotingState.put("member-name", actor.getMember());
+ memberVotingState.put("voting", true);
+ votingStateArray.put(memberVotingState);
+ }
+ inputBlock.put("member-voting-state", votingStateArray);
+ votingInput.put("input", inputBlock);
+ log.debug("tryFailover(): {}", votingInput);
+ // Change voting all shards
+ votingResponse = ConnectionManager.getConnectionResponse(httpProtocol + operator.getNode() + ":" + controllerPort + "/restconf/operations/cluster-admin:change-member-voting-states-for-all-shards", ConnectionManager.HttpMethod.POST, votingInput.toString(), credentials);
+ } catch(IOException e) {
+ log.error("tryFailover(): Failure changing voting", e);
+ }
+ if(votingResponse != null) {
+ if(votingResponse.statusCode != 200) {
+ status.setStatusCode(votingResponse.statusCode);
+ status.setMessage("Failed to swap voting.");
+ } else {
+ status.setStatusCode(200);
+ status.setMessage("Failover complete.");
+ }
+ } else {
+ status.setStatusCode(500);
+ status.setMessage("Failed to swap voting.");
+ }
+
+ return status;
+ }
+
+ /**
+ * Implementation of {@code resolveSites()}. Calls
+ * {@code resolveSiteForMember()} to resolve which site a member belongs to.
+ *
+ * @see HealthResolver
+ */
+ @Override
+ public void resolveSites() {
+ log.info("Map contains {} entries", memberMap.size());
+ memberMap.forEach((key, value) -> resolveSiteForMember(value));
+ }
+
+ /**
+ * Resolves which site a member belongs to. Members 1-3 are assumed to be
+ * <i>Site 1</i> while members 4-6 are assumed to be <i>Site 2</i>.
+ *
+ * @see HealthResolver
+ */
+ private void resolveSiteForMember(ClusterActor actor) {
+ try {
+ int memberNumber = Integer.parseInt(actor.getMember().split("-")[1]);
+ if(memberNumber < 4) {
+ actor.setSite("Site 1");
+ } else {
+ actor.setSite("Site 2");
+ }
+ log.info("resolveSiteForMember(): {} belongs to {}", actor.getNode(), actor.getSite());
+ } catch (NumberFormatException e) {
+ log.error("resolveSiteForMember(): Could not parse member number for {}. Defaulting to Site 1.", actor.getNode());
+ actor.setSite("resolveSiteForMember(): Site 1");
+ }
+ }
+} \ No newline at end of file
diff --git a/plugins/grToolkit/provider/src/main/java/org/onap/ccsdk/sli/plugins/grtoolkit/resolver/ThreeNodeHealthResolver.java b/plugins/grToolkit/provider/src/main/java/org/onap/ccsdk/sli/plugins/grtoolkit/resolver/ThreeNodeHealthResolver.java
new file mode 100644
index 000000000..2180b2bf8
--- /dev/null
+++ b/plugins/grToolkit/provider/src/main/java/org/onap/ccsdk/sli/plugins/grtoolkit/resolver/ThreeNodeHealthResolver.java
@@ -0,0 +1,162 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.grtoolkit.resolver;
+
+import org.onap.ccsdk.sli.core.dblib.DbLibService;
+import org.onap.ccsdk.sli.plugins.grtoolkit.data.AdminHealth;
+import org.onap.ccsdk.sli.plugins.grtoolkit.data.ClusterActor;
+import org.onap.ccsdk.sli.plugins.grtoolkit.data.ClusterHealth;
+import org.onap.ccsdk.sli.plugins.grtoolkit.data.DatabaseHealth;
+import org.onap.ccsdk.sli.plugins.grtoolkit.data.FailoverStatus;
+import org.onap.ccsdk.sli.plugins.grtoolkit.data.Health;
+import org.onap.ccsdk.sli.plugins.grtoolkit.data.SiteHealth;
+
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.plugins.gr.toolkit.rev180926.FailoverInput;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+/**
+ * Implementation of {@code HealthResolver} for a three node controller
+ * architecture, where all nodes are located within the same data center or
+ * geographic region. The nodes are assumed to be in an Active/Active/Active
+ * voting configuration.
+ *
+ * @author Anthony Haddox
+ * @see HealthResolver
+ */
+public class ThreeNodeHealthResolver extends HealthResolver {
+ private final Logger log = LoggerFactory.getLogger(ThreeNodeHealthResolver.class);
+
+ /**
+ * Constructs the health resolver used by the {@code GrToolkitProvider} to
+ * determine the health of the application components.
+ *
+ * @param map a HashMap containing all of the nodes in the akka cluster
+ * @param properties the properties passed ino the provider
+ * @param dbLib a reference to the {@code DbLibService} of the provider
+ * @see HealthResolver
+ * @see org.onap.ccsdk.sli.plugins.grtoolkit.GrToolkitProvider
+ */
+ public ThreeNodeHealthResolver(Map<String, ClusterActor> map, Properties properties, DbLibService dbLib) {
+ super(map, properties, dbLib);
+ resolveSites();
+ }
+
+ /**
+ * Implementation of {@code getClusterHealth()}. Uses the
+ * {@code ShardResolver} to gather health information about the controller.
+ * If 2 of 3 members are healthy, the cluster is deemed healthy.
+ *
+ * @return an {@code ClusterHealth} object with health of the akka cluster
+ * @see org.onap.ccsdk.sli.plugins.grtoolkit.GrToolkitProvider
+ * @see HealthResolver
+ * @see ClusterHealth
+ * @see ShardResolver
+ */
+ @Override
+ public ClusterHealth getClusterHealth() {
+ log.info("getClusterHealth(): Getting cluster health...");
+ shardResolver.getControllerHealth(memberMap);
+ long healthyMembers = memberMap.values().stream().filter(member -> member.isUp() && ! member.isUnreachable()).count();
+ return (healthyMembers > 1) ? new ClusterHealth().withHealth(Health.HEALTHY) : new ClusterHealth().withHealth(Health.FAULTY);
+ }
+
+ /**
+ * Implementation of {@code getSiteHealth()}. Uses the results from
+ * {@code getAdminHealth}, {@code getDatabaseHealth}, and
+ * {@code getClusterHealth} to determine the health of the site. If all
+ * components are healthy, the site is healthy.
+ *
+ * @return a List of {@code SiteHealth} objects with health of the site
+ * @see org.onap.ccsdk.sli.plugins.grtoolkit.GrToolkitProvider
+ * @see HealthResolver
+ * @see SiteHealth
+ * @see ShardResolver
+ */
+ @Override
+ public List<SiteHealth> getSiteHealth() {
+ log.info("getSiteHealth(): Getting site health...");
+ AdminHealth adminHealth = getAdminHealth();
+ DatabaseHealth databaseHealth = getDatabaseHealth();
+ ClusterHealth clusterHealth = getClusterHealth();
+ SiteHealth siteHealth = new SiteHealth()
+ .withAdminHealth(adminHealth)
+ .withDatabaseHealth(databaseHealth)
+ .withClusterHealth(clusterHealth)
+ .withRole("ACTIVE")
+ .withId(getSiteIdentifier());
+ log.info("getSiteHealth(): Admin Health: {}", adminHealth.getHealth().toString());
+ log.info("getSiteHealth(): Database Health: {}", databaseHealth.getHealth().toString());
+ log.info("getSiteHealth(): Cluster Health: {}", clusterHealth.getHealth().toString());
+ if(isHealthy(adminHealth.getHealth()) && isHealthy(databaseHealth.getHealth()) && isHealthy(clusterHealth.getHealth())) {
+ siteHealth.setHealth(Health.HEALTHY);
+ }
+
+ return Collections.singletonList(siteHealth);
+ }
+
+ /**
+ * Implementation of {@code tryFailover()}. No controller-level failover
+ * options are available in a three node architecture, so 400 Bad Request
+ * is returned, and no action is taken.
+ *
+ * @return an {@code SiteHealth} object with health of the site
+ * @see org.onap.ccsdk.sli.plugins.grtoolkit.GrToolkitProvider
+ * @see HealthResolver
+ * @see FailoverStatus
+ * @see FailoverInput
+ */
+ @Override
+ public FailoverStatus tryFailover(FailoverInput input) {
+ log.info("tryFailover(): Failover not supported in the current configuration.");
+ return new FailoverStatus().withStatusCode(400).withMessage("Failover not supported in current configuration.");
+ }
+
+ /**
+ * Implementation of {@code resolveSites()}. Calls
+ * {@code resolveSiteForMember()} to resolve which site a member belongs to.
+ *
+ * @see HealthResolver
+ */
+ @Override
+ public void resolveSites() {
+ log.info("Map contains {} entries", memberMap.size());
+ memberMap.forEach((key, value) -> resolveSiteForMember(value));
+ }
+
+ /**
+ * Resolves which site a member belongs to. Since this is a three node
+ * co-located architecture, it is defaulted to <i>Site 1</i>.
+ *
+ * @see HealthResolver
+ */
+ private void resolveSiteForMember(ClusterActor actor) {
+ actor.setSite("Site 1");
+ log.info("resolveSiteForMember(): {} belongs to {}", actor.getNode(), actor.getSite());
+ }
+}
diff --git a/plugins/grToolkit/provider/src/main/resources/gr-toolkit.properties b/plugins/grToolkit/provider/src/main/resources/gr-toolkit.properties
new file mode 100755
index 000000000..e3463df08
--- /dev/null
+++ b/plugins/grToolkit/provider/src/main/resources/gr-toolkit.properties
@@ -0,0 +1,35 @@
+# ============LICENSE_START=======================================================
+# openECOMP : SDN-C
+# ================================================================================
+# Copyright (C) 2019 AT&T Intellectual Property. All rights
+# reserved.
+# ================================================================================
+# 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.
+# ============LICENSE_END=========================================================
+
+resolver=org.onap.ccsdk.sli.plugins.grtoolkit.resolver.SingleNodeHealthResolver
+akka.conf.location=/opt/opendaylight/current/controller/configuration/initial/akka.conf
+adm.useSsl=true
+adm.fqdn=
+adm.healthcheck=/healthcheck
+adm.port.http=8181
+adm.port.ssl=8443
+controller.credentials=admin:admin
+controller.useSsl=true
+controller.port.http=8181
+controller.port.ssl=8443
+controller.port.akka=2550
+mbean.cluster=/jolokia/read/akka:type=Cluster
+mbean.shardManager=/jolokia/read/org.opendaylight.controller:Category=ShardManager,name=shard-manager-config,type=DistributedConfigDatastore
+mbean.shard.config=/jolokia/read/org.opendaylight.controller:Category=Shards,name=%s,type=DistributedConfigDatastore
+site.identifier=UniqueSiteNameHere
diff --git a/plugins/grToolkit/provider/src/main/resources/org/opendaylight/blueprint/GrToolkit.xml b/plugins/grToolkit/provider/src/main/resources/org/opendaylight/blueprint/GrToolkit.xml
new file mode 100644
index 000000000..5a4492c56
--- /dev/null
+++ b/plugins/grToolkit/provider/src/main/resources/org/opendaylight/blueprint/GrToolkit.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+ xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0"
+ odl:use-default-for-reference-types="true">
+
+ <reference id="dataBroker"
+ interface="org.opendaylight.controller.md.sal.binding.api.DataBroker"
+ odl:type="default" />
+
+ <reference id="notificationService"
+ interface="org.opendaylight.controller.md.sal.binding.api.NotificationPublishService"
+ odl:type="default" />
+
+ <reference id="rpcRegistry"
+ interface="org.opendaylight.controller.sal.binding.api.RpcProviderRegistry"
+ odl:type="default" />
+
+ <reference id="dbLib"
+ interface="org.onap.ccsdk.sli.core.dblib.DbLibService" />
+
+ <reference id="configDatastore" interface="org.opendaylight.controller.cluster.datastore.DistributedDataStoreInterface"
+ odl:type="distributed-config"/>
+
+ <bean id="provider" class="org.onap.ccsdk.sli.plugins.grtoolkit.GrToolkitProvider">
+ <argument ref="dataBroker" />
+ <argument ref="notificationService" />
+ <argument ref="rpcRegistry" />
+ <argument ref="dbLib" />
+ <argument ref="configDatastore" />
+ </bean>
+
+ <odl:rpc-implementation ref="provider"/>
+</blueprint>
diff --git a/plugins/grToolkit/provider/src/test/java/org/onap/ccsdk/sli/plugins/grtoolkit/GrToolkitProviderTest.java b/plugins/grToolkit/provider/src/test/java/org/onap/ccsdk/sli/plugins/grtoolkit/GrToolkitProviderTest.java
new file mode 100644
index 000000000..edd6d1b8d
--- /dev/null
+++ b/plugins/grToolkit/provider/src/test/java/org/onap/ccsdk/sli/plugins/grtoolkit/GrToolkitProviderTest.java
@@ -0,0 +1,352 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2018 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.grtoolkit;
+import com.github.tomakehurst.wiremock.junit.WireMockRule;
+
+import com.google.common.util.concurrent.ListenableFuture;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.contrib.java.lang.system.EnvironmentVariables;
+
+import org.onap.ccsdk.sli.core.dblib.DBLibConnection;
+import org.onap.ccsdk.sli.core.dblib.DbLibService;
+import org.onap.ccsdk.sli.plugins.grtoolkit.data.ClusterActor;
+
+import org.opendaylight.controller.cluster.access.concepts.MemberName;
+import org.opendaylight.controller.cluster.datastore.DistributedDataStoreInterface;
+import org.opendaylight.controller.cluster.datastore.utils.ActorUtils;
+import org.opendaylight.controller.md.sal.binding.api.DataBroker;
+import org.opendaylight.controller.md.sal.binding.api.NotificationPublishService;
+import org.opendaylight.controller.sal.binding.api.RpcProviderRegistry;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.plugins.gr.toolkit.rev180926.AdminHealthOutput;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.plugins.gr.toolkit.rev180926.ClusterHealthOutput;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.plugins.gr.toolkit.rev180926.DatabaseHealthOutput;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.plugins.gr.toolkit.rev180926.FailoverOutput;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.plugins.gr.toolkit.rev180926.HaltAkkaTrafficInputBuilder;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.plugins.gr.toolkit.rev180926.HaltAkkaTrafficOutput;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.plugins.gr.toolkit.rev180926.ResumeAkkaTrafficInputBuilder;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.plugins.gr.toolkit.rev180926.ResumeAkkaTrafficOutput;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.plugins.gr.toolkit.rev180926.SiteHealthOutput;
+import org.opendaylight.yang.gen.v1.org.onap.ccsdk.sli.plugins.gr.toolkit.rev180926.SiteIdentifierOutput;
+import org.opendaylight.yangtools.yang.common.RpcResult;
+
+import java.io.IOException;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Properties;
+import java.util.concurrent.ExecutionException;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
+import static com.github.tomakehurst.wiremock.client.WireMock.get;
+import static com.github.tomakehurst.wiremock.client.WireMock.stubFor;
+import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+public class GrToolkitProviderTest {
+ GrToolkitProvider provider;
+ GrToolkitProvider providerSpy;
+ DataBroker dataBroker;
+ NotificationPublishService notificationProviderService;
+ RpcProviderRegistry rpcProviderRegistry;
+ DistributedDataStoreInterface configDatastore;
+ DbLibService dbLibService;
+ DBLibConnection connection;
+ Properties properties;
+
+ @Rule
+ public final EnvironmentVariables environmentVariables = new EnvironmentVariables();
+ @Rule
+ public WireMockRule wireMockRule = new WireMockRule(9999);
+
+ @Before
+ public void setup() {
+ environmentVariables.set("SDNC_CONFIG_DIR","src/test/resources");
+ dataBroker = mock(DataBroker.class);
+ notificationProviderService = mock(NotificationPublishService.class);
+ rpcProviderRegistry = mock(RpcProviderRegistry.class);
+ configDatastore = mock(DistributedDataStoreInterface.class);
+ dbLibService = mock(DbLibService.class);
+ connection = mock(DBLibConnection.class);
+
+ ActorUtils actorContext = mock(ActorUtils.class);
+ MemberName memberName = MemberName.forName("Test");
+
+ when(actorContext.getCurrentMemberName()).thenReturn(memberName);
+ when(configDatastore.getActorUtils()).thenReturn(actorContext);
+
+ try {
+ when(connection.isReadOnly()).thenReturn(false);
+ when(connection.isClosed()).thenReturn(false);
+ when(dbLibService.isActive()).thenReturn(true);
+ when(dbLibService.getConnection()).thenReturn(connection);
+ } catch(SQLException e) {
+ fail();
+ }
+
+ provider = new GrToolkitProvider(dataBroker, notificationProviderService,
+ rpcProviderRegistry, configDatastore, dbLibService);
+ providerSpy = spy(provider);
+ stubController();
+ }
+
+ @Test
+ public void closeTest() {
+ try {
+ provider.close();
+ } catch(Exception e) {
+ // Exception expected
+ }
+ }
+
+ @Test
+ public void onDataTreeChangedTest() {
+ provider.onDataTreeChanged(new ArrayList());
+ // onDataTreeChanged is an empty stub
+ }
+
+ private void stubController() {
+ String clusterBody = null;
+ String shardManagerBody = null;
+ String shardDefaultBody = null;
+ String shardOperationalBody = null;
+ try(Stream<String> stream = Files.lines(Paths.get("src/test/resources/three/cluster.json"))) {
+ clusterBody = stream.collect(Collectors.joining());
+ } catch(IOException e) {
+ fail();
+ }
+ try(Stream<String> stream = Files.lines(Paths.get("src/test/resources/three/shard-manager.json"))) {
+ shardManagerBody = stream.collect(Collectors.joining());
+ } catch(IOException e) {
+ fail();
+ }
+ try(Stream<String> stream = Files.lines(Paths.get("src/test/resources/three/default-config.json"))) {
+ shardDefaultBody = stream.collect(Collectors.joining());
+ } catch(IOException e) {
+ fail();
+ }
+ try(Stream<String> stream = Files.lines(Paths.get("src/test/resources/three/default-operational.json"))) {
+ shardOperationalBody = stream.collect(Collectors.joining());
+ } catch(IOException e) {
+ fail();
+ }
+
+ if(clusterBody == null || shardManagerBody == null || shardDefaultBody == null || shardOperationalBody == null) {
+ fail();
+ }
+ stubFor(get(urlEqualTo("/adm/healthcheck")).willReturn(aResponse().withStatus(200)));
+ stubFor(get(urlEqualTo("/jolokia/read/akka:type=Cluster")).willReturn(aResponse().withStatus(200).withBody(clusterBody)));
+ stubFor(get(urlEqualTo("/jolokia/read/org.opendaylight.controller:Category=ShardManager,name=shard-manager-config,type=DistributedConfigDatastore")).inScenario("testing").willReturn(aResponse().withStatus(200).withBody(shardManagerBody)).willSetStateTo("next"));
+ stubFor(get(urlEqualTo("/jolokia/read/org.opendaylight.controller:Category=Shards,name=member-1-shard-default-config,type=DistributedConfigDatastore")).inScenario("testing").willReturn(aResponse().withStatus(200).withBody(shardDefaultBody)).willSetStateTo("next"));
+ stubFor(get(urlEqualTo("/jolokia/read/org.opendaylight.controller:Category=Shards,name=member-1-shard-default-operational,type=DistributedOperationalDatastore")).willReturn(aResponse().withStatus(200).withBody(shardOperationalBody)));
+ }
+
+ @Test
+ public void clusterHealthTest() {
+ ListenableFuture<RpcResult<ClusterHealthOutput>> result = provider.clusterHealth(null);
+ try {
+ assertEquals("0", result.get().getResult().getStatus());
+ } catch(InterruptedException | ExecutionException e) {
+ fail();
+ }
+ }
+
+ @Test
+ public void siteHealthTest() {
+ ListenableFuture<RpcResult<SiteHealthOutput>> result = provider.siteHealth(null);
+ try {
+ assertEquals("200", result.get().getResult().getStatus());
+ } catch(InterruptedException | ExecutionException e) {
+ fail();
+ }
+ }
+
+ @Test
+ public void databaseHealthTest() {
+ ListenableFuture<RpcResult<DatabaseHealthOutput>> result = provider.databaseHealth(null);
+ try {
+ assertEquals("200", result.get().getResult().getStatus());
+ } catch(InterruptedException | ExecutionException e) {
+ fail();
+ }
+ }
+
+ @Test
+ public void databaseHealthWhenROTest() {
+ try {
+ when(connection.isReadOnly()).thenReturn(true);
+ } catch(SQLException e) {
+ fail();
+ }
+ ListenableFuture<RpcResult<DatabaseHealthOutput>> result = provider.databaseHealth(null);
+ try {
+ assertEquals("500", result.get().getResult().getStatus());
+ } catch(InterruptedException | ExecutionException e) {
+ fail();
+ }
+ }
+
+ @Test
+ public void databaseHealthWhenExceptionTest() {
+ try {
+ when(connection.isReadOnly()).thenThrow(new SQLException());
+ } catch(SQLException e) {
+ //expected
+ }
+ ListenableFuture<RpcResult<DatabaseHealthOutput>> result = provider.databaseHealth(null);
+ try {
+ assertEquals("500", result.get().getResult().getStatus());
+ } catch(InterruptedException | ExecutionException e) {
+ fail();
+ }
+ }
+
+ @Test
+ public void adminHealthTest() {
+ ListenableFuture<RpcResult<AdminHealthOutput>> result = provider.adminHealth(null);
+ try {
+ assertEquals("200", result.get().getResult().getStatus());
+ } catch(InterruptedException | ExecutionException e) {
+ fail();
+ }
+ }
+
+ @Test
+ public void siteIdentifierTest() {
+ ListenableFuture<RpcResult<SiteIdentifierOutput>> result = provider.siteIdentifier(null);
+ try {
+ assertEquals("200", result.get().getResult().getStatus());
+ } catch(InterruptedException | ExecutionException e) {
+ fail();
+ }
+ }
+
+ @Test
+ public void failoverTest() {
+ ListenableFuture<RpcResult<FailoverOutput>> result = provider.failover(null);
+ try {
+ assertEquals("400", result.get().getResult().getStatus());
+ } catch(InterruptedException | ExecutionException e) {
+ fail();
+ }
+ }
+
+ @Test
+ public void haltTrafficTest() {
+ HaltAkkaTrafficInputBuilder builder = new HaltAkkaTrafficInputBuilder();
+ builder.setNodeInfo(new ArrayList<>());
+ ListenableFuture<RpcResult<HaltAkkaTrafficOutput>> result = provider.haltAkkaTraffic(builder.build());
+ try {
+ assertEquals("200", result.get().getResult().getStatus());
+ } catch(InterruptedException | ExecutionException e) {
+ fail();
+ }
+ }
+
+ @Test
+ public void resumeTrafficTest() {
+ ResumeAkkaTrafficInputBuilder builder = new ResumeAkkaTrafficInputBuilder();
+ builder.setNodeInfo(new ArrayList<>());
+ ListenableFuture<RpcResult<ResumeAkkaTrafficOutput>> result = provider.resumeAkkaTraffic(builder.build());
+ try {
+ assertEquals("200", result.get().getResult().getStatus());
+ } catch(InterruptedException | ExecutionException e) {
+ fail();
+ }
+ }
+
+ @Test
+ public void executeCommandTest() {
+ try {
+ Method method = provider.getClass().getDeclaredMethod("executeCommand", String.class);
+ method.setAccessible(true);
+ method.invoke(provider, "ls");
+ } catch(NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
+ fail();
+ }
+ }
+
+ @Test
+ public void isolateSiteFromClusterTest() {
+ try {
+ ClusterActor actor = new ClusterActor();
+ actor.setNode("some-node");
+ actor.setAkkaPort("2550");
+ ArrayList<ClusterActor> activeList = new ArrayList<>();
+ activeList.add(actor);
+ ArrayList<ClusterActor> standbyList = new ArrayList<>();
+ standbyList.add(actor);
+ Method method = provider.getClass().getDeclaredMethod("isolateSiteFromCluster", ArrayList.class, ArrayList.class, String.class);
+ method.setAccessible(true);
+ method.invoke(provider, activeList, standbyList, "80");
+ } catch(NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
+ fail();
+ }
+ }
+
+ @Test
+ public void downUnreachableNodesTest() {
+ try {
+ ClusterActor actor = new ClusterActor();
+ actor.setNode("some-node");
+ actor.setAkkaPort("2550");
+ ArrayList<ClusterActor> activeList = new ArrayList<>();
+ activeList.add(actor);
+ ArrayList<ClusterActor> standbyList = new ArrayList<>();
+ standbyList.add(actor);
+ Method method = provider.getClass().getDeclaredMethod("downUnreachableNodes", ArrayList.class, ArrayList.class, String.class);
+ method.setAccessible(true);
+ method.invoke(provider, activeList, standbyList, "80");
+ } catch(NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
+ fail();
+ }
+ }
+
+ @Test
+ public void backupMdSalTest() {
+ try {
+ ClusterActor actor = new ClusterActor();
+ actor.setNode("some-Node");
+ actor.setAkkaPort("2550");
+ ArrayList<ClusterActor> activeList = new ArrayList<>();
+ activeList.add(actor);
+ Method method = provider.getClass().getDeclaredMethod("backupMdSal", ArrayList.class, String.class);
+ method.setAccessible(true);
+ method.invoke(provider, activeList, "80");
+ } catch(NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
+ fail();
+ }
+ }
+}
diff --git a/plugins/grToolkit/provider/src/test/java/org/onap/ccsdk/sli/plugins/grtoolkit/connection/ConnectionManagerTest.java b/plugins/grToolkit/provider/src/test/java/org/onap/ccsdk/sli/plugins/grtoolkit/connection/ConnectionManagerTest.java
new file mode 100644
index 000000000..f749688d9
--- /dev/null
+++ b/plugins/grToolkit/provider/src/test/java/org/onap/ccsdk/sli/plugins/grtoolkit/connection/ConnectionManagerTest.java
@@ -0,0 +1,65 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.grtoolkit.connection;
+
+import com.github.tomakehurst.wiremock.junit.WireMockRule;
+
+import org.junit.Rule;
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+import static com.github.tomakehurst.wiremock.client.WireMock.*;
+
+public class ConnectionManagerTest {
+ @Rule
+ public WireMockRule wireMockRule = new WireMockRule(9999);
+
+ @Test
+ public void getConnectionResponseWithInput() throws Exception {
+ stubFor(post(urlEqualTo("/post"))
+ .willReturn(aResponse().withStatus(200)));
+ ConnectionResponse response = ConnectionManager.getConnectionResponse("http://localhost:9999/post", ConnectionManager.HttpMethod.POST, "", "creds:creds");
+ assertNotNull(response);
+ assertEquals(200, response.statusCode);
+ }
+
+ @Test
+ public void getConnectionResponseWithCredentials() throws Exception {
+ stubFor(post(urlEqualTo("/post"))
+ .willReturn(aResponse().withStatus(200)));
+ ConnectionResponse response = ConnectionManager.getConnectionResponse("http://localhost:9999/post", ConnectionManager.HttpMethod.POST, "", "creds:creds");
+ assertNotNull(response);
+ assertEquals(200, response.statusCode);
+ }
+
+ @Test
+ public void getConnectionResponse() throws Exception {
+ stubFor(get(urlEqualTo("/get"))
+ .willReturn(aResponse().withStatus(200)
+ .withBody("Multi\nLine\nResponse")));
+ ConnectionResponse response = ConnectionManager.getConnectionResponse("http://localhost:9999/get", ConnectionManager.HttpMethod.GET, null, null);
+ assertNotNull(response);
+ assertEquals(200, response.statusCode);
+ assertEquals("MultiLineResponse", response.content);
+ }
+} \ No newline at end of file
diff --git a/plugins/grToolkit/provider/src/test/java/org/onap/ccsdk/sli/plugins/grtoolkit/connection/ConnectionResponseTest.java b/plugins/grToolkit/provider/src/test/java/org/onap/ccsdk/sli/plugins/grtoolkit/connection/ConnectionResponseTest.java
new file mode 100644
index 000000000..a9f0edc30
--- /dev/null
+++ b/plugins/grToolkit/provider/src/test/java/org/onap/ccsdk/sli/plugins/grtoolkit/connection/ConnectionResponseTest.java
@@ -0,0 +1,42 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.grtoolkit.connection;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+public class ConnectionResponseTest {
+ @Test
+ public void constructorTest() {
+ ConnectionResponse response = new ConnectionResponse();
+ assertNotNull(response);
+ assertEquals(0, response.statusCode);
+ assertNull(response.content);
+ assertTrue(response.toString().length() > 0);
+ }
+ @Test
+ public void withStatusCode() {
+ ConnectionResponse response = new ConnectionResponse().withStatusCode(123);
+ assertEquals(123, response.statusCode);
+ }
+} \ No newline at end of file
diff --git a/plugins/grToolkit/provider/src/test/java/org/onap/ccsdk/sli/plugins/grtoolkit/data/AdminHealthTest.java b/plugins/grToolkit/provider/src/test/java/org/onap/ccsdk/sli/plugins/grtoolkit/data/AdminHealthTest.java
new file mode 100644
index 000000000..fa56a4d49
--- /dev/null
+++ b/plugins/grToolkit/provider/src/test/java/org/onap/ccsdk/sli/plugins/grtoolkit/data/AdminHealthTest.java
@@ -0,0 +1,59 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.grtoolkit.data;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+public class AdminHealthTest {
+ @Test
+ public void constructorTest() {
+ AdminHealth health = new AdminHealth(Health.HEALTHY);
+ assertEquals(Health.HEALTHY, health.getHealth());
+ }
+
+ @Test
+ public void constructor2Test() {
+ AdminHealth health = new AdminHealth(Health.FAULTY, 500);
+ assertEquals(Health.FAULTY, health.getHealth());
+ assertEquals(500, health.getStatusCode());
+ }
+
+ @Test
+ public void setHealth() {
+ AdminHealth health = new AdminHealth(Health.HEALTHY, 201);
+ assertEquals(Health.HEALTHY, health.getHealth());
+ assertEquals(201, health.getStatusCode());
+ health.setHealth(Health.FAULTY);
+ assertEquals(Health.FAULTY, health.getHealth());
+ }
+
+ @Test
+ public void setStatusCode() {
+ AdminHealth health = new AdminHealth(Health.HEALTHY, 200);
+ assertEquals(Health.HEALTHY, health.getHealth());
+ assertEquals(200, health.getStatusCode());
+ health.setStatusCode(409);
+ assertEquals(409, health.getStatusCode());
+ }
+} \ No newline at end of file
diff --git a/plugins/grToolkit/provider/src/test/java/org/onap/ccsdk/sli/plugins/grtoolkit/data/ClusterHealthTest.java b/plugins/grToolkit/provider/src/test/java/org/onap/ccsdk/sli/plugins/grtoolkit/data/ClusterHealthTest.java
new file mode 100644
index 000000000..2e2ab3fd7
--- /dev/null
+++ b/plugins/grToolkit/provider/src/test/java/org/onap/ccsdk/sli/plugins/grtoolkit/data/ClusterHealthTest.java
@@ -0,0 +1,47 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.grtoolkit.data;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+public class ClusterHealthTest {
+ @Test
+ public void constructorTest() {
+ ClusterHealth health = new ClusterHealth();
+ assertEquals(Health.FAULTY, health.getHealth());
+ }
+
+ @Test
+ public void withHealth() {
+ ClusterHealth health = new ClusterHealth().withHealth(Health.HEALTHY);
+ assertEquals(Health.HEALTHY, health.getHealth());
+ }
+
+ @Test
+ public void setHealth() {
+ ClusterHealth health = new ClusterHealth();
+ health.setHealth(Health.HEALTHY);
+ assertEquals(Health.HEALTHY, health.getHealth());
+ }
+} \ No newline at end of file
diff --git a/plugins/grToolkit/provider/src/test/java/org/onap/ccsdk/sli/plugins/grtoolkit/data/DatabaseHealthTest.java b/plugins/grToolkit/provider/src/test/java/org/onap/ccsdk/sli/plugins/grtoolkit/data/DatabaseHealthTest.java
new file mode 100644
index 000000000..05621a503
--- /dev/null
+++ b/plugins/grToolkit/provider/src/test/java/org/onap/ccsdk/sli/plugins/grtoolkit/data/DatabaseHealthTest.java
@@ -0,0 +1,42 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.grtoolkit.data;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+public class DatabaseHealthTest {
+ @Test
+ public void constructorTest() {
+ DatabaseHealth health = new DatabaseHealth(Health.FAULTY);
+ assertEquals(Health.FAULTY, health.getHealth());
+ }
+
+ @Test
+ public void setHealth() {
+ DatabaseHealth health = new DatabaseHealth(Health.FAULTY);
+ assertEquals(Health.FAULTY, health.getHealth());
+ health.setHealth(Health.HEALTHY);
+ assertEquals(Health.HEALTHY, health.getHealth());
+ }
+} \ No newline at end of file
diff --git a/plugins/grToolkit/provider/src/test/java/org/onap/ccsdk/sli/plugins/grtoolkit/data/FailoverStatusTest.java b/plugins/grToolkit/provider/src/test/java/org/onap/ccsdk/sli/plugins/grtoolkit/data/FailoverStatusTest.java
new file mode 100644
index 000000000..b5b3d00d2
--- /dev/null
+++ b/plugins/grToolkit/provider/src/test/java/org/onap/ccsdk/sli/plugins/grtoolkit/data/FailoverStatusTest.java
@@ -0,0 +1,60 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.grtoolkit.data;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+public class FailoverStatusTest {
+ @Test
+ public void constructorTest() {
+ FailoverStatus status = new FailoverStatus();
+ assertEquals(200, status.getStatusCode());
+ assertEquals("Failover complete.", status.getMessage());
+ }
+ @Test
+ public void withStatusCode() {
+ FailoverStatus status = new FailoverStatus().withStatusCode(500);
+ assertEquals(500, status.getStatusCode());
+ }
+
+ @Test
+ public void withMessage() {
+ FailoverStatus status = new FailoverStatus().withMessage("Test");
+ assertEquals("Test", status.getMessage());
+ }
+
+ @Test
+ public void setStatusCode() {
+ FailoverStatus status = new FailoverStatus();
+ status.setStatusCode(500);
+ assertEquals(500, status.getStatusCode());
+ }
+
+ @Test
+ public void setMessage() {
+ FailoverStatus status = new FailoverStatus();
+ status.setMessage("Test");
+ assertEquals("Test", status.getMessage());
+ }
+} \ No newline at end of file
diff --git a/plugins/grToolkit/provider/src/test/java/org/onap/ccsdk/sli/plugins/grtoolkit/data/HealthTest.java b/plugins/grToolkit/provider/src/test/java/org/onap/ccsdk/sli/plugins/grtoolkit/data/HealthTest.java
new file mode 100644
index 000000000..1115d2084
--- /dev/null
+++ b/plugins/grToolkit/provider/src/test/java/org/onap/ccsdk/sli/plugins/grtoolkit/data/HealthTest.java
@@ -0,0 +1,34 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.grtoolkit.data;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+public class HealthTest {
+ @Test
+ public void getHealth() {
+ assertEquals("HEALTHY", Health.HEALTHY.getHealth());
+ assertEquals("FAULTY", Health.FAULTY.getHealth());
+ }
+} \ No newline at end of file
diff --git a/plugins/grToolkit/provider/src/test/java/org/onap/ccsdk/sli/plugins/grtoolkit/data/MemberBuilderTest.java b/plugins/grToolkit/provider/src/test/java/org/onap/ccsdk/sli/plugins/grtoolkit/data/MemberBuilderTest.java
new file mode 100644
index 000000000..7ed0135a6
--- /dev/null
+++ b/plugins/grToolkit/provider/src/test/java/org/onap/ccsdk/sli/plugins/grtoolkit/data/MemberBuilderTest.java
@@ -0,0 +1,62 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2018 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.grtoolkit.data;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+
+import static org.junit.Assert.*;
+
+public class MemberBuilderTest {
+ MemberBuilder builder;
+ ClusterActor actor;
+
+ @Before
+ public void setUp() {
+ actor = new ClusterActor();
+ actor.setUp(true);
+ actor.setVoting(true);
+ }
+
+ @Test
+ public void constructorTest() {
+ ArrayList<String> actorList = new ArrayList<>();
+ ArrayList<String> shardList = new ArrayList<>();
+ HashMap<String, Integer> commitMap = new HashMap<>();
+ actorList.add("Some-Actor");
+ shardList.add("Some-shard");
+ commitMap.put("Some-shard", 4);
+ commitMap.put("Some-other-shard", -4);
+ actor.setShardLeader(actorList);
+ actor.setReplicaShards(shardList);
+ actor.setNonReplicaShards(shardList);
+ actor.setCommits(commitMap);
+ assertNotNull(actor.toString());
+ assertEquals("", actor.getSite());
+ assertEquals(1, actor.getNonReplicaShards().size());
+ builder = new MemberBuilder(actor);
+ assertNotNull(builder.build());
+ }
+} \ No newline at end of file
diff --git a/plugins/grToolkit/provider/src/test/java/org/onap/ccsdk/sli/plugins/grtoolkit/data/SiteHealthTest.java b/plugins/grToolkit/provider/src/test/java/org/onap/ccsdk/sli/plugins/grtoolkit/data/SiteHealthTest.java
new file mode 100644
index 000000000..7b74991e7
--- /dev/null
+++ b/plugins/grToolkit/provider/src/test/java/org/onap/ccsdk/sli/plugins/grtoolkit/data/SiteHealthTest.java
@@ -0,0 +1,108 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.grtoolkit.data;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+public class SiteHealthTest {
+ @Test
+ public void constructorTest() {
+ SiteHealth health = new SiteHealth();
+ assertNotNull(health.getAdminHealth());
+ assertNotNull(health.getDatabaseHealth());
+ assertNotNull(health.getClusterHealth());
+ assertEquals(Health.FAULTY, health.getHealth());
+ }
+ @Test
+ public void withAdminHealth() {
+ SiteHealth health = new SiteHealth().withAdminHealth(new AdminHealth(Health.HEALTHY));
+ assertEquals(Health.HEALTHY, health.getAdminHealth().get(0).getHealth());
+ }
+
+ @Test
+ public void withDatabaseHealth() {
+ SiteHealth health = new SiteHealth().withDatabaseHealth(new DatabaseHealth(Health.HEALTHY));
+ assertEquals(Health.HEALTHY, health.getDatabaseHealth().get(0).getHealth());
+ }
+
+ @Test
+ public void withClusterHealth() {
+ SiteHealth health = new SiteHealth().withClusterHealth(new ClusterHealth());
+ assertEquals(Health.FAULTY, health.getClusterHealth().get(0).getHealth());
+ }
+
+ @Test
+ public void withId() {
+ SiteHealth health = new SiteHealth().withId("My_ID");
+ assertEquals("My_ID", health.getId());
+ }
+
+ @Test
+ public void withRole() {
+ SiteHealth health = new SiteHealth().withRole("My_role");
+ assertEquals("My_role", health.getRole());
+ }
+
+ @Test
+ public void setHealth() {
+ SiteHealth health = new SiteHealth();
+ health.setHealth(Health.HEALTHY);
+ assertEquals(Health.HEALTHY, health.getHealth());
+ }
+
+ @Test
+ public void setAdminHealth() {
+ SiteHealth health = new SiteHealth().withAdminHealth(new AdminHealth(Health.HEALTHY));
+ health.setAdminHealth(null);
+ assertNull(health.getAdminHealth());
+ }
+
+ @Test
+ public void setDatabaseHealth() {
+ SiteHealth health = new SiteHealth().withDatabaseHealth(new DatabaseHealth(Health.HEALTHY));
+ health.setDatabaseHealth(null);
+ assertNull(health.getDatabaseHealth());
+ }
+
+ @Test
+ public void setClusterHealth() {
+ SiteHealth health = new SiteHealth().withClusterHealth(new ClusterHealth());
+ health.setClusterHealth(null);
+ assertNull(health.getClusterHealth());
+ }
+
+ @Test
+ public void setId() {
+ SiteHealth health = new SiteHealth().withId("My_ID");
+ health.setId("My_new_ID");
+ assertEquals("My_new_ID", health.getId());
+ }
+
+ @Test
+ public void setRole() {
+ SiteHealth health = new SiteHealth().withRole("My_role");
+ health.setRole("My_new_role");
+ assertEquals("My_new_role", health.getRole());
+ }
+} \ No newline at end of file
diff --git a/plugins/grToolkit/provider/src/test/java/org/onap/ccsdk/sli/plugins/grtoolkit/resolver/SingleNodeHealthResolverTest.java b/plugins/grToolkit/provider/src/test/java/org/onap/ccsdk/sli/plugins/grtoolkit/resolver/SingleNodeHealthResolverTest.java
new file mode 100644
index 000000000..2827b4055
--- /dev/null
+++ b/plugins/grToolkit/provider/src/test/java/org/onap/ccsdk/sli/plugins/grtoolkit/resolver/SingleNodeHealthResolverTest.java
@@ -0,0 +1,235 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.grtoolkit.resolver;
+
+import com.github.tomakehurst.wiremock.junit.WireMockRule;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+import org.onap.ccsdk.sli.core.dblib.DBLibConnection;
+import org.onap.ccsdk.sli.core.dblib.DbLibService;
+import org.onap.ccsdk.sli.plugins.grtoolkit.data.AdminHealth;
+import org.onap.ccsdk.sli.plugins.grtoolkit.data.ClusterActor;
+import org.onap.ccsdk.sli.plugins.grtoolkit.data.ClusterHealth;
+import org.onap.ccsdk.sli.plugins.grtoolkit.data.DatabaseHealth;
+import org.onap.ccsdk.sli.plugins.grtoolkit.data.FailoverStatus;
+import org.onap.ccsdk.sli.plugins.grtoolkit.data.Health;
+import org.onap.ccsdk.sli.plugins.grtoolkit.data.SiteHealth;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.sql.SQLException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
+import static com.github.tomakehurst.wiremock.client.WireMock.get;
+import static com.github.tomakehurst.wiremock.client.WireMock.stubFor;
+import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
+
+import static org.junit.Assert.*;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class SingleNodeHealthResolverTest {
+ private Map<String, ClusterActor> memberMap;
+ private DbLibService dbLibService;
+ private DBLibConnection connection;
+ private SingleNodeHealthResolver resolver;
+
+ @Rule
+ public WireMockRule wireMockRule = new WireMockRule(9999);
+
+ @Before
+ public void setUp() {
+ memberMap = generateMemberMap(1);
+ Properties properties = new Properties();
+ try(FileInputStream fileInputStream = new FileInputStream("src/test/resources/single/gr-toolkit.properties")) {
+ properties.load(fileInputStream);
+ } catch(IOException e) {
+ fail();
+ }
+
+ dbLibService = mock(DbLibService.class);
+ connection = mock(DBLibConnection.class);
+ resolver = new SingleNodeHealthResolver(memberMap, properties, dbLibService);
+ }
+
+ private Map<String, ClusterActor> generateMemberMap(int memberCount) {
+ Map<String, ClusterActor> map = new HashMap<>();
+ ClusterActor actor;
+ for(int ndx = 0; ndx < memberCount; ndx++) {
+ actor = new ClusterActor();
+ actor.setNode("localhost");
+ actor.setAkkaPort("2550");
+ actor.setMember("member-" + (ndx + 1));
+ actor.setUp(true);
+ actor.setUnreachable(false);
+
+ map.put(actor.getNode(), actor);
+ }
+ return map;
+ }
+
+ @Test
+ public void getAdminHealthFaulty() {
+ stubFor(get(urlEqualTo("/adm/healthcheck")).willReturn(aResponse().withStatus(500)));
+ AdminHealth health = resolver.getAdminHealth();
+ assertNotNull(health);
+ assertEquals(500, health.getStatusCode());
+ assertEquals(Health.FAULTY, health.getHealth());
+ }
+
+ @Test
+ public void getAdminHealthHealthy() {
+ stubFor(get(urlEqualTo("/adm/healthcheck")).willReturn(aResponse().withStatus(200)));
+ AdminHealth health = resolver.getAdminHealth();
+ assertNotNull(health);
+ assertEquals(200, health.getStatusCode());
+ assertEquals(Health.HEALTHY, health.getHealth());
+ }
+
+ @Test
+ public void getDatabaseHealth() {
+ try {
+ when(connection.isReadOnly()).thenReturn(false);
+ when(connection.isClosed()).thenReturn(false);
+ when(dbLibService.isActive()).thenReturn(true);
+ when(dbLibService.getConnection()).thenReturn(connection);
+ } catch(SQLException e) {
+ fail();
+ }
+ DatabaseHealth health = resolver.getDatabaseHealth();
+ assertEquals(Health.HEALTHY, health.getHealth());
+ }
+
+ @Test
+ public void getDatabaseHealthFaulty() {
+ try {
+ when(connection.isReadOnly()).thenReturn(true);
+ when(connection.isClosed()).thenReturn(true);
+ when(dbLibService.isActive()).thenReturn(false);
+ when(dbLibService.getConnection()).thenReturn(connection);
+ } catch(SQLException e) {
+ fail();
+ }
+ DatabaseHealth health = resolver.getDatabaseHealth();
+ assertEquals(Health.FAULTY, health.getHealth());
+ }
+
+ @Test
+ public void getDatabaseHealthException() {
+ try {
+ when(connection.isReadOnly()).thenThrow(new SQLException());
+ when(connection.isClosed()).thenReturn(true);
+ when(dbLibService.isActive()).thenReturn(false);
+ when(dbLibService.getConnection()).thenReturn(connection);
+ } catch(SQLException e) {
+ fail();
+ }
+ DatabaseHealth health = resolver.getDatabaseHealth();
+ assertEquals(Health.FAULTY, health.getHealth());
+ }
+
+ @Test
+ public void siteIdentifier() {
+ assertEquals("TestODL", resolver.getSiteIdentifier());
+ resolver.setSiteIdentifier("NewTestODL");
+ assertEquals("NewTestODL", resolver.getSiteIdentifier());
+ }
+
+ @Test
+ public void getClusterHealth() {
+ stubController();
+ ClusterHealth health = resolver.getClusterHealth();
+ assertEquals(Health.HEALTHY, health.getHealth());
+ }
+
+ private void stubController() {
+ String clusterBody = null;
+ String shardManagerBody = null;
+ String shardDefaultBody = null;
+ String shardOperationalBody = null;
+ try(Stream<String> stream = Files.lines(Paths.get("src/test/resources/single/cluster.json"))) {
+ clusterBody = stream.collect(Collectors.joining());
+ } catch(IOException e) {
+ fail();
+ }
+ try(Stream<String> stream = Files.lines(Paths.get("src/test/resources/single/shard-manager.json"))) {
+ shardManagerBody = stream.collect(Collectors.joining());
+ } catch(IOException e) {
+ fail();
+ }
+ try(Stream<String> stream = Files.lines(Paths.get("src/test/resources/single/default-config.json"))) {
+ shardDefaultBody = stream.collect(Collectors.joining());
+ } catch(IOException e) {
+ fail();
+ }
+ try(Stream<String> stream = Files.lines(Paths.get("src/test/resources/single/default-operational.json"))) {
+ shardOperationalBody = stream.collect(Collectors.joining());
+ } catch(IOException e) {
+ fail();
+ }
+
+ if(clusterBody == null || shardManagerBody == null || shardDefaultBody == null || shardOperationalBody == null) {
+ fail();
+ }
+ stubFor(get(urlEqualTo("/jolokia/read/akka:type=Cluster")).willReturn(aResponse().withStatus(200).withBody(clusterBody)));
+ stubFor(get(urlEqualTo("/jolokia/read/org.opendaylight.controller:Category=ShardManager,name=shard-manager-config,type=DistributedConfigDatastore")).willReturn(aResponse().withStatus(200).withBody(shardManagerBody)));
+ stubFor(get(urlEqualTo("/jolokia/read/org.opendaylight.controller:Category=Shards,name=member-1-shard-default-config,type=DistributedConfigDatastore")).willReturn(aResponse().withStatus(200).withBody(shardDefaultBody)));
+ stubFor(get(urlEqualTo("/jolokia/read/org.opendaylight.controller:Category=Shards,name=member-1-shard-default-operational,type=DistributedOperationalDatastore")).willReturn(aResponse().withStatus(200).withBody(shardOperationalBody)));
+ }
+
+ @Test
+ public void getSiteHealth() {
+ stubController();
+ stubFor(get(urlEqualTo("/adm/healthcheck")).willReturn(aResponse().withStatus(200)));
+ try {
+ when(connection.isReadOnly()).thenReturn(false);
+ when(connection.isClosed()).thenReturn(false);
+ when(dbLibService.isActive()).thenReturn(true);
+ when(dbLibService.getConnection()).thenReturn(connection);
+ } catch(SQLException e) {
+ fail();
+ }
+ List<SiteHealth> health = resolver.getSiteHealth();
+ assertNotNull(health);
+ assertNotEquals(0, health.size());
+ assertEquals(1, health.size());
+ assertEquals(Health.HEALTHY, health.get(0).getHealth());
+ }
+
+ @Test
+ public void tryFailover() {
+ FailoverStatus status = resolver.tryFailover(null);
+ assertEquals(400, status.getStatusCode());
+ }
+} \ No newline at end of file
diff --git a/plugins/grToolkit/provider/src/test/java/org/onap/ccsdk/sli/plugins/grtoolkit/resolver/SixNodeHealthResolverTest.java b/plugins/grToolkit/provider/src/test/java/org/onap/ccsdk/sli/plugins/grtoolkit/resolver/SixNodeHealthResolverTest.java
new file mode 100644
index 000000000..cbab450e1
--- /dev/null
+++ b/plugins/grToolkit/provider/src/test/java/org/onap/ccsdk/sli/plugins/grtoolkit/resolver/SixNodeHealthResolverTest.java
@@ -0,0 +1,335 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.grtoolkit.resolver;
+
+import com.github.tomakehurst.wiremock.junit.WireMockRule;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+import org.onap.ccsdk.sli.core.dblib.DBLibConnection;
+import org.onap.ccsdk.sli.core.dblib.DbLibService;
+import org.onap.ccsdk.sli.plugins.grtoolkit.data.AdminHealth;
+import org.onap.ccsdk.sli.plugins.grtoolkit.data.ClusterActor;
+import org.onap.ccsdk.sli.plugins.grtoolkit.data.ClusterHealth;
+import org.onap.ccsdk.sli.plugins.grtoolkit.data.DatabaseHealth;
+import org.onap.ccsdk.sli.plugins.grtoolkit.data.FailoverStatus;
+import org.onap.ccsdk.sli.plugins.grtoolkit.data.Health;
+import org.onap.ccsdk.sli.plugins.grtoolkit.data.SiteHealth;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.sql.SQLException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
+import static com.github.tomakehurst.wiremock.client.WireMock.get;
+import static com.github.tomakehurst.wiremock.client.WireMock.post;
+import static com.github.tomakehurst.wiremock.client.WireMock.stubFor;
+import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
+
+import static org.junit.Assert.*;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class SixNodeHealthResolverTest {
+ private Map<String, ClusterActor> memberMap;
+ private DbLibService dbLibService;
+ private DBLibConnection connection;
+ private SixNodeHealthResolver resolver;
+
+ @Rule
+ public WireMockRule wireMockRule = new WireMockRule(9999);
+
+ @Before
+ public void setUp() {
+ memberMap = generateMemberMap(6);
+ Properties properties = new Properties();
+ try(FileInputStream fileInputStream = new FileInputStream("src/test/resources/six/gr-toolkit.properties")) {
+ properties.load(fileInputStream);
+ } catch(IOException e) {
+ fail();
+ }
+
+ dbLibService = mock(DbLibService.class);
+ connection = mock(DBLibConnection.class);
+ resolver = new SixNodeHealthResolver(memberMap, properties, dbLibService);
+ }
+
+ private Map<String, ClusterActor> generateMemberMap(int memberCount) {
+ Map<String, ClusterActor> map = new HashMap<>();
+ ClusterActor actor;
+ for(int ndx = 0; ndx < memberCount; ndx++) {
+ actor = new ClusterActor();
+ actor.setNode("127.0.1." + (ndx + 1));
+ actor.setAkkaPort("2550");
+ actor.setMember("member-" + (ndx + 1));
+ actor.setUp(true);
+ actor.setUnreachable(false);
+
+ map.put(actor.getNode(), actor);
+ }
+ return map;
+ }
+
+ @Test
+ public void getAdminHealthFaulty() {
+ stubFor(get(urlEqualTo("/adm/healthcheck")).willReturn(aResponse().withStatus(500)));
+ AdminHealth health = resolver.getAdminHealth();
+ assertNotNull(health);
+ assertEquals(500, health.getStatusCode());
+ assertEquals(Health.FAULTY, health.getHealth());
+ }
+
+ @Test
+ public void getAdminHealthHealthy() {
+ stubFor(get(urlEqualTo("/adm/healthcheck")).willReturn(aResponse().withStatus(200)));
+ AdminHealth health = resolver.getAdminHealth();
+ assertNotNull(health);
+ assertEquals(200, health.getStatusCode());
+ assertEquals(Health.HEALTHY, health.getHealth());
+ }
+
+ @Test
+ public void getDatabaseHealth() {
+ try {
+ when(connection.isReadOnly()).thenReturn(false);
+ when(connection.isClosed()).thenReturn(false);
+ when(dbLibService.isActive()).thenReturn(true);
+ when(dbLibService.getConnection()).thenReturn(connection);
+ } catch(SQLException e) {
+ fail();
+ }
+ DatabaseHealth health = resolver.getDatabaseHealth();
+ assertEquals(Health.HEALTHY, health.getHealth());
+ }
+
+ @Test
+ public void getDatabaseHealthFaulty() {
+ try {
+ when(connection.isReadOnly()).thenReturn(true);
+ when(connection.isClosed()).thenReturn(true);
+ when(dbLibService.isActive()).thenReturn(false);
+ when(dbLibService.getConnection()).thenReturn(connection);
+ } catch(SQLException e) {
+ fail();
+ }
+ DatabaseHealth health = resolver.getDatabaseHealth();
+ assertEquals(Health.FAULTY, health.getHealth());
+ }
+
+ @Test
+ public void getDatabaseHealthException() {
+ try {
+ when(connection.isReadOnly()).thenThrow(new SQLException());
+ when(connection.isClosed()).thenReturn(true);
+ when(dbLibService.isActive()).thenReturn(false);
+ when(dbLibService.getConnection()).thenReturn(connection);
+ } catch(SQLException e) {
+ fail();
+ }
+ DatabaseHealth health = resolver.getDatabaseHealth();
+ assertEquals(Health.FAULTY, health.getHealth());
+ }
+
+ @Test
+ public void siteIdentifier() {
+ assertEquals("TestODL", resolver.getSiteIdentifier());
+ resolver.setSiteIdentifier("NewTestODL");
+ assertEquals("NewTestODL", resolver.getSiteIdentifier());
+ }
+
+ @Test
+ public void getClusterHealth() {
+ stubController();
+ ClusterHealth health = resolver.getClusterHealth();
+ assertEquals(Health.HEALTHY, health.getHealth());
+ }
+
+ private void stubController() {
+ String clusterBody = null;
+ String shardManagerBody = null;
+ String shardDefaultBody = null;
+ String shardOperationalBody = null;
+ String componentBody = null;
+ String identifierBody = null;
+ try(Stream<String> stream = Files.lines(Paths.get("src/test/resources/six/cluster.json"))) {
+ clusterBody = stream.collect(Collectors.joining());
+ } catch(IOException e) {
+ fail();
+ }
+ try(Stream<String> stream = Files.lines(Paths.get("src/test/resources/six/shard-manager.json"))) {
+ shardManagerBody = stream.collect(Collectors.joining());
+ } catch(IOException e) {
+ fail();
+ }
+ try(Stream<String> stream = Files.lines(Paths.get("src/test/resources/six/default-config.json"))) {
+ shardDefaultBody = stream.collect(Collectors.joining());
+ } catch(IOException e) {
+ fail();
+ }
+ try(Stream<String> stream = Files.lines(Paths.get("src/test/resources/six/default-operational.json"))) {
+ shardOperationalBody = stream.collect(Collectors.joining());
+ } catch(IOException e) {
+ fail();
+ }
+ try(Stream<String> stream = Files.lines(Paths.get("src/test/resources/six/component-health.json"))) {
+ componentBody = stream.collect(Collectors.joining());
+ } catch(IOException e) {
+ fail();
+ }
+ try(Stream<String> stream = Files.lines(Paths.get("src/test/resources/six/site-identifier.json"))) {
+ identifierBody = stream.collect(Collectors.joining());
+ } catch(IOException e) {
+ fail();
+ }
+
+ if(clusterBody == null || shardManagerBody == null || shardDefaultBody == null || shardOperationalBody == null
+ || componentBody == null || identifierBody == null) {
+ fail();
+ }
+ stubFor(get(urlEqualTo("/jolokia/read/akka:type=Cluster")).willReturn(aResponse().withStatus(200).withBody(clusterBody)));
+ stubFor(get(urlEqualTo("/jolokia/read/org.opendaylight.controller:Category=ShardManager,name=shard-manager-config,type=DistributedConfigDatastore")).inScenario("testing").willReturn(aResponse().withStatus(200).withBody(shardManagerBody)).willSetStateTo("next"));
+ stubFor(get(urlEqualTo("/jolokia/read/org.opendaylight.controller:Category=Shards,name=member-1-shard-default-config,type=DistributedConfigDatastore")).inScenario("testing").willReturn(aResponse().withStatus(200).withBody(shardDefaultBody)).willSetStateTo("next"));
+ stubFor(get(urlEqualTo("/jolokia/read/org.opendaylight.controller:Category=Shards,name=member-1-shard-default-operational,type=DistributedOperationalDatastore")).willReturn(aResponse().withStatus(200).withBody(shardOperationalBody)));
+ stubFor(post(urlEqualTo("/restconf/operations/gr-toolkit:site-identifier")).willReturn(aResponse().withStatus(200).withBody(identifierBody)));
+ stubFor(post(urlEqualTo("/restconf/operations/gr-toolkit:admin-health")).inScenario("testing").willReturn(aResponse().withStatus(200).withBody(componentBody)).willSetStateTo("next"));
+ stubFor(post(urlEqualTo("/restconf/operations/gr-toolkit:database-health")).willReturn(aResponse().withStatus(200).withBody(componentBody)));
+ }
+
+ @Test
+ public void getSiteHealth() {
+ stubController();
+ stubFor(get(urlEqualTo("/adm/healthcheck")).willReturn(aResponse().withStatus(200)));
+ try {
+ when(connection.isReadOnly()).thenReturn(false);
+ when(connection.isClosed()).thenReturn(false);
+ when(dbLibService.isActive()).thenReturn(true);
+ when(dbLibService.getConnection()).thenReturn(connection);
+ } catch(SQLException e) {
+ fail();
+ }
+ List<SiteHealth> health = resolver.getSiteHealth();
+ assertNotNull(health);
+ assertNotEquals(0, health.size());
+ assertEquals(2, health.size());
+ assertEquals(Health.HEALTHY, health.get(0).getHealth());
+ }
+
+ @Test
+ public void getSiteHealthFaulty() {
+ stubController();
+ stubFor(get(urlEqualTo("/adm/healthcheck")).willReturn(aResponse().withStatus(200)));
+ try {
+ when(connection.isReadOnly()).thenReturn(false);
+ when(connection.isClosed()).thenReturn(false);
+ when(dbLibService.isActive()).thenReturn(true);
+ when(dbLibService.getConnection()).thenReturn(connection);
+ } catch(SQLException e) {
+ fail();
+ }
+ stubFor(get(urlEqualTo("/jolokia/read/org.opendaylight.controller:Category=ShardManager,name=shard-manager-config,type=DistributedConfigDatastore")).inScenario("testing").whenScenarioStateIs("next").willReturn(aResponse().withBodyFile("nonexistent")));
+ List<SiteHealth> health = resolver.getSiteHealth();
+ assertNotNull(health);
+ assertNotEquals(0, health.size());
+ assertEquals(2, health.size());
+ assertEquals(Health.FAULTY, health.get(0).getHealth());
+ }
+
+ @Test
+ public void getSiteHealthFaultyShard() {
+ stubController();
+ stubFor(get(urlEqualTo("/adm/healthcheck")).willReturn(aResponse().withStatus(200)));
+ try {
+ when(connection.isReadOnly()).thenReturn(false);
+ when(connection.isClosed()).thenReturn(false);
+ when(dbLibService.isActive()).thenReturn(true);
+ when(dbLibService.getConnection()).thenReturn(connection);
+ } catch(SQLException e) {
+ fail();
+ }
+ stubFor(get(urlEqualTo("/jolokia/read/org.opendaylight.controller:Category=Shards,name=member-1-shard-default-config,type=DistributedConfigDatastore")).inScenario("testing").willReturn(aResponse().withBodyFile("nonexistent")).willSetStateTo("next"));
+ List<SiteHealth> health = resolver.getSiteHealth();
+ assertNotNull(health);
+ assertNotEquals(0, health.size());
+ assertEquals(2, health.size());
+ assertEquals(Health.FAULTY, health.get(0).getHealth());
+ }
+
+ @Test
+ public void getSiteHealthFaultyCluster() {
+ stubController();
+ stubFor(get(urlEqualTo("/adm/healthcheck")).willReturn(aResponse().withStatus(200)));
+ try {
+ when(connection.isReadOnly()).thenReturn(false);
+ when(connection.isClosed()).thenReturn(false);
+ when(dbLibService.isActive()).thenReturn(true);
+ when(dbLibService.getConnection()).thenReturn(connection);
+ } catch(SQLException e) {
+ fail();
+ }
+ stubFor(get(urlEqualTo("/jolokia/read/akka:type=Cluster")).willReturn(aResponse().withStatus(200).withBodyFile("nonexistent")));
+ List<SiteHealth> health = resolver.getSiteHealth();
+ assertNotNull(health);
+ assertNotEquals(0, health.size());
+ assertEquals(2, health.size());
+ assertEquals(Health.FAULTY, health.get(0).getHealth());
+ }
+
+ @Test
+ public void getSiteHealthFaultyAdmin() {
+ stubController();
+ stubFor(post(urlEqualTo("/restconf/operations/gr-toolkit:admin-health")).inScenario("testing").willReturn(aResponse().withBodyFile("nonexistent")).willSetStateTo("next"));
+ stubFor(get(urlEqualTo("/restconf/operations/gr-toolkit:admin-health")).inScenario("testing").whenScenarioStateIs("next").willReturn(aResponse().withBodyFile("nonexistent")));
+ try {
+ when(connection.isReadOnly()).thenReturn(false);
+ when(connection.isClosed()).thenReturn(false);
+ when(dbLibService.isActive()).thenReturn(true);
+ when(dbLibService.getConnection()).thenReturn(connection);
+ } catch(SQLException e) {
+ fail();
+ }
+ List<SiteHealth> health = resolver.getSiteHealth();
+ assertNotNull(health);
+ assertNotEquals(0, health.size());
+ assertEquals(2, health.size());
+ assertEquals(Health.FAULTY, health.get(0).getHealth());
+ assertEquals(Health.FAULTY, health.get(1).getHealth());
+ }
+
+ @Test
+ public void tryFailover() {
+ stubController();
+ stubFor(get(urlEqualTo("/restconf/operations/cluster-admin:change-member-voting-states-for-all-shards")).willReturn(aResponse().withStatus(200)));
+ FailoverStatus status = resolver.tryFailover(null);
+ assertEquals(500, status.getStatusCode());
+ }
+} \ No newline at end of file
diff --git a/plugins/grToolkit/provider/src/test/java/org/onap/ccsdk/sli/plugins/grtoolkit/resolver/ThreeNodeHealthResolverTest.java b/plugins/grToolkit/provider/src/test/java/org/onap/ccsdk/sli/plugins/grtoolkit/resolver/ThreeNodeHealthResolverTest.java
new file mode 100644
index 000000000..4ea07be43
--- /dev/null
+++ b/plugins/grToolkit/provider/src/test/java/org/onap/ccsdk/sli/plugins/grtoolkit/resolver/ThreeNodeHealthResolverTest.java
@@ -0,0 +1,314 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2019 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.grtoolkit.resolver;
+
+import com.github.tomakehurst.wiremock.junit.WireMockRule;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+
+import org.onap.ccsdk.sli.core.dblib.DBLibConnection;
+import org.onap.ccsdk.sli.core.dblib.DbLibService;
+import org.onap.ccsdk.sli.plugins.grtoolkit.data.AdminHealth;
+import org.onap.ccsdk.sli.plugins.grtoolkit.data.ClusterActor;
+import org.onap.ccsdk.sli.plugins.grtoolkit.data.ClusterHealth;
+import org.onap.ccsdk.sli.plugins.grtoolkit.data.DatabaseHealth;
+import org.onap.ccsdk.sli.plugins.grtoolkit.data.FailoverStatus;
+import org.onap.ccsdk.sli.plugins.grtoolkit.data.Health;
+import org.onap.ccsdk.sli.plugins.grtoolkit.data.SiteHealth;
+
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.sql.SQLException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
+import static com.github.tomakehurst.wiremock.client.WireMock.get;
+import static com.github.tomakehurst.wiremock.client.WireMock.stubFor;
+import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
+
+import static org.junit.Assert.*;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class ThreeNodeHealthResolverTest {
+ private Map<String, ClusterActor> memberMap;
+ private DbLibService dbLibService;
+ private DBLibConnection connection;
+ private ThreeNodeHealthResolver resolver;
+
+ @Rule
+ public WireMockRule wireMockRule = new WireMockRule(9999);
+
+ @Before
+ public void setUp() {
+ memberMap = generateMemberMap(3);
+ Properties properties = new Properties();
+ try(FileInputStream fileInputStream = new FileInputStream("src/test/resources/three/gr-toolkit.properties")) {
+ properties.load(fileInputStream);
+ } catch(IOException e) {
+ fail();
+ }
+
+ dbLibService = mock(DbLibService.class);
+ connection = mock(DBLibConnection.class);
+ resolver = new ThreeNodeHealthResolver(memberMap, properties, dbLibService);
+ }
+
+ private Map<String, ClusterActor> generateMemberMap(int memberCount) {
+ Map<String, ClusterActor> map = new HashMap<>();
+ ClusterActor actor;
+ for(int ndx = 0; ndx < memberCount; ndx++) {
+ actor = new ClusterActor();
+ actor.setNode("127.0.1." + (ndx + 1));
+ actor.setAkkaPort("2550");
+ actor.setMember("member-" + (ndx + 1));
+ actor.setUp(true);
+ actor.setUnreachable(false);
+
+ map.put(actor.getNode(), actor);
+ }
+ return map;
+ }
+
+ @Test
+ public void getAdminHealthFaulty() {
+ stubFor(get(urlEqualTo("/adm/healthcheck")).willReturn(aResponse().withStatus(500)));
+ AdminHealth health = resolver.getAdminHealth();
+ assertNotNull(health);
+ assertEquals(500, health.getStatusCode());
+ assertEquals(Health.FAULTY, health.getHealth());
+ }
+
+ @Test
+ public void getAdminHealthHealthy() {
+ stubFor(get(urlEqualTo("/adm/healthcheck")).willReturn(aResponse().withStatus(200)));
+ AdminHealth health = resolver.getAdminHealth();
+ assertNotNull(health);
+ assertEquals(200, health.getStatusCode());
+ assertEquals(Health.HEALTHY, health.getHealth());
+ }
+
+ @Test
+ public void getDatabaseHealth() {
+ try {
+ when(connection.isReadOnly()).thenReturn(false);
+ when(connection.isClosed()).thenReturn(false);
+ when(dbLibService.isActive()).thenReturn(true);
+ when(dbLibService.getConnection()).thenReturn(connection);
+ } catch(SQLException e) {
+ fail();
+ }
+ DatabaseHealth health = resolver.getDatabaseHealth();
+ assertEquals(Health.HEALTHY, health.getHealth());
+ }
+
+ @Test
+ public void getDatabaseHealthFaulty() {
+ try {
+ when(connection.isReadOnly()).thenReturn(true);
+ when(connection.isClosed()).thenReturn(true);
+ when(dbLibService.isActive()).thenReturn(false);
+ when(dbLibService.getConnection()).thenReturn(connection);
+ } catch(SQLException e) {
+ fail();
+ }
+ DatabaseHealth health = resolver.getDatabaseHealth();
+ assertEquals(Health.FAULTY, health.getHealth());
+ }
+
+ @Test
+ public void getDatabaseHealthException() {
+ try {
+ when(connection.isReadOnly()).thenThrow(new SQLException());
+ when(connection.isClosed()).thenReturn(true);
+ when(dbLibService.isActive()).thenReturn(false);
+ when(dbLibService.getConnection()).thenReturn(connection);
+ } catch(SQLException e) {
+ fail();
+ }
+ DatabaseHealth health = resolver.getDatabaseHealth();
+ assertEquals(Health.FAULTY, health.getHealth());
+ }
+
+ @Test
+ public void siteIdentifier() {
+ assertEquals("TestODL", resolver.getSiteIdentifier());
+ resolver.setSiteIdentifier("NewTestODL");
+ assertEquals("NewTestODL", resolver.getSiteIdentifier());
+ }
+
+ @Test
+ public void getClusterHealth() {
+ stubController();
+ ClusterHealth health = resolver.getClusterHealth();
+ assertEquals(Health.HEALTHY, health.getHealth());
+ }
+
+ private void stubController() {
+ String clusterBody = null;
+ String shardManagerBody = null;
+ String shardDefaultBody = null;
+ String shardOperationalBody = null;
+ try(Stream<String> stream = Files.lines(Paths.get("src/test/resources/three/cluster.json"))) {
+ clusterBody = stream.collect(Collectors.joining());
+ } catch(IOException e) {
+ fail();
+ }
+ try(Stream<String> stream = Files.lines(Paths.get("src/test/resources/three/shard-manager.json"))) {
+ shardManagerBody = stream.collect(Collectors.joining());
+ } catch(IOException e) {
+ fail();
+ }
+ try(Stream<String> stream = Files.lines(Paths.get("src/test/resources/three/default-config.json"))) {
+ shardDefaultBody = stream.collect(Collectors.joining());
+ } catch(IOException e) {
+ fail();
+ }
+ try(Stream<String> stream = Files.lines(Paths.get("src/test/resources/three/default-operational.json"))) {
+ shardOperationalBody = stream.collect(Collectors.joining());
+ } catch(IOException e) {
+ fail();
+ }
+
+ if(clusterBody == null || shardManagerBody == null || shardDefaultBody == null || shardOperationalBody == null) {
+ fail();
+ }
+ stubFor(get(urlEqualTo("/jolokia/read/akka:type=Cluster")).willReturn(aResponse().withStatus(200).withBody(clusterBody)));
+ stubFor(get(urlEqualTo("/jolokia/read/org.opendaylight.controller:Category=ShardManager,name=shard-manager-config,type=DistributedConfigDatastore")).inScenario("testing").willReturn(aResponse().withStatus(200).withBody(shardManagerBody)).willSetStateTo("next"));
+ stubFor(get(urlEqualTo("/jolokia/read/org.opendaylight.controller:Category=Shards,name=member-1-shard-default-config,type=DistributedConfigDatastore")).inScenario("testing").willReturn(aResponse().withStatus(200).withBody(shardDefaultBody)).willSetStateTo("next"));
+ stubFor(get(urlEqualTo("/jolokia/read/org.opendaylight.controller:Category=Shards,name=member-1-shard-default-operational,type=DistributedOperationalDatastore")).willReturn(aResponse().withStatus(200).withBody(shardOperationalBody)));
+ }
+
+ @Test
+ public void getSiteHealth() {
+ stubController();
+ stubFor(get(urlEqualTo("/adm/healthcheck")).willReturn(aResponse().withStatus(200)));
+ try {
+ when(connection.isReadOnly()).thenReturn(false);
+ when(connection.isClosed()).thenReturn(false);
+ when(dbLibService.isActive()).thenReturn(true);
+ when(dbLibService.getConnection()).thenReturn(connection);
+ } catch(SQLException e) {
+ fail();
+ }
+ List<SiteHealth> health = resolver.getSiteHealth();
+ assertNotNull(health);
+ assertNotEquals(0, health.size());
+ assertEquals(1, health.size());
+ assertEquals(Health.HEALTHY, health.get(0).getHealth());
+ }
+
+ @Test
+ public void getSiteHealthFaulty() {
+ stubController();
+ stubFor(get(urlEqualTo("/adm/healthcheck")).willReturn(aResponse().withStatus(200)));
+ try {
+ when(connection.isReadOnly()).thenReturn(false);
+ when(connection.isClosed()).thenReturn(false);
+ when(dbLibService.isActive()).thenReturn(true);
+ when(dbLibService.getConnection()).thenReturn(connection);
+ } catch(SQLException e) {
+ fail();
+ }
+ stubFor(get(urlEqualTo("/jolokia/read/org.opendaylight.controller:Category=ShardManager,name=shard-manager-config,type=DistributedConfigDatastore")).inScenario("testing").whenScenarioStateIs("next").willReturn(aResponse().withBodyFile("nonexistent")));
+ List<SiteHealth> health = resolver.getSiteHealth();
+ assertNotNull(health);
+ assertNotEquals(0, health.size());
+ assertEquals(1, health.size());
+ assertEquals(Health.FAULTY, health.get(0).getHealth());
+ }
+
+ @Test
+ public void getSiteHealthFaultyShard() {
+ stubController();
+ stubFor(get(urlEqualTo("/adm/healthcheck")).willReturn(aResponse().withStatus(200)));
+ try {
+ when(connection.isReadOnly()).thenReturn(false);
+ when(connection.isClosed()).thenReturn(false);
+ when(dbLibService.isActive()).thenReturn(true);
+ when(dbLibService.getConnection()).thenReturn(connection);
+ } catch(SQLException e) {
+ fail();
+ }
+ stubFor(get(urlEqualTo("/jolokia/read/org.opendaylight.controller:Category=Shards,name=member-1-shard-default-config,type=DistributedConfigDatastore")).inScenario("testing").willReturn(aResponse().withBodyFile("nonexistent")).willSetStateTo("next"));
+ List<SiteHealth> health = resolver.getSiteHealth();
+ assertNotNull(health);
+ assertNotEquals(0, health.size());
+ assertEquals(1, health.size());
+ assertEquals(Health.HEALTHY, health.get(0).getHealth());
+ }
+
+ @Test
+ public void getSiteHealthFaultyCluster() {
+ stubController();
+ stubFor(get(urlEqualTo("/adm/healthcheck")).willReturn(aResponse().withStatus(200)));
+ try {
+ when(connection.isReadOnly()).thenReturn(false);
+ when(connection.isClosed()).thenReturn(false);
+ when(dbLibService.isActive()).thenReturn(true);
+ when(dbLibService.getConnection()).thenReturn(connection);
+ } catch(SQLException e) {
+ fail();
+ }
+ stubFor(get(urlEqualTo("/jolokia/read/akka:type=Cluster")).willReturn(aResponse().withStatus(200).withBodyFile("nonexistent")));
+ List<SiteHealth> health = resolver.getSiteHealth();
+ assertNotNull(health);
+ assertNotEquals(0, health.size());
+ assertEquals(1, health.size());
+ assertEquals(Health.FAULTY, health.get(0).getHealth());
+ }
+
+ @Test
+ public void getSiteHealthFaultyAdmin() {
+ stubController();
+ stubFor(get(urlEqualTo("/adm/healthcheck")).willReturn(aResponse().withStatus(400)));
+ try {
+ when(connection.isReadOnly()).thenReturn(false);
+ when(connection.isClosed()).thenReturn(false);
+ when(dbLibService.isActive()).thenReturn(true);
+ when(dbLibService.getConnection()).thenReturn(connection);
+ } catch(SQLException e) {
+ fail();
+ }
+ List<SiteHealth> health = resolver.getSiteHealth();
+ assertNotNull(health);
+ assertNotEquals(0, health.size());
+ assertEquals(1, health.size());
+ assertEquals(Health.FAULTY, health.get(0).getHealth());
+ }
+
+ @Test
+ public void tryFailover() {
+ FailoverStatus status = resolver.tryFailover(null);
+ assertEquals(400, status.getStatusCode());
+ }
+} \ No newline at end of file
diff --git a/plugins/grToolkit/provider/src/test/resources/akka.conf b/plugins/grToolkit/provider/src/test/resources/akka.conf
new file mode 100644
index 000000000..ce46748ec
--- /dev/null
+++ b/plugins/grToolkit/provider/src/test/resources/akka.conf
@@ -0,0 +1,67 @@
+# ============LICENSE_START=======================================================
+# openECOMP : SDN-C
+# ================================================================================
+# Copyright (C) 2019 AT&T Intellectual Property. All rights
+# reserved.
+# ================================================================================
+# 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.
+# ============LICENSE_END=========================================================
+
+odl-cluster-data {
+ akka {
+ remote {
+ artery {
+ enabled = off
+ canonical.hostname = "127.0.0.1"
+ canonical.port = 2550
+ }
+ netty.tcp {
+ hostname = "127.0.0.1"
+ port = 2550
+ }
+ # when under load we might trip a false positive on the failure detector
+ # transport-failure-detector {
+ # heartbeat-interval = 4 s
+ # acceptable-heartbeat-pause = 16s
+ # }
+ }
+
+ cluster {
+ # Remove ".tcp" when using artery.
+ seed-nodes = ["akka.tcp://opendaylight-cluster-data@127.0.1.1:2550"]
+
+ roles = [
+ "member-1"
+ ]
+
+ }
+
+ persistence {
+ # By default the snapshots/journal directories live in KARAF_HOME. You can choose to put it somewhere else by
+ # modifying the following two properties. The directory location specified may be a relative or absolute path.
+ # The relative path is always relative to KARAF_HOME.
+
+ # snapshot-store.local.dir = "target/snapshots"
+ # journal.leveldb.dir = "target/journal"
+
+ journal {
+ leveldb {
+ # Set native = off to use a Java-only implementation of leveldb.
+ # Note that the Java-only version is not currently considered by Akka to be production quality.
+
+ # native = off
+ }
+ }
+ }
+ }
+}
diff --git a/plugins/grToolkit/provider/src/test/resources/gr-toolkit.properties b/plugins/grToolkit/provider/src/test/resources/gr-toolkit.properties
new file mode 100755
index 000000000..52b19bf51
--- /dev/null
+++ b/plugins/grToolkit/provider/src/test/resources/gr-toolkit.properties
@@ -0,0 +1,35 @@
+# ============LICENSE_START=======================================================
+# openECOMP : SDN-C
+# ================================================================================
+# Copyright (C) 2019 AT&T Intellectual Property. All rights
+# reserved.
+# ================================================================================
+# 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.
+# ============LICENSE_END=========================================================
+
+resolver=org.onap.ccsdk.sli.plugins.grtoolkit.resolver.SingleNodeHealthResolver
+akka.conf.location=src/test/resources/akka.conf
+adm.useSsl=false
+adm.fqdn=localhost
+adm.healthcheck=/adm/healthcheck
+adm.port.http=9999
+adm.port.ssl=19999
+controller.credentials=admin:admin
+controller.useSsl=false
+controller.port.http=9999
+controller.port.ssl=19999
+controller.port.akka=2550
+mbean.cluster=/jolokia/read/akka:type=Cluster
+mbean.shardManager=/jolokia/read/org.opendaylight.controller:Category=ShardManager,name=shard-manager-config,type=DistributedConfigDatastore
+mbean.shard.config=/jolokia/read/org.opendaylight.controller:Category=Shards,name=%s,type=DistributedConfigDatastore
+#site.identifier=TestODL
diff --git a/plugins/grToolkit/provider/src/test/resources/single/akka.conf b/plugins/grToolkit/provider/src/test/resources/single/akka.conf
new file mode 100644
index 000000000..ce46748ec
--- /dev/null
+++ b/plugins/grToolkit/provider/src/test/resources/single/akka.conf
@@ -0,0 +1,67 @@
+# ============LICENSE_START=======================================================
+# openECOMP : SDN-C
+# ================================================================================
+# Copyright (C) 2019 AT&T Intellectual Property. All rights
+# reserved.
+# ================================================================================
+# 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.
+# ============LICENSE_END=========================================================
+
+odl-cluster-data {
+ akka {
+ remote {
+ artery {
+ enabled = off
+ canonical.hostname = "127.0.0.1"
+ canonical.port = 2550
+ }
+ netty.tcp {
+ hostname = "127.0.0.1"
+ port = 2550
+ }
+ # when under load we might trip a false positive on the failure detector
+ # transport-failure-detector {
+ # heartbeat-interval = 4 s
+ # acceptable-heartbeat-pause = 16s
+ # }
+ }
+
+ cluster {
+ # Remove ".tcp" when using artery.
+ seed-nodes = ["akka.tcp://opendaylight-cluster-data@127.0.1.1:2550"]
+
+ roles = [
+ "member-1"
+ ]
+
+ }
+
+ persistence {
+ # By default the snapshots/journal directories live in KARAF_HOME. You can choose to put it somewhere else by
+ # modifying the following two properties. The directory location specified may be a relative or absolute path.
+ # The relative path is always relative to KARAF_HOME.
+
+ # snapshot-store.local.dir = "target/snapshots"
+ # journal.leveldb.dir = "target/journal"
+
+ journal {
+ leveldb {
+ # Set native = off to use a Java-only implementation of leveldb.
+ # Note that the Java-only version is not currently considered by Akka to be production quality.
+
+ # native = off
+ }
+ }
+ }
+ }
+}
diff --git a/plugins/grToolkit/provider/src/test/resources/single/cluster.json b/plugins/grToolkit/provider/src/test/resources/single/cluster.json
new file mode 100644
index 000000000..93360845f
--- /dev/null
+++ b/plugins/grToolkit/provider/src/test/resources/single/cluster.json
@@ -0,0 +1,17 @@
+{
+ "request": {
+ "mbean": "akka:type=Cluster",
+ "type": "read"
+ },
+ "value": {
+ "Leader": "akka.tcp://opendaylight-cluster-data@localhost:2550",
+ "Unreachable": "",
+ "Singleton": true,
+ "Available": true,
+ "MemberStatus": "Up",
+ "ClusterStatus": "{\n \"members\": [\n {\n \"address\": \"akka.tcp://opendaylight-cluster-data@localhost:2550\",\n \"roles\": [\n \"dc-default\",\n \"member-1\"\n ],\n \"status\": \"Up\"\n }\n ],\n \"self-address\": \"akka.tcp://opendaylight-cluster-data@localhost:2550\",\n \"unreachable\": []\n}\n",
+ "Members": "akka.tcp://opendaylight-cluster-data@localhost:2550"
+ },
+ "timestamp": 1575393881,
+ "status": 200
+}
diff --git a/plugins/grToolkit/provider/src/test/resources/single/default-config.json b/plugins/grToolkit/provider/src/test/resources/single/default-config.json
new file mode 100644
index 000000000..d75998e5d
--- /dev/null
+++ b/plugins/grToolkit/provider/src/test/resources/single/default-config.json
@@ -0,0 +1,46 @@
+{
+ "request": {
+ "mbean": "org.opendaylight.controller:Category=Shards,name=member-1-shard-default-config,type=DistributedConfigDatastore",
+ "type": "read"
+ },
+ "value": {
+ "ReadWriteTransactionCount": 0,
+ "SnapshotIndex": 22,
+ "InMemoryJournalLogSize": 1,
+ "ReplicatedToAllIndex": -1,
+ "Leader": "member-1-shard-default-config",
+ "LastIndex": 23,
+ "RaftState": "Leader",
+ "LastCommittedTransactionTime": "2019-12-03 16:36:39.413",
+ "LastApplied": 23,
+ "PeerAddresses": "",
+ "LastLogIndex": 23,
+ "LastLeadershipChangeTime": "2019-12-03 16:36:33.460",
+ "WriteOnlyTransactionCount": 0,
+ "FollowerInitialSyncStatus": false,
+ "FollowerInfo": [],
+ "FailedReadTransactionsCount": 0,
+ "Voting": true,
+ "StatRetrievalTime": "454.8 μs",
+ "CurrentTerm": 4,
+ "LastTerm": 4,
+ "FailedTransactionsCount": 0,
+ "PendingTxCommitQueueSize": 0,
+ "VotedFor": "member-1-shard-default-config",
+ "SnapshotCaptureInitiated": false,
+ "CommittedTransactionsCount": 5,
+ "TxCohortCacheSize": 0,
+ "PeerVotingStates": "",
+ "LastLogTerm": 4,
+ "StatRetrievalError": null,
+ "CommitIndex": 23,
+ "SnapshotTerm": 4,
+ "AbortTransactionsCount": 0,
+ "ReadOnlyTransactionCount": 0,
+ "ShardName": "member-1-shard-default-config",
+ "LeadershipChangeCount": 1,
+ "InMemoryJournalDataSize": 37
+ },
+ "timestamp": 1575393787,
+ "status": 200
+} \ No newline at end of file
diff --git a/plugins/grToolkit/provider/src/test/resources/single/default-operational.json b/plugins/grToolkit/provider/src/test/resources/single/default-operational.json
new file mode 100644
index 000000000..88a5d2c96
--- /dev/null
+++ b/plugins/grToolkit/provider/src/test/resources/single/default-operational.json
@@ -0,0 +1,46 @@
+{
+ "request": {
+ "mbean": "org.opendaylight.controller:Category=Shards,name=member-1-shard-default-operational,type=DistributedOperationalDatastore",
+ "type": "read"
+ },
+ "value": {
+ "ReadWriteTransactionCount": 0,
+ "SnapshotIndex": 22,
+ "InMemoryJournalLogSize": 1,
+ "ReplicatedToAllIndex": -1,
+ "Leader": "member-1-shard-default-operational",
+ "LastIndex": 23,
+ "RaftState": "Leader",
+ "LastCommittedTransactionTime": "2019-12-03 16:36:39.413",
+ "LastApplied": 23,
+ "PeerAddresses": "",
+ "LastLogIndex": 23,
+ "LastLeadershipChangeTime": "2019-12-03 16:36:33.460",
+ "WriteOnlyTransactionCount": 0,
+ "FollowerInitialSyncStatus": false,
+ "FollowerInfo": [],
+ "FailedReadTransactionsCount": 0,
+ "Voting": true,
+ "StatRetrievalTime": "454.8 μs",
+ "CurrentTerm": 4,
+ "LastTerm": 4,
+ "FailedTransactionsCount": 0,
+ "PendingTxCommitQueueSize": 0,
+ "VotedFor": "member-1-shard-default-operational",
+ "SnapshotCaptureInitiated": false,
+ "CommittedTransactionsCount": 5,
+ "TxCohortCacheSize": 0,
+ "PeerVotingStates": "",
+ "LastLogTerm": 4,
+ "StatRetrievalError": null,
+ "CommitIndex": 23,
+ "SnapshotTerm": 4,
+ "AbortTransactionsCount": 0,
+ "ReadOnlyTransactionCount": 0,
+ "ShardName": "member-1-shard-default-operational",
+ "LeadershipChangeCount": 1,
+ "InMemoryJournalDataSize": 37
+ },
+ "timestamp": 1575393787,
+ "status": 200
+} \ No newline at end of file
diff --git a/plugins/grToolkit/provider/src/test/resources/single/gr-toolkit.properties b/plugins/grToolkit/provider/src/test/resources/single/gr-toolkit.properties
new file mode 100755
index 000000000..cc7820e90
--- /dev/null
+++ b/plugins/grToolkit/provider/src/test/resources/single/gr-toolkit.properties
@@ -0,0 +1,34 @@
+# ============LICENSE_START=======================================================
+# openECOMP : SDN-C
+# ================================================================================
+# Copyright (C) 2019 AT&T Intellectual Property. All rights
+# reserved.
+# ================================================================================
+# 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.
+# ============LICENSE_END=========================================================
+
+akka.conf.location=src/test/resources/single/akka.conf
+adm.useSsl=false
+adm.fqdn=localhost
+adm.healthcheck=/adm/healthcheck
+adm.port.http=9999
+adm.port.ssl=19999
+controller.credentials=admin:admin
+controller.useSsl=false
+controller.port.http=9999
+controller.port.ssl=19999
+controller.port.akka=2550
+mbean.cluster=/jolokia/read/akka:type=Cluster
+mbean.shardManager=/jolokia/read/org.opendaylight.controller:Category=ShardManager,name=shard-manager-config,type=DistributedConfigDatastore
+mbean.shard.config=/jolokia/read/org.opendaylight.controller:Category=Shards,name=%s,type=DistributedConfigDatastore
+site.identifier=TestODL
diff --git a/plugins/grToolkit/provider/src/test/resources/single/shard-manager.json b/plugins/grToolkit/provider/src/test/resources/single/shard-manager.json
new file mode 100644
index 000000000..301184ef8
--- /dev/null
+++ b/plugins/grToolkit/provider/src/test/resources/single/shard-manager.json
@@ -0,0 +1,15 @@
+{
+ "request": {
+ "mbean": "org.opendaylight.controller:Category=ShardManager,name=shard-manager-config,type=DistributedConfigDatastore",
+ "type": "read"
+ },
+ "value": {
+ "LocalShards": [
+ "member-1-shard-default-config"
+ ],
+ "SyncStatus": true,
+ "MemberName": "member-1"
+ },
+ "timestamp": 1575393918,
+ "status": 200
+} \ No newline at end of file
diff --git a/plugins/grToolkit/provider/src/test/resources/six/akka.conf b/plugins/grToolkit/provider/src/test/resources/six/akka.conf
new file mode 100644
index 000000000..9bda35d68
--- /dev/null
+++ b/plugins/grToolkit/provider/src/test/resources/six/akka.conf
@@ -0,0 +1,67 @@
+# ============LICENSE_START=======================================================
+# openECOMP : SDN-C
+# ================================================================================
+# Copyright (C) 2019 AT&T Intellectual Property. All rights
+# reserved.
+# ================================================================================
+# 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.
+# ============LICENSE_END=========================================================
+
+odl-cluster-data {
+ akka {
+ remote {
+ artery {
+ enabled = off
+ canonical.hostname = "127.0.0.1"
+ canonical.port = 2550
+ }
+ netty.tcp {
+ hostname = "127.0.0.1"
+ port = 2550
+ }
+ # when under load we might trip a false positive on the failure detector
+ # transport-failure-detector {
+ # heartbeat-interval = 4 s
+ # acceptable-heartbeat-pause = 16s
+ # }
+ }
+
+ cluster {
+ # Remove ".tcp" when using artery.
+ seed-nodes = ["akka.tcp://opendaylight-cluster-data@127.0.0.1:2550", "akka.tcp://opendaylight-cluster-data@127.0.0.2:2550", "akka.tcp://opendaylight-cluster-data@127.0.0.3:2550", "akka.tcp://opendaylight-cluster-data@127.0.0.4:2550", "akka.tcp://opendaylight-cluster-data@127.0.0.5:2550", "akka.tcp://opendaylight-cluster-data@127.0.0.6:2550"]
+
+ roles = [
+ "member-1"
+ ]
+
+ }
+
+ persistence {
+ # By default the snapshots/journal directories live in KARAF_HOME. You can choose to put it somewhere else by
+ # modifying the following two properties. The directory location specified may be a relative or absolute path.
+ # The relative path is always relative to KARAF_HOME.
+
+ # snapshot-store.local.dir = "target/snapshots"
+ # journal.leveldb.dir = "target/journal"
+
+ journal {
+ leveldb {
+ # Set native = off to use a Java-only implementation of leveldb.
+ # Note that the Java-only version is not currently considered by Akka to be production quality.
+
+ # native = off
+ }
+ }
+ }
+ }
+}
diff --git a/plugins/grToolkit/provider/src/test/resources/six/cluster.json b/plugins/grToolkit/provider/src/test/resources/six/cluster.json
new file mode 100644
index 000000000..d6a54c8c8
--- /dev/null
+++ b/plugins/grToolkit/provider/src/test/resources/six/cluster.json
@@ -0,0 +1,17 @@
+{
+ "request": {
+ "mbean": "akka:type=Cluster",
+ "type": "read"
+ },
+ "value": {
+ "Leader": "akka.tcp://opendaylight-cluster-data@localhost:2550",
+ "Unreachable": "",
+ "Singleton": true,
+ "Available": true,
+ "MemberStatus": "Up",
+ "ClusterStatus": "{\n \"members\": [\n {\n \"address\": \"akka.tcp://opendaylight-cluster-data@localhost:2550\",\n \"roles\": [\n \"dc-default\",\n \"member-1\"\n ],\n \"status\": \"Up\"\n },\n {\n \"address\": \"akka.tcp://opendaylight-cluster-data@localhost:2550\",\n \"roles\": [\n \"dc-default\",\n \"member-2\"\n ],\n \"status\": \"Up\"\n },\n {\n \"address\": \"akka.tcp://opendaylight-cluster-data@localhost:2550\",\n \"roles\": [\n \"dc-default\",\n \"member-3\"\n ],\n \"status\": \"Up\"\n }\n ],\n \"self-address\": \"akka.tcp://opendaylight-cluster-data@localhost:2550\",\n \"unreachable\": []\n}\n",
+ "Members": "akka.tcp://opendaylight-cluster-data@localhost:2550"
+ },
+ "timestamp": 1575393881,
+ "status": 200
+} \ No newline at end of file
diff --git a/plugins/grToolkit/provider/src/test/resources/six/component-health.json b/plugins/grToolkit/provider/src/test/resources/six/component-health.json
new file mode 100644
index 000000000..1ca01da42
--- /dev/null
+++ b/plugins/grToolkit/provider/src/test/resources/six/component-health.json
@@ -0,0 +1,7 @@
+{
+ "output": {
+ "status": "200",
+ "served-by": "member-2",
+ "health": "HEALTHY"
+ }
+}
diff --git a/plugins/grToolkit/provider/src/test/resources/six/default-config.json b/plugins/grToolkit/provider/src/test/resources/six/default-config.json
new file mode 100644
index 000000000..d75998e5d
--- /dev/null
+++ b/plugins/grToolkit/provider/src/test/resources/six/default-config.json
@@ -0,0 +1,46 @@
+{
+ "request": {
+ "mbean": "org.opendaylight.controller:Category=Shards,name=member-1-shard-default-config,type=DistributedConfigDatastore",
+ "type": "read"
+ },
+ "value": {
+ "ReadWriteTransactionCount": 0,
+ "SnapshotIndex": 22,
+ "InMemoryJournalLogSize": 1,
+ "ReplicatedToAllIndex": -1,
+ "Leader": "member-1-shard-default-config",
+ "LastIndex": 23,
+ "RaftState": "Leader",
+ "LastCommittedTransactionTime": "2019-12-03 16:36:39.413",
+ "LastApplied": 23,
+ "PeerAddresses": "",
+ "LastLogIndex": 23,
+ "LastLeadershipChangeTime": "2019-12-03 16:36:33.460",
+ "WriteOnlyTransactionCount": 0,
+ "FollowerInitialSyncStatus": false,
+ "FollowerInfo": [],
+ "FailedReadTransactionsCount": 0,
+ "Voting": true,
+ "StatRetrievalTime": "454.8 μs",
+ "CurrentTerm": 4,
+ "LastTerm": 4,
+ "FailedTransactionsCount": 0,
+ "PendingTxCommitQueueSize": 0,
+ "VotedFor": "member-1-shard-default-config",
+ "SnapshotCaptureInitiated": false,
+ "CommittedTransactionsCount": 5,
+ "TxCohortCacheSize": 0,
+ "PeerVotingStates": "",
+ "LastLogTerm": 4,
+ "StatRetrievalError": null,
+ "CommitIndex": 23,
+ "SnapshotTerm": 4,
+ "AbortTransactionsCount": 0,
+ "ReadOnlyTransactionCount": 0,
+ "ShardName": "member-1-shard-default-config",
+ "LeadershipChangeCount": 1,
+ "InMemoryJournalDataSize": 37
+ },
+ "timestamp": 1575393787,
+ "status": 200
+} \ No newline at end of file
diff --git a/plugins/grToolkit/provider/src/test/resources/six/default-operational.json b/plugins/grToolkit/provider/src/test/resources/six/default-operational.json
new file mode 100644
index 000000000..88a5d2c96
--- /dev/null
+++ b/plugins/grToolkit/provider/src/test/resources/six/default-operational.json
@@ -0,0 +1,46 @@
+{
+ "request": {
+ "mbean": "org.opendaylight.controller:Category=Shards,name=member-1-shard-default-operational,type=DistributedOperationalDatastore",
+ "type": "read"
+ },
+ "value": {
+ "ReadWriteTransactionCount": 0,
+ "SnapshotIndex": 22,
+ "InMemoryJournalLogSize": 1,
+ "ReplicatedToAllIndex": -1,
+ "Leader": "member-1-shard-default-operational",
+ "LastIndex": 23,
+ "RaftState": "Leader",
+ "LastCommittedTransactionTime": "2019-12-03 16:36:39.413",
+ "LastApplied": 23,
+ "PeerAddresses": "",
+ "LastLogIndex": 23,
+ "LastLeadershipChangeTime": "2019-12-03 16:36:33.460",
+ "WriteOnlyTransactionCount": 0,
+ "FollowerInitialSyncStatus": false,
+ "FollowerInfo": [],
+ "FailedReadTransactionsCount": 0,
+ "Voting": true,
+ "StatRetrievalTime": "454.8 μs",
+ "CurrentTerm": 4,
+ "LastTerm": 4,
+ "FailedTransactionsCount": 0,
+ "PendingTxCommitQueueSize": 0,
+ "VotedFor": "member-1-shard-default-operational",
+ "SnapshotCaptureInitiated": false,
+ "CommittedTransactionsCount": 5,
+ "TxCohortCacheSize": 0,
+ "PeerVotingStates": "",
+ "LastLogTerm": 4,
+ "StatRetrievalError": null,
+ "CommitIndex": 23,
+ "SnapshotTerm": 4,
+ "AbortTransactionsCount": 0,
+ "ReadOnlyTransactionCount": 0,
+ "ShardName": "member-1-shard-default-operational",
+ "LeadershipChangeCount": 1,
+ "InMemoryJournalDataSize": 37
+ },
+ "timestamp": 1575393787,
+ "status": 200
+} \ No newline at end of file
diff --git a/plugins/grToolkit/provider/src/test/resources/six/gr-toolkit.properties b/plugins/grToolkit/provider/src/test/resources/six/gr-toolkit.properties
new file mode 100755
index 000000000..54c9af742
--- /dev/null
+++ b/plugins/grToolkit/provider/src/test/resources/six/gr-toolkit.properties
@@ -0,0 +1,34 @@
+# ============LICENSE_START=======================================================
+# openECOMP : SDN-C
+# ================================================================================
+# Copyright (C) 2019 AT&T Intellectual Property. All rights
+# reserved.
+# ================================================================================
+# 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.
+# ============LICENSE_END=========================================================
+
+akka.conf.location=src/test/resources/six/akka.conf
+adm.useSsl=false
+adm.fqdn=localhost
+adm.healthcheck=/adm/healthcheck
+adm.port.http=9999
+adm.port.ssl=19999
+controller.credentials=admin:admin
+controller.useSsl=false
+controller.port.http=9999
+controller.port.ssl=19999
+controller.port.akka=2550
+mbean.cluster=/jolokia/read/akka:type=Cluster
+mbean.shardManager=/jolokia/read/org.opendaylight.controller:Category=ShardManager,name=shard-manager-config,type=DistributedConfigDatastore
+mbean.shard.config=/jolokia/read/org.opendaylight.controller:Category=Shards,name=%s,type=DistributedConfigDatastore
+site.identifier=TestODL
diff --git a/plugins/grToolkit/provider/src/test/resources/six/shard-manager.json b/plugins/grToolkit/provider/src/test/resources/six/shard-manager.json
new file mode 100644
index 000000000..301184ef8
--- /dev/null
+++ b/plugins/grToolkit/provider/src/test/resources/six/shard-manager.json
@@ -0,0 +1,15 @@
+{
+ "request": {
+ "mbean": "org.opendaylight.controller:Category=ShardManager,name=shard-manager-config,type=DistributedConfigDatastore",
+ "type": "read"
+ },
+ "value": {
+ "LocalShards": [
+ "member-1-shard-default-config"
+ ],
+ "SyncStatus": true,
+ "MemberName": "member-1"
+ },
+ "timestamp": 1575393918,
+ "status": 200
+} \ No newline at end of file
diff --git a/plugins/grToolkit/provider/src/test/resources/six/site-identifier.json b/plugins/grToolkit/provider/src/test/resources/six/site-identifier.json
new file mode 100644
index 000000000..7599ceb15
--- /dev/null
+++ b/plugins/grToolkit/provider/src/test/resources/six/site-identifier.json
@@ -0,0 +1,7 @@
+{
+ "output": {
+ "status": "200",
+ "id": "test-site",
+ "served-by": "member-1"
+ }
+}
diff --git a/plugins/grToolkit/provider/src/test/resources/three/akka.conf b/plugins/grToolkit/provider/src/test/resources/three/akka.conf
new file mode 100644
index 000000000..a6c151dd1
--- /dev/null
+++ b/plugins/grToolkit/provider/src/test/resources/three/akka.conf
@@ -0,0 +1,67 @@
+# ============LICENSE_START=======================================================
+# openECOMP : SDN-C
+# ================================================================================
+# Copyright (C) 2019 AT&T Intellectual Property. All rights
+# reserved.
+# ================================================================================
+# 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.
+# ============LICENSE_END=========================================================
+
+odl-cluster-data {
+ akka {
+ remote {
+ artery {
+ enabled = off
+ canonical.hostname = "127.0.0.1"
+ canonical.port = 2550
+ }
+ netty.tcp {
+ hostname = "127.0.0.1"
+ port = 2550
+ }
+ # when under load we might trip a false positive on the failure detector
+ # transport-failure-detector {
+ # heartbeat-interval = 4 s
+ # acceptable-heartbeat-pause = 16s
+ # }
+ }
+
+ cluster {
+ # Remove ".tcp" when using artery.
+ seed-nodes = ["akka.tcp://opendaylight-cluster-data@127.0.0.1:2550", "akka.tcp://opendaylight-cluster-data@127.0.0.2:2550", "akka.tcp://opendaylight-cluster-data@127.0.0.3:2550"]
+
+ roles = [
+ "member-1"
+ ]
+
+ }
+
+ persistence {
+ # By default the snapshots/journal directories live in KARAF_HOME. You can choose to put it somewhere else by
+ # modifying the following two properties. The directory location specified may be a relative or absolute path.
+ # The relative path is always relative to KARAF_HOME.
+
+ # snapshot-store.local.dir = "target/snapshots"
+ # journal.leveldb.dir = "target/journal"
+
+ journal {
+ leveldb {
+ # Set native = off to use a Java-only implementation of leveldb.
+ # Note that the Java-only version is not currently considered by Akka to be production quality.
+
+ # native = off
+ }
+ }
+ }
+ }
+}
diff --git a/plugins/grToolkit/provider/src/test/resources/three/cluster.json b/plugins/grToolkit/provider/src/test/resources/three/cluster.json
new file mode 100644
index 000000000..d6a54c8c8
--- /dev/null
+++ b/plugins/grToolkit/provider/src/test/resources/three/cluster.json
@@ -0,0 +1,17 @@
+{
+ "request": {
+ "mbean": "akka:type=Cluster",
+ "type": "read"
+ },
+ "value": {
+ "Leader": "akka.tcp://opendaylight-cluster-data@localhost:2550",
+ "Unreachable": "",
+ "Singleton": true,
+ "Available": true,
+ "MemberStatus": "Up",
+ "ClusterStatus": "{\n \"members\": [\n {\n \"address\": \"akka.tcp://opendaylight-cluster-data@localhost:2550\",\n \"roles\": [\n \"dc-default\",\n \"member-1\"\n ],\n \"status\": \"Up\"\n },\n {\n \"address\": \"akka.tcp://opendaylight-cluster-data@localhost:2550\",\n \"roles\": [\n \"dc-default\",\n \"member-2\"\n ],\n \"status\": \"Up\"\n },\n {\n \"address\": \"akka.tcp://opendaylight-cluster-data@localhost:2550\",\n \"roles\": [\n \"dc-default\",\n \"member-3\"\n ],\n \"status\": \"Up\"\n }\n ],\n \"self-address\": \"akka.tcp://opendaylight-cluster-data@localhost:2550\",\n \"unreachable\": []\n}\n",
+ "Members": "akka.tcp://opendaylight-cluster-data@localhost:2550"
+ },
+ "timestamp": 1575393881,
+ "status": 200
+} \ No newline at end of file
diff --git a/plugins/grToolkit/provider/src/test/resources/three/default-config.json b/plugins/grToolkit/provider/src/test/resources/three/default-config.json
new file mode 100644
index 000000000..d75998e5d
--- /dev/null
+++ b/plugins/grToolkit/provider/src/test/resources/three/default-config.json
@@ -0,0 +1,46 @@
+{
+ "request": {
+ "mbean": "org.opendaylight.controller:Category=Shards,name=member-1-shard-default-config,type=DistributedConfigDatastore",
+ "type": "read"
+ },
+ "value": {
+ "ReadWriteTransactionCount": 0,
+ "SnapshotIndex": 22,
+ "InMemoryJournalLogSize": 1,
+ "ReplicatedToAllIndex": -1,
+ "Leader": "member-1-shard-default-config",
+ "LastIndex": 23,
+ "RaftState": "Leader",
+ "LastCommittedTransactionTime": "2019-12-03 16:36:39.413",
+ "LastApplied": 23,
+ "PeerAddresses": "",
+ "LastLogIndex": 23,
+ "LastLeadershipChangeTime": "2019-12-03 16:36:33.460",
+ "WriteOnlyTransactionCount": 0,
+ "FollowerInitialSyncStatus": false,
+ "FollowerInfo": [],
+ "FailedReadTransactionsCount": 0,
+ "Voting": true,
+ "StatRetrievalTime": "454.8 μs",
+ "CurrentTerm": 4,
+ "LastTerm": 4,
+ "FailedTransactionsCount": 0,
+ "PendingTxCommitQueueSize": 0,
+ "VotedFor": "member-1-shard-default-config",
+ "SnapshotCaptureInitiated": false,
+ "CommittedTransactionsCount": 5,
+ "TxCohortCacheSize": 0,
+ "PeerVotingStates": "",
+ "LastLogTerm": 4,
+ "StatRetrievalError": null,
+ "CommitIndex": 23,
+ "SnapshotTerm": 4,
+ "AbortTransactionsCount": 0,
+ "ReadOnlyTransactionCount": 0,
+ "ShardName": "member-1-shard-default-config",
+ "LeadershipChangeCount": 1,
+ "InMemoryJournalDataSize": 37
+ },
+ "timestamp": 1575393787,
+ "status": 200
+} \ No newline at end of file
diff --git a/plugins/grToolkit/provider/src/test/resources/three/default-operational.json b/plugins/grToolkit/provider/src/test/resources/three/default-operational.json
new file mode 100644
index 000000000..88a5d2c96
--- /dev/null
+++ b/plugins/grToolkit/provider/src/test/resources/three/default-operational.json
@@ -0,0 +1,46 @@
+{
+ "request": {
+ "mbean": "org.opendaylight.controller:Category=Shards,name=member-1-shard-default-operational,type=DistributedOperationalDatastore",
+ "type": "read"
+ },
+ "value": {
+ "ReadWriteTransactionCount": 0,
+ "SnapshotIndex": 22,
+ "InMemoryJournalLogSize": 1,
+ "ReplicatedToAllIndex": -1,
+ "Leader": "member-1-shard-default-operational",
+ "LastIndex": 23,
+ "RaftState": "Leader",
+ "LastCommittedTransactionTime": "2019-12-03 16:36:39.413",
+ "LastApplied": 23,
+ "PeerAddresses": "",
+ "LastLogIndex": 23,
+ "LastLeadershipChangeTime": "2019-12-03 16:36:33.460",
+ "WriteOnlyTransactionCount": 0,
+ "FollowerInitialSyncStatus": false,
+ "FollowerInfo": [],
+ "FailedReadTransactionsCount": 0,
+ "Voting": true,
+ "StatRetrievalTime": "454.8 μs",
+ "CurrentTerm": 4,
+ "LastTerm": 4,
+ "FailedTransactionsCount": 0,
+ "PendingTxCommitQueueSize": 0,
+ "VotedFor": "member-1-shard-default-operational",
+ "SnapshotCaptureInitiated": false,
+ "CommittedTransactionsCount": 5,
+ "TxCohortCacheSize": 0,
+ "PeerVotingStates": "",
+ "LastLogTerm": 4,
+ "StatRetrievalError": null,
+ "CommitIndex": 23,
+ "SnapshotTerm": 4,
+ "AbortTransactionsCount": 0,
+ "ReadOnlyTransactionCount": 0,
+ "ShardName": "member-1-shard-default-operational",
+ "LeadershipChangeCount": 1,
+ "InMemoryJournalDataSize": 37
+ },
+ "timestamp": 1575393787,
+ "status": 200
+} \ No newline at end of file
diff --git a/plugins/grToolkit/provider/src/test/resources/three/gr-toolkit.properties b/plugins/grToolkit/provider/src/test/resources/three/gr-toolkit.properties
new file mode 100755
index 000000000..cc7820e90
--- /dev/null
+++ b/plugins/grToolkit/provider/src/test/resources/three/gr-toolkit.properties
@@ -0,0 +1,34 @@
+# ============LICENSE_START=======================================================
+# openECOMP : SDN-C
+# ================================================================================
+# Copyright (C) 2019 AT&T Intellectual Property. All rights
+# reserved.
+# ================================================================================
+# 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.
+# ============LICENSE_END=========================================================
+
+akka.conf.location=src/test/resources/single/akka.conf
+adm.useSsl=false
+adm.fqdn=localhost
+adm.healthcheck=/adm/healthcheck
+adm.port.http=9999
+adm.port.ssl=19999
+controller.credentials=admin:admin
+controller.useSsl=false
+controller.port.http=9999
+controller.port.ssl=19999
+controller.port.akka=2550
+mbean.cluster=/jolokia/read/akka:type=Cluster
+mbean.shardManager=/jolokia/read/org.opendaylight.controller:Category=ShardManager,name=shard-manager-config,type=DistributedConfigDatastore
+mbean.shard.config=/jolokia/read/org.opendaylight.controller:Category=Shards,name=%s,type=DistributedConfigDatastore
+site.identifier=TestODL
diff --git a/plugins/grToolkit/provider/src/test/resources/three/shard-manager.json b/plugins/grToolkit/provider/src/test/resources/three/shard-manager.json
new file mode 100644
index 000000000..301184ef8
--- /dev/null
+++ b/plugins/grToolkit/provider/src/test/resources/three/shard-manager.json
@@ -0,0 +1,15 @@
+{
+ "request": {
+ "mbean": "org.opendaylight.controller:Category=ShardManager,name=shard-manager-config,type=DistributedConfigDatastore",
+ "type": "read"
+ },
+ "value": {
+ "LocalShards": [
+ "member-1-shard-default-config"
+ ],
+ "SyncStatus": true,
+ "MemberName": "member-1"
+ },
+ "timestamp": 1575393918,
+ "status": 200
+} \ No newline at end of file
diff --git a/plugins/properties-node/.gitignore b/plugins/properties-node/.gitignore
new file mode 100755
index 000000000..b73caf31e
--- /dev/null
+++ b/plugins/properties-node/.gitignore
@@ -0,0 +1,34 @@
+#####standard .git ignore entries#####
+
+## IDE Specific Files ##
+org.eclipse.core.resources.prefs
+.classpath
+.project
+.settings
+.idea
+.externalToolBuilders
+maven-eclipse.xml
+workspace
+
+## Compilation Files ##
+*.class
+**/target
+target
+target-ide
+MANIFEST.MF
+
+## Misc Ignores (OS specific etc) ##
+bin/
+dist
+*~
+*.ipr
+*.iml
+*.iws
+classes
+out/
+.DS_STORE
+.metadata
+
+## Folders which contain auto generated source code ##
+yang-gen-config
+yang-gen-sal
diff --git a/plugins/properties-node/installer/pom.xml b/plugins/properties-node/installer/pom.xml
new file mode 100755
index 000000000..4dc62faae
--- /dev/null
+++ b/plugins/properties-node/installer/pom.xml
@@ -0,0 +1,127 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>odlparent-lite</artifactId>
+ <version>2.1.0</version>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.plugins</groupId>
+ <artifactId>properties-node-installer</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>pom</packaging>
+
+ <name>ccsdk-sli-plugins :: properties-node :: ${project.artifactId}</name>
+
+ <properties>
+ <application.name>ccsdk-properties-node</application.name>
+ <features.boot>${application.name}</features.boot>
+ <features.repositories>mvn:org.onap.ccsdk.sli.plugins/${features.boot}/${project.version}/xml/features</features.repositories>
+ <include.transitive.dependencies>false</include.transitive.dependencies>
+ </properties>
+
+ <dependencies>
+
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.plugins</groupId>
+ <artifactId>properties-node-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <version>2.6</version>
+ <executions>
+ <execution>
+ <id>maven-repo-zip</id>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ <phase>package</phase>
+ <configuration>
+ <attach>true</attach>
+ <finalName>stage/${application.name}-${project.version}</finalName>
+ <descriptors>
+ <descriptor>src/assembly/assemble_mvnrepo_zip.xml</descriptor>
+ </descriptors>
+ <appendAssemblyId>true</appendAssemblyId>
+ </configuration>
+ </execution>
+ <execution>
+ <id>installer-zip</id>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ <phase>package</phase>
+ <configuration>
+ <attach>true</attach>
+ <finalName>${application.name}-${project.version}-installer</finalName>
+ <descriptors>
+ <descriptor>src/assembly/assemble_installer_zip.xml</descriptor>
+ </descriptors>
+ <appendAssemblyId>false</appendAssemblyId>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>copy-dependencies</id>
+ <goals>
+ <goal>copy-dependencies</goal>
+ </goals>
+ <phase>prepare-package</phase>
+ <configuration>
+ <transitive>false</transitive>
+ <outputDirectory>${project.build.directory}/assembly/system</outputDirectory>
+ <overWriteReleases>false</overWriteReleases>
+ <overWriteSnapshots>true</overWriteSnapshots>
+ <overWriteIfNewer>true</overWriteIfNewer>
+ <useRepositoryLayout>true</useRepositoryLayout>
+ <addParentPoms>false</addParentPoms>
+ <copyPom>false</copyPom>
+ <includeGroupIds>org.onap.ccsdk.sli.plugins</includeGroupIds>
+ <scope>provided</scope>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <artifactId>maven-resources-plugin</artifactId>
+ <version>2.6</version>
+ <executions>
+ <execution>
+ <id>copy-version</id>
+ <goals>
+ <goal>copy-resources</goal>
+ </goals><!-- here the phase you need -->
+ <phase>validate</phase>
+ <configuration>
+ <outputDirectory>${basedir}/target/stage</outputDirectory>
+ <resources>
+ <resource>
+ <directory>src/main/resources/scripts</directory>
+ <includes>
+ <include>install-feature.sh</include>
+ </includes>
+ <filtering>true</filtering>
+ </resource>
+ </resources>
+ </configuration>
+ </execution>
+
+ </executions>
+ </plugin>
+
+ </plugins>
+ </build>
+</project>
diff --git a/plugins/properties-node/installer/src/assembly/assemble_installer_zip.xml b/plugins/properties-node/installer/src/assembly/assemble_installer_zip.xml
new file mode 100644
index 000000000..b6fd65582
--- /dev/null
+++ b/plugins/properties-node/installer/src/assembly/assemble_installer_zip.xml
@@ -0,0 +1,59 @@
+<!--
+ ============LICENSE_START=======================================================
+ openECOMP : SDN-C
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property. All rights
+ reserved.
+ ================================================================================
+ 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.
+ ============LICENSE_END=========================================================
+ -->
+
+<!-- Defines how we build the .zip file which is our distribution. -->
+
+<assembly
+ xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
+ <id>installer_zip</id>
+ <formats>
+ <format>zip</format>
+ </formats>
+
+ <!-- we want "system" and related files right at the root level
+ as this file is suppose to be unzip on top of a karaf
+ distro. -->
+ <includeBaseDirectory>false</includeBaseDirectory>
+
+ <fileSets>
+ <fileSet>
+ <directory>target/stage/</directory>
+ <outputDirectory>${application.name}</outputDirectory>
+ <fileMode>755</fileMode>
+ <includes>
+ <include>*.sh</include>
+ </includes>
+ </fileSet>
+ <fileSet>
+ <directory>target/stage/</directory>
+ <outputDirectory>${application.name}</outputDirectory>
+ <fileMode>644</fileMode>
+ <excludes>
+ <exclude>*.sh</exclude>
+ </excludes>
+ </fileSet>
+ </fileSets>
+
+
+
+</assembly>
diff --git a/plugins/properties-node/installer/src/assembly/assemble_mvnrepo_zip.xml b/plugins/properties-node/installer/src/assembly/assemble_mvnrepo_zip.xml
new file mode 100644
index 000000000..9cdc78879
--- /dev/null
+++ b/plugins/properties-node/installer/src/assembly/assemble_mvnrepo_zip.xml
@@ -0,0 +1,49 @@
+<!--
+ ============LICENSE_START=======================================================
+ openECOMP : SDN-C
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property. All rights
+ reserved.
+ ================================================================================
+ 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.
+ ============LICENSE_END=========================================================
+ -->
+
+<!-- Defines how we build the .zip file which is our distribution. -->
+
+<assembly
+ xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
+ <id>repo</id>
+ <formats>
+ <format>zip</format>
+ </formats>
+
+ <!-- we want "system" and related files right at the root level
+ as this file is suppose to be unzip on top of a karaf
+ distro. -->
+ <includeBaseDirectory>false</includeBaseDirectory>
+
+ <fileSets>
+ <fileSet>
+ <directory>target/assembly/</directory>
+ <outputDirectory>.</outputDirectory>
+ <excludes>
+ </excludes>
+ </fileSet>
+ </fileSets>
+
+
+
+</assembly>
diff --git a/plugins/properties-node/installer/src/main/resources/scripts/install-feature.sh b/plugins/properties-node/installer/src/main/resources/scripts/install-feature.sh
new file mode 100644
index 000000000..0eab001d5
--- /dev/null
+++ b/plugins/properties-node/installer/src/main/resources/scripts/install-feature.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+
+###
+# ============LICENSE_START=======================================================
+# openECOMP : SDN-C
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights
+# reserved.
+# ================================================================================
+# 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.
+# ============LICENSE_END=========================================================
+###
+
+ODL_HOME=${ODL_HOME:-/opt/opendaylight/current}
+ODL_KARAF_CLIENT=${ODL_KARAF_CLIENT:-${ODL_HOME}/bin/client}
+INSTALLERDIR=$(dirname $0)
+
+REPOZIP=${INSTALLERDIR}/${features.boot}-${project.version}.zip
+
+if [ -f ${REPOZIP} ]
+then
+ unzip -d ${ODL_HOME} ${REPOZIP}
+else
+ echo "ERROR : repo zip ($REPOZIP) not found"
+ exit 1
+fi
+
+${ODL_KARAF_CLIENT} feature:repo-add ${features.repositories}
+${ODL_KARAF_CLIENT} feature:install ${features.boot}
diff --git a/plugins/properties-node/pom.xml b/plugins/properties-node/pom.xml
new file mode 100755
index 000000000..71fffe4d3
--- /dev/null
+++ b/plugins/properties-node/pom.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>odlparent-lite</artifactId>
+ <version>2.1.0</version>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.plugins</groupId>
+ <artifactId>properties-node</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>pom</packaging>
+
+ <name>ccsdk-sli-plugins :: properties-node</name>
+ <description>This is an implementation of DG Execute Node that reads property file and
+ puts the properties in the DG context</description>
+
+ <modules>
+ <module>provider</module>
+ <module>installer</module>
+ </modules>
+</project>
diff --git a/plugins/properties-node/provider/pom.xml b/plugins/properties-node/provider/pom.xml
new file mode 100755
index 000000000..fdfb4b3cb
--- /dev/null
+++ b/plugins/properties-node/provider/pom.xml
@@ -0,0 +1,60 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>binding-parent</artifactId>
+ <version>2.1.0</version>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.plugins</groupId>
+ <artifactId>properties-node-provider</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>bundle</packaging>
+
+ <name>ccsdk-sli-plugins :: properties-node :: ${project.artifactId}</name>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sli-core-artifacts</artifactId>
+ <version>${ccsdk.sli.core.version}</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.github.stefanbirkner</groupId>
+ <artifactId>system-rules</artifactId>
+ <version>1.19.0</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-test</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sli-common</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.codehaus.jettison</groupId>
+ <artifactId>jettison</artifactId>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/plugins/properties-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/prop/JsonParser.java b/plugins/properties-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/prop/JsonParser.java
new file mode 100644
index 000000000..89243a055
--- /dev/null
+++ b/plugins/properties-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/prop/JsonParser.java
@@ -0,0 +1,94 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.prop;
+
+import org.codehaus.jettison.json.JSONArray;
+import org.codehaus.jettison.json.JSONException;
+import org.codehaus.jettison.json.JSONObject;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+public final class JsonParser {
+
+ private static final Logger log = LoggerFactory.getLogger(JsonParser.class);
+
+ private JsonParser() {
+ // Preventing instantiation of the same.
+ }
+
+ @SuppressWarnings("unchecked")
+ public static Map<String, String> convertToProperties(String s)
+ throws SvcLogicException {
+
+ checkNotNull(s, "Input should not be null.");
+
+ try {
+ JSONObject json = new JSONObject(s);
+ Map<String, Object> wm = new HashMap<>();
+ Iterator<String> ii = json.keys();
+ while (ii.hasNext()) {
+ String key1 = ii.next();
+ wm.put(key1, json.get(key1));
+ }
+
+ Map<String, String> mm = new HashMap<>();
+
+ while (!wm.isEmpty())
+ for (String key : new ArrayList<>(wm.keySet())) {
+ Object o = wm.get(key);
+ wm.remove(key);
+
+ if (o instanceof Boolean || o instanceof Number || o instanceof String) {
+ mm.put(key, o.toString());
+
+ log.info("Added property: {} : {}", key, o.toString());
+ } else if (o instanceof JSONObject) {
+ JSONObject jo = (JSONObject) o;
+ Iterator<String> i = jo.keys();
+ while (i.hasNext()) {
+ String key1 = i.next();
+ wm.put(key + "." + key1, jo.get(key1));
+ }
+ } else if (o instanceof JSONArray) {
+ JSONArray ja = (JSONArray) o;
+ mm.put(key + "_length", String.valueOf(ja.length()));
+
+ log.info("Added property: {}_length: {}", key, String.valueOf(ja.length()));
+
+ for (int i = 0; i < ja.length(); i++)
+ wm.put(key + '[' + i + ']', ja.get(i));
+ }
+ }
+ return mm;
+ } catch (JSONException e) {
+ throw new SvcLogicException("Unable to convert JSON to properties " + e.getLocalizedMessage(), e);
+ }
+ }
+}
diff --git a/plugins/properties-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/prop/Parameters.java b/plugins/properties-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/prop/Parameters.java
new file mode 100644
index 000000000..99e4647d7
--- /dev/null
+++ b/plugins/properties-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/prop/Parameters.java
@@ -0,0 +1,31 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.prop;
+
+import java.util.Set;
+
+public class Parameters {
+ public String fileName;
+ public String contextPrefix;
+ public Set<String> listNameList;
+ public boolean fileBasedParsing;
+}
diff --git a/plugins/properties-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/prop/PropertiesNode.java b/plugins/properties-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/prop/PropertiesNode.java
new file mode 100644
index 000000000..b4bc84747
--- /dev/null
+++ b/plugins/properties-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/prop/PropertiesNode.java
@@ -0,0 +1,194 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.prop;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.core.sli.SvcLogicJavaPlugin;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class PropertiesNode implements SvcLogicJavaPlugin {
+
+ private static final Logger log = LoggerFactory.getLogger(PropertiesNode.class);
+
+ public void readProperties(Map<String, String> paramMap, SvcLogicContext ctx) throws SvcLogicException {
+ Parameters param = getParameters(paramMap);
+ Properties prop = new Properties();
+ try {
+ File file = new File(param.fileName);
+ try (InputStream in = new FileInputStream(file)) {
+ Map<String, String> mm = null;
+ String pfx = param.contextPrefix != null ? param.contextPrefix + '.' : "";
+ if (param.fileBasedParsing) {
+ byte[] data = new byte[(int) file.length()];
+ if ("json".equalsIgnoreCase(getFileExtension(param.fileName))) {
+ in.read(data);
+ String str = new String(data, "UTF-8");
+ mm = JsonParser.convertToProperties(str);
+ } else if ("xml".equalsIgnoreCase(getFileExtension(param.fileName))) {
+ in.read(data);
+ String str = new String(data, "UTF-8");
+ mm = XmlParser.convertToProperties(str, param.listNameList);
+ } else {
+ prop.load(in);
+ for (Object key : prop.keySet()) {
+ String name = (String) key;
+ String value = prop.getProperty(name);
+ if (value != null && value.trim().length() > 0) {
+ ctx.setAttribute(pfx + name, getObfuscatedVal(value.trim()));
+ log.info("+++ " + pfx + name + ": [" + maskPassword(pfx + name, value) + "]");
+ }
+ }
+ }
+ if (mm != null) {
+ for (Map.Entry<String, String> entry : mm.entrySet()) {
+ ctx.setAttribute(pfx + entry.getKey(), getObfuscatedVal(entry.getValue()));
+ log.info("+++ " + pfx + entry.getKey() + ": ["
+ + maskPassword(pfx + entry.getKey(), entry.getValue()) + "]");
+ }
+ }
+ } else {
+ prop.load(in);
+ for (Object key : prop.keySet()) {
+ String name = (String) key;
+ String value = prop.getProperty(name);
+ if (value != null && value.trim().length() > 0) {
+ ctx.setAttribute(pfx + name, getObfuscatedVal(value.trim()));
+ log.info("+++ " + pfx + name + ": [" + maskPassword(pfx + name, value) + "]");
+ }
+ }
+ }
+ }
+ } catch (IOException e) {
+ throw new SvcLogicException("Cannot read property file: " + param.fileName + ": " + e.getMessage(), e);
+ }
+ }
+
+ /* Unobfuscate param value */
+ private static String getObfuscatedVal(String paramValue) {
+ String resValue = paramValue;
+ if (paramValue != null && paramValue.startsWith("${") && paramValue.endsWith("}"))
+ {
+ String paramStr = paramValue.substring(2, paramValue.length()-1);
+ if (paramStr != null && paramStr.length() > 0)
+ {
+ String val = System.getenv(paramStr);
+ if (val != null && val.length() > 0)
+ {
+ resValue=val;
+ log.info("Obfuscated value RESET for param value:" + paramValue);
+ }
+ }
+ }
+ return resValue;
+ }
+
+ /*
+ * Getting extension has to do the following "" --> "" "name" --> "" "name.txt" --> "txt"
+ * ".htpasswd" --> "" "name.with.many.dots.myext" --> "myext"
+ */
+ private static String getFileExtension(String fileName) {
+ if (fileName.lastIndexOf(".") != -1 && fileName.lastIndexOf(".") != 0) {
+ return fileName.substring(fileName.lastIndexOf(".") + 1);
+ } else {
+ return "";
+ }
+ }
+
+ protected Parameters getParameters(Map<String, String> paramMap) throws SvcLogicException {
+ Parameters p = new Parameters();
+ p.fileName = parseParam(paramMap, "fileName", true, null);
+ p.contextPrefix = parseParam(paramMap, "contextPrefix", false, null);
+ p.listNameList = getListNameList(paramMap);
+ String fileBasedParsingStr = paramMap.get("fileBasedParsing");
+ p.fileBasedParsing = "true".equalsIgnoreCase(fileBasedParsingStr);
+ return p;
+ }
+
+ protected Set<String> getListNameList(Map<String, String> paramMap) {
+ Set<String> ll = new HashSet<>();
+ for (Map.Entry<String, String> entry : paramMap.entrySet()) {
+ if (entry.getKey().startsWith("listName")) {
+ ll.add(entry.getValue());
+ }
+ }
+ return ll;
+ }
+
+ private String parseParam(Map<String, String> paramMap, String name, boolean required, String def)
+ throws SvcLogicException {
+ String s = paramMap.get(name);
+
+ if (s == null || s.trim().length() == 0) {
+ if (!required) {
+ return def;
+ }
+ throw new SvcLogicException("Parameter " + name + " is required in PropertiesNode");
+ }
+
+ s = s.trim();
+ String value = "";
+ int i = 0;
+ int i1 = s.indexOf('%');
+ while (i1 >= 0) {
+ int i2 = s.indexOf('%', i1 + 1);
+ if (i2 < 0) {
+ throw new SvcLogicException("Cannot parse parameter " + name + ": " + s + ": no matching %");
+ }
+
+ String varName = s.substring(i1 + 1, i2);
+ String varValue = System.getenv(varName);
+ if (varValue == null) {
+ varValue = "";
+ }
+
+ value += s.substring(i, i1);
+ value += varValue;
+
+ i = i2 + 1;
+ i1 = s.indexOf('%', i);
+ }
+ value += s.substring(i);
+
+ log.info("Parameter " + name + ": " + maskPassword(name, value));
+ return value;
+ }
+
+ private static Object maskPassword(String name, Object value) {
+ String[] pwdNames = {"pwd", "passwd", "password", "Pwd", "Passwd", "Password"};
+ for (String pwdName : pwdNames) {
+ if (name.contains(pwdName)) {
+ return "**********";
+ }
+ }
+ return value;
+ }
+}
diff --git a/plugins/properties-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/prop/XmlParser.java b/plugins/properties-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/prop/XmlParser.java
new file mode 100644
index 000000000..f48a21e9d
--- /dev/null
+++ b/plugins/properties-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/prop/XmlParser.java
@@ -0,0 +1,176 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved. *
+ * Modifications Copyright © 2018 IBM.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.prop;
+
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+import javax.xml.XMLConstants;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+public final class XmlParser {
+
+ private static final Logger log = LoggerFactory.getLogger(XmlParser.class);
+
+ private XmlParser() {
+ // Preventing instantiation of the same.
+ }
+
+ public static Map<String, String> convertToProperties(String s, Set<String> listNameList)
+ throws SvcLogicException {
+
+ checkNotNull(s, "Input should not be null.");
+
+ Handler handler = new Handler(listNameList);
+ try {
+ SAXParserFactory factory = SAXParserFactory.newInstance();
+
+ factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
+ factory.setFeature("http://xml.org/sax/features/external-general-entities", false);
+ factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
+ SAXParser saxParser = factory.newSAXParser();
+ InputStream in = new ByteArrayInputStream(s.getBytes());
+ saxParser.parse(in, handler);
+ } catch (ParserConfigurationException | IOException | SAXException | NumberFormatException e) {
+ throw new SvcLogicException("Unable to convert XML to properties" + e.getLocalizedMessage(), e);
+ }
+ return handler.getProperties();
+ }
+
+ private static class Handler extends DefaultHandler {
+
+ private Set<String> listNameList;
+
+ private Map<String, String> properties = new HashMap<>();
+
+ StringBuilder currentName = new StringBuilder();
+ StringBuilder currentValue = new StringBuilder();
+
+ public Handler(Set<String> listNameList) {
+ super();
+ this.listNameList = listNameList;
+ if (this.listNameList == null)
+ this.listNameList = new HashSet<>();
+ }
+
+ public Map<String, String> getProperties() {
+ return properties;
+ }
+
+ @Override
+ public void startElement(String uri, String localName, String qName, Attributes attributes)
+ throws SAXException {
+ super.startElement(uri, localName, qName, attributes);
+
+ String name = localName;
+ if (name == null || name.trim().length() == 0)
+ name = qName;
+ int i2 = name.indexOf(':');
+ if (i2 >= 0)
+ name = name.substring(i2 + 1);
+
+ if (currentName.length() > 0)
+ currentName.append(Character.toString('.'));
+ currentName.append(name);
+
+ String listName = removeIndexes(currentName.toString());
+
+ if (listNameList.contains(listName)) {
+ String n = currentName.toString() + "_length";
+ int len = getInt(properties, n);
+ properties.put(n, String.valueOf(len + 1));
+ currentName.append("[").append(len).append("]");
+ }
+ }
+
+ @Override
+ public void endElement(String uri, String localName, String qName) throws SAXException {
+ super.endElement(uri, localName, qName);
+
+ String name = localName;
+ if (name == null || name.trim().length() == 0)
+ name = qName;
+ int i2 = name.indexOf(':');
+ if (i2 >= 0)
+ name = name.substring(i2 + 1);
+
+ String s = currentValue.toString().trim();
+ if (s.length() > 0) {
+ properties.put(currentName.toString(), s);
+
+ log.info("Added property: {} : {}", currentName, s);
+ currentValue = new StringBuilder();
+ }
+
+ int i1 = currentName.lastIndexOf("." + name);
+ if (i1 <= 0)
+ currentName = new StringBuilder();
+ else
+ currentName = new StringBuilder(currentName.substring(0, i1));
+ }
+
+ @Override
+ public void characters(char[] ch, int start, int length) throws SAXException {
+ super.characters(ch, start, length);
+
+ String value = new String(ch, start, length);
+ currentValue.append(value);
+ }
+
+ private static int getInt(Map<String, String> mm, String name) {
+ String s = mm.get(name);
+ if (s == null)
+ return 0;
+ return Integer.parseInt(s);
+ }
+
+ private String removeIndexes(String currentName) {
+ StringBuilder b = new StringBuilder();
+ boolean add = true;
+ for (int i = 0; i < currentName.length(); i++) {
+ char c = currentName.charAt(i);
+ if (c == '[')
+ add = false;
+ else if (c == ']')
+ add = true;
+ else if (add)
+ b.append(Character.toString(c));
+ }
+ return b.toString();
+ }
+ }
+}
diff --git a/plugins/properties-node/provider/src/main/resources/OSGI-INF/blueprint/properties-node-blueprint.xml b/plugins/properties-node/provider/src/main/resources/OSGI-INF/blueprint/properties-node-blueprint.xml
new file mode 100755
index 000000000..6e1d48efd
--- /dev/null
+++ b/plugins/properties-node/provider/src/main/resources/OSGI-INF/blueprint/properties-node-blueprint.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+ xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0"
+ odl:use-default-for-reference-types="true">
+
+ <bean id="propNodeProvider" class="org.onap.ccsdk.sli.plugins.prop.PropertiesNode" />
+
+
+
+ <service ref="propNodeProvider">
+ <interfaces>
+ <value>org.onap.ccsdk.sli.plugins.prop.PropertiesNode</value>
+ </interfaces>
+ </service>
+
+</blueprint> \ No newline at end of file
diff --git a/plugins/properties-node/provider/src/main/resources/org/opendaylight/blueprint/properties-node-blueprint.xml b/plugins/properties-node/provider/src/main/resources/org/opendaylight/blueprint/properties-node-blueprint.xml
new file mode 100755
index 000000000..6e1d48efd
--- /dev/null
+++ b/plugins/properties-node/provider/src/main/resources/org/opendaylight/blueprint/properties-node-blueprint.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+ xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0"
+ odl:use-default-for-reference-types="true">
+
+ <bean id="propNodeProvider" class="org.onap.ccsdk.sli.plugins.prop.PropertiesNode" />
+
+
+
+ <service ref="propNodeProvider">
+ <interfaces>
+ <value>org.onap.ccsdk.sli.plugins.prop.PropertiesNode</value>
+ </interfaces>
+ </service>
+
+</blueprint> \ No newline at end of file
diff --git a/plugins/properties-node/provider/src/test/java/jtest/org/onap/ccsdk/sli/plugins/prop/TestJsonParser.java b/plugins/properties-node/provider/src/test/java/jtest/org/onap/ccsdk/sli/plugins/prop/TestJsonParser.java
new file mode 100644
index 000000000..0681124d9
--- /dev/null
+++ b/plugins/properties-node/provider/src/test/java/jtest/org/onap/ccsdk/sli/plugins/prop/TestJsonParser.java
@@ -0,0 +1,73 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package jtest.org.onap.ccsdk.sli.plugins.prop;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.Test;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.plugins.prop.JsonParser;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class TestJsonParser {
+
+ private static final Logger log = LoggerFactory.getLogger(TestJsonParser.class);
+
+ @Test
+ public void test() throws SvcLogicException, IOException {
+ BufferedReader in = new BufferedReader(
+ new InputStreamReader(ClassLoader.getSystemResourceAsStream("test.json"))
+ );
+ StringBuilder b = new StringBuilder();
+ String line;
+ while ((line = in.readLine()) != null)
+ b.append(line).append('\n');
+
+ Map<String, String> mm = JsonParser.convertToProperties(b.toString());
+
+ logProperties(mm);
+
+ in.close();
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void testNullString() throws SvcLogicException {
+ JsonParser.convertToProperties(null);
+ }
+
+ private void logProperties(Map<String, String> mm) {
+ List<String> ll = new ArrayList<>();
+ for (Object o : mm.keySet())
+ ll.add((String) o);
+ Collections.sort(ll);
+ log.info("Properties:");
+ for (String name : ll)
+ log.info("--- {}: {}", name, mm.get(name));
+ }
+}
diff --git a/plugins/properties-node/provider/src/test/java/jtest/org/onap/ccsdk/sli/plugins/prop/TestPropertiesNode.java b/plugins/properties-node/provider/src/test/java/jtest/org/onap/ccsdk/sli/plugins/prop/TestPropertiesNode.java
new file mode 100644
index 000000000..a858c49b3
--- /dev/null
+++ b/plugins/properties-node/provider/src/test/java/jtest/org/onap/ccsdk/sli/plugins/prop/TestPropertiesNode.java
@@ -0,0 +1,608 @@
+package jtest.org.onap.ccsdk.sli.plugins.prop;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.contrib.java.lang.system.EnvironmentVariables;
+import static org.junit.Assert.assertEquals;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.plugins.prop.PropertiesNode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class TestPropertiesNode {
+
+ private static final Logger log = LoggerFactory.getLogger(TestPropertiesNode.class);
+ @Rule
+ public EnvironmentVariables environmentVariables = new EnvironmentVariables();
+
+ @Test
+ public void testJSONFileParsing() throws SvcLogicException {
+ SvcLogicContext ctx = new SvcLogicContext();
+
+ Map<String, String> p = new HashMap<String, String>();
+ p.put("fileName", "src/test/resources/test.json");
+ p.put("contextPrefix", "test-json");
+ p.put("fileBasedParsing","true");
+
+ PropertiesNode rcn = new PropertiesNode();
+ rcn.readProperties(p, ctx);
+
+ assertEquals(ctx.getAttribute("test-json.message"),"The provisioned access " +
+ "bandwidth is at or exceeds 50% of the total server capacity.");
+ }
+
+ @Test
+ public void testJSONFileArrayParsing() throws SvcLogicException {
+ SvcLogicContext ctx = new SvcLogicContext();
+
+ Map<String, String> p = new HashMap<String, String>();
+ p.put("fileName", "src/test/resources/test.json");
+ p.put("contextPrefix", "test-json");
+ p.put("fileBasedParsing","true");
+
+ PropertiesNode rcn = new PropertiesNode();
+ rcn.readProperties(p, ctx);
+
+ assertEquals(ctx.getAttribute("test-json.equipment-data[0].max-server-speed"),"1600000");
+ assertEquals(ctx.getAttribute("test-json.resource-state.used"),"1605000");
+ assertEquals(ctx.getAttribute("test-json.resource-rule.service-model"),"DUMMY");
+ assertEquals(ctx.getAttribute("test-json.resource-rule.endpoint-position"),"VCE-Cust");
+ }
+
+ @Test
+ public void testJSONFileParsingPrefixCheck() throws SvcLogicException {
+ SvcLogicContext ctx = new SvcLogicContext();
+
+ Map<String, String> p = new HashMap<String, String>();
+ p.put("fileName", "src/test/resources/test.json");
+ p.put("contextPrefix", "");
+ p.put("fileBasedParsing","true");
+
+ PropertiesNode rcn = new PropertiesNode();
+ rcn.readProperties(p, ctx);
+
+ assertEquals(ctx.getAttribute("equipment-data[0].max-server-speed"),"1600000");
+ assertEquals(ctx.getAttribute("resource-state.used"),"1605000");
+ assertEquals(ctx.getAttribute("resource-rule.service-model"),"DUMMY");
+ assertEquals(ctx.getAttribute("resource-rule.endpoint-position"),"VCE-Cust");
+ assertEquals(ctx.getAttribute("resource-rule.hard-limit-expression"),"max-server-" +
+ "speed * number-primary-servers");
+ }
+
+ @Test
+ public void testJSONFileParsingNoPrefix() throws SvcLogicException {
+ SvcLogicContext ctx = new SvcLogicContext();
+
+ Map<String, String> p = new HashMap<String, String>();
+ p.put("fileName", "src/test/resources/test.json");
+ p.put("fileBasedParsing","true");
+
+ PropertiesNode rcn = new PropertiesNode();
+ rcn.readProperties(p, ctx);
+
+ assertEquals(ctx.getAttribute("equipment-data[0].max-server-speed"),"1600000");
+ assertEquals(ctx.getAttribute("resource-state.used"),"1605000");
+ assertEquals(ctx.getAttribute("resource-rule.service-model"),"DUMMY");
+ assertEquals(ctx.getAttribute("resource-rule.endpoint-position"),"VCE-Cust");
+ assertEquals(ctx.getAttribute("resource-rule.hard-limit-expression"),"max-server-" +
+ "speed * number-primary-servers");
+ }
+
+ @Test
+ public void testJSONFileParsingCtxCheck() throws SvcLogicException {
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute("tmp.sdn-circuit-req-row_length", "1");
+
+ Map<String, String> p = new HashMap<String, String>();
+ p.put("fileName", "src/test/resources/test.json");
+ p.put("fileBasedParsing","true");
+
+ PropertiesNode rcn = new PropertiesNode();
+ rcn.readProperties(p, ctx);
+
+ assertEquals(ctx.getAttribute("equipment-data[0].max-server-speed"),"1600000");
+ assertEquals(ctx.getAttribute("resource-state.used"),"1605000");
+ assertEquals(ctx.getAttribute("resource-rule.service-model"),"DUMMY");
+ assertEquals(ctx.getAttribute("resource-rule.endpoint-position"),"VCE-Cust");
+ assertEquals(ctx.getAttribute("resource-rule.hard-limit-expression"),"max-server-" +
+ "speed * number-primary-servers");
+ assertEquals(ctx.getAttribute("tmp.sdn-circuit-req-row_length"),"1");
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void testToPropertiesInvalidJson() throws SvcLogicException {
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute("tmp.sdn-circuit-req-row_length", "1");
+
+ Map<String, String> p = new HashMap<String, String>();
+ p.put("fileName", "src/test/resources/test-invalid.json");
+ p.put("contextPrefix", "invalid");
+ p.put("fileBasedParsing","true");
+
+ PropertiesNode rcn = new PropertiesNode();
+ rcn.readProperties(p, ctx);
+
+ assertEquals(ctx.getAttribute("tmp.sdn-circuit-req-row_length"),"1");
+ }
+
+ @Test
+ public void testTXTFileParsing() throws SvcLogicException {
+
+ environmentVariables.set("deployer_pass", "sdncp-123");
+ assertEquals("sdncp-123", System.getenv("deployer_pass"));
+
+ SvcLogicContext ctx = new SvcLogicContext();
+
+ Map<String, String> p = new HashMap<String, String>();
+ p.put("fileName", "src/test/resources/test.txt");
+ p.put("contextPrefix", "test-txt");
+ p.put("fileBasedParsing","true");
+
+ PropertiesNode rcn = new PropertiesNode();
+ rcn.readProperties(p, ctx);
+
+ assertEquals(ctx.getAttribute("test-txt.service-data.service-information.service-type"),"AVPN");
+ assertEquals(ctx.getAttribute("test-txt.service-configuration-notification-input.response-code"),"0");
+ assertEquals(ctx.getAttribute("test-txt.operational-data.avpn-ip-port-information.port-" +
+ "level-cos.queueing.pe-per-class-queueing-behaviors.cos3-queueing"),"WRED");
+ assertEquals(ctx.getAttribute("test-txt.service-data.avpn-ip-port-information.avpn-" +
+ "access-information.l1-customer-handoff"),"_1000BASELX");
+ assertEquals(ctx.getAttribute("test-txt.service-data.avpn-ip-port-information.avpn-" +
+ "access-information.vlan-tag-control"),"_1Q");
+ assertEquals(ctx.getAttribute("test-txt.obfuscated-var"), "sdncp-123");
+ }
+
+ @Test
+ public void testTXTFileParsingPrefixCheck() throws SvcLogicException {
+ SvcLogicContext ctx = new SvcLogicContext();
+
+ Map<String, String> p = new HashMap<String, String>();
+ p.put("fileName", "src/test/resources/test.txt");
+ p.put("contextPrefix", "");
+ p.put("fileBasedParsing","true");
+
+ PropertiesNode rcn = new PropertiesNode();
+ rcn.readProperties(p, ctx);
+
+ assertEquals(ctx.getAttribute("service-data.service-information.service-type"),"AVPN");
+ assertEquals(ctx.getAttribute("service-configuration-notification-input.response-code"),"0");
+ assertEquals(ctx.getAttribute("operational-data.avpn-ip-port-information.port-" +
+ "level-cos.queueing.pe-per-class-queueing-behaviors.cos3-queueing"),"WRED");
+ assertEquals(ctx.getAttribute("service-data.avpn-ip-port-information.avpn-" +
+ "access-information.l1-customer-handoff"),"_1000BASELX");
+ assertEquals(ctx.getAttribute("service-data.avpn-ip-port-information.avpn-" +
+ "access-information.vlan-tag-control"),"_1Q");
+ }
+
+ @Test
+ public void testTXTFileParsingNoPrefix() throws SvcLogicException {
+ SvcLogicContext ctx = new SvcLogicContext();
+
+ Map<String, String> p = new HashMap<String, String>();
+ p.put("fileName", "src/test/resources/test.txt");
+ p.put("fileBasedParsing","true");
+
+ PropertiesNode rcn = new PropertiesNode();
+ rcn.readProperties(p, ctx);
+
+ assertEquals(ctx.getAttribute("service-data.service-information.service-type"),"AVPN");
+ assertEquals(ctx.getAttribute("service-configuration-notification-input.response-code"),"0");
+ assertEquals(ctx.getAttribute("operational-data.avpn-ip-port-information.port-" +
+ "level-cos.queueing.pe-per-class-queueing-behaviors.cos3-queueing"),"WRED");
+ assertEquals(ctx.getAttribute("service-data.avpn-ip-port-information.avpn-" +
+ "access-information.l1-customer-handoff"),"_1000BASELX");
+ assertEquals(ctx.getAttribute("service-data.avpn-ip-port-information.avpn-" +
+ "access-information.vlan-tag-control"),"_1Q");
+ }
+
+ @Test
+ public void testTXTFileParsingCtxCheck() throws SvcLogicException {
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute("tmp.sdn-circuit-req-row_length", "1");
+
+ Map<String, String> p = new HashMap<String, String>();
+ p.put("fileName", "src/test/resources/test.txt");
+ p.put("fileBasedParsing","true");
+
+ PropertiesNode rcn = new PropertiesNode();
+ rcn.readProperties(p, ctx);
+
+ assertEquals(ctx.getAttribute("service-data.service-information.service-type"),"AVPN");
+ assertEquals(ctx.getAttribute("service-configuration-notification-input.response-code"),"0");
+ assertEquals(ctx.getAttribute("operational-data.avpn-ip-port-information.port-" +
+ "level-cos.queueing.pe-per-class-queueing-behaviors.cos3-queueing"),"WRED");
+ assertEquals(ctx.getAttribute("service-data.avpn-ip-port-information.avpn-" +
+ "access-information.l1-customer-handoff"),"_1000BASELX");
+ assertEquals(ctx.getAttribute("service-data.avpn-ip-port-information.avpn-" +
+ "access-information.vlan-tag-control"),"_1Q");
+ assertEquals(ctx.getAttribute("tmp.sdn-circuit-req-row_length"),"1");
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void testToPropertiesInvalidParam() throws SvcLogicException {
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute("tmp.sdn-circuit-req-row_length", "1");
+
+ Map<String, String> p = new HashMap<String, String>();
+ p.put("responsePrefix", "response");
+ p.put("skipSending", "true");
+ p.put("fileBasedParsing","true");
+
+ PropertiesNode rcn = new PropertiesNode();
+ rcn.readProperties(p, ctx);
+
+ assertEquals(ctx.getAttribute("tmp.sdn-circuit-req-row_length"),"1");
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void testToPropertiesNoParam() throws SvcLogicException {
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute("tmp.sdn-circuit-req-row_length", "1");
+
+ Map<String, String> p = new HashMap<String, String>();
+ p.put("fileBasedParsing","true");
+
+ PropertiesNode rcn = new PropertiesNode();
+ rcn.readProperties(p, ctx);
+
+ assertEquals(ctx.getAttribute("tmp.sdn-circuit-req-row_length"),"1");
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void testToPropertiesFilePathError() throws SvcLogicException {
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute("tmp.sdn-circuit-req-row_length", "1");
+
+ Map<String, String> p = new HashMap<String, String>();
+ p.put("fileName", "src/tests/resources/test.txt");
+ p.put("fileBasedParsing","true");
+
+ PropertiesNode rcn = new PropertiesNode();
+ rcn.readProperties(p, ctx);
+
+ assertEquals(ctx.getAttribute("tmp.sdn-circuit-req-row_length"),"1");
+ }
+
+ @Test
+ public void testXMLFileParsing() throws SvcLogicException {
+ SvcLogicContext ctx = new SvcLogicContext();
+
+ Map<String, String> p = new HashMap<String, String>();
+ p.put("fileName", "src/test/resources/test.xml");
+ p.put("contextPrefix", "test-xml");
+ p.put("listName", "project.build");
+ p.put("fileBasedParsing","true");
+
+ PropertiesNode rcn = new PropertiesNode();
+ rcn.readProperties(p, ctx);
+
+ assertEquals(ctx.getAttribute("test-xml.project.modelVersion"),"4.0.0");
+ }
+
+ @Test
+ public void testXMLFileInnerParsing() throws SvcLogicException {
+ SvcLogicContext ctx = new SvcLogicContext();
+
+ Map<String, String> p = new HashMap<String, String>();
+ p.put("fileName", "src/test/resources/test.xml");
+ p.put("contextPrefix", "test-xml");
+ p.put("listName", "project.modelVersion");
+ p.put("fileBasedParsing","true");
+
+ PropertiesNode rcn = new PropertiesNode();
+ rcn.readProperties(p, ctx);
+
+ assertEquals(ctx.getAttribute("test-xml.project.properties.project.build.sourceEncoding"),"UTF-8");
+ assertEquals(ctx.getAttribute("test-xml.project.dependencies.dependency.scope"),"provided");
+ assertEquals(ctx.getAttribute("test-xml.project.build.pluginManagement.plugins.plugin.configuration" +
+ ".lifecycleMappingMetadata.pluginExecutions.pluginExecution." +
+ "pluginExecutionFilter.versionRange"),"[1.2.0.100,)");
+ assertEquals(ctx.getAttribute("test-xml.project.build.plugins.plugin.configuration." +
+ "instructions.Import-Package"),"*");
+ }
+
+ @Test
+ public void testXMLFileParsingPrefixCheck() throws SvcLogicException {
+ SvcLogicContext ctx = new SvcLogicContext();
+
+ Map<String, String> p = new HashMap<String, String>();
+ p.put("fileName", "src/test/resources/test.xml");
+ p.put("contextPrefix", "");
+ p.put("fileBasedParsing","true");
+
+ PropertiesNode rcn = new PropertiesNode();
+ rcn.readProperties(p, ctx);
+
+ assertEquals(ctx.getAttribute("project.properties.project.build.sourceEncoding"),"UTF-8");
+ assertEquals(ctx.getAttribute("project.dependencies.dependency.scope"),"provided");
+ assertEquals(ctx.getAttribute("project.build.pluginManagement.plugins.plugin.configuration" +
+ ".lifecycleMappingMetadata.pluginExecutions.pluginExecution." +
+ "pluginExecutionFilter.versionRange"),"[1.2.0.100,)");
+ assertEquals(ctx.getAttribute("project.build.plugins.plugin.configuration." +
+ "instructions.Import-Package"),"*");
+ }
+
+ @Test
+ public void testXMLFileParsingNoPrefix() throws SvcLogicException {
+ SvcLogicContext ctx = new SvcLogicContext();
+
+ Map<String, String> p = new HashMap<String, String>();
+ p.put("fileName", "src/test/resources/test.xml");
+ p.put("fileBasedParsing","true");
+
+ PropertiesNode rcn = new PropertiesNode();
+ rcn.readProperties(p, ctx);
+
+ assertEquals(ctx.getAttribute("project.properties.project.build.sourceEncoding"),"UTF-8");
+ assertEquals(ctx.getAttribute("project.dependencies.dependency.scope"),"provided");
+ assertEquals(ctx.getAttribute("project.build.pluginManagement.plugins.plugin.configuration" +
+ ".lifecycleMappingMetadata.pluginExecutions.pluginExecution." +
+ "pluginExecutionFilter.versionRange"),"[1.2.0.100,)");
+ assertEquals(ctx.getAttribute("project.build.plugins.plugin.configuration." +
+ "instructions.Import-Package"),"*");
+ }
+
+ @Test
+ public void testXMLFileParsingCtxCheck() throws SvcLogicException {
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute("tmp.sdn-circuit-req-row_length", "1");
+
+ Map<String, String> p = new HashMap<String, String>();
+ p.put("fileName", "src/test/resources/test.xml");
+ p.put("fileBasedParsing","true");
+
+ PropertiesNode rcn = new PropertiesNode();
+ rcn.readProperties(p, ctx);
+
+ assertEquals(ctx.getAttribute("project.properties.project.build.sourceEncoding"),"UTF-8");
+ assertEquals(ctx.getAttribute("project.dependencies.dependency.scope"),"provided");
+ assertEquals(ctx.getAttribute("project.build.pluginManagement.plugins.plugin.configuration" +
+ ".lifecycleMappingMetadata.pluginExecutions.pluginExecution." +
+ "pluginExecutionFilter.versionRange"),"[1.2.0.100,)");
+ assertEquals(ctx.getAttribute("project.build.plugins.plugin.configuration." +
+ "instructions.Import-Package"),"*");
+ assertEquals(ctx.getAttribute("tmp.sdn-circuit-req-row_length"),"1");
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void testToPropertiesInvalidXML() throws SvcLogicException {
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute("tmp.sdn-circuit-req-row_length", "1");
+
+ Map<String, String> p = new HashMap<String, String>();
+ p.put("fileName", "src/test/resources/test-invalid.xml");
+ p.put("contextPrefix", "invalid");
+ p.put("fileBasedParsing","true");
+
+ PropertiesNode rcn = new PropertiesNode();
+ rcn.readProperties(p, ctx);
+
+ assertEquals(ctx.getAttribute("tmp.sdn-circuit-req-row_length"),"1");
+ }
+
+ @Test
+ public void testXMLFileParsingListName() throws SvcLogicException {
+ SvcLogicContext ctx = new SvcLogicContext();
+
+ Map<String, String> p = new HashMap<String, String>();
+ p.put("fileName", "src/test/resources/test.xml");
+ p.put("contextPrefix", "test-xml-listName");
+ p.put("fileBasedParsing","true");
+ p.put("listName", "project.build.pluginManagement");
+
+ PropertiesNode rcn = new PropertiesNode();
+ rcn.readProperties(p, ctx);
+
+ assertEquals(ctx.getAttribute("test-xml-listName.project.build." +
+ "pluginManagement.plugins.plugin.version"),null);
+ assertEquals(ctx.getAttribute("test-xml-listName.project.build." +
+ "plugins.plugin.groupId"),"org.apache.felix");
+ }
+
+ @Test
+ public void testXMLFileParsingListNameAnother() throws SvcLogicException {
+ SvcLogicContext ctx = new SvcLogicContext();
+
+ Map<String, String> p = new HashMap<String, String>();
+ p.put("fileName", "src/test/resources/test.xml");
+ p.put("contextPrefix", "test-xml-listName");
+ p.put("fileBasedParsing","true");
+ p.put("listName", "project.modelVersion");
+
+ PropertiesNode rcn = new PropertiesNode();
+ rcn.readProperties(p, ctx);
+
+ assertEquals(ctx.getAttribute("test-xml-listName.project.modelVersion"),null);
+ assertEquals(ctx.getAttribute("test-xml-listName.project.build." +
+ "plugins.plugin.groupId"),"org.apache.felix");
+ }
+
+ @Test
+ public void testTXTFileParsingNotFileBased() throws SvcLogicException {
+ SvcLogicContext ctx = new SvcLogicContext();
+
+ Map<String, String> p = new HashMap<String, String>();
+ p.put("fileName", "src/test/resources/test.txt");
+ p.put("contextPrefix", "test-txt");
+
+ PropertiesNode rcn = new PropertiesNode();
+ rcn.readProperties(p, ctx);
+
+ assertEquals(ctx.getAttribute("test-txt.service-data.service-information.service-type"),"AVPN");
+ assertEquals(ctx.getAttribute("test-txt.service-configuration-notification-input.response-code"),"0");
+ assertEquals(ctx.getAttribute("test-txt.operational-data.avpn-ip-port-information.port-" +
+ "level-cos.queueing.pe-per-class-queueing-behaviors.cos3-queueing"),"WRED");
+ assertEquals(ctx.getAttribute("test-txt.service-data.avpn-ip-port-information.avpn-" +
+ "access-information.l1-customer-handoff"),"_1000BASELX");
+ assertEquals(ctx.getAttribute("test-txt.service-data.avpn-ip-port-information.avpn-" +
+ "access-information.vlan-tag-control"),"_1Q");
+ }
+
+ @Test
+ public void testTXTFileParsingPrefixCheckNotFileBased() throws SvcLogicException {
+ SvcLogicContext ctx = new SvcLogicContext();
+
+ Map<String, String> p = new HashMap<String, String>();
+ p.put("fileName", "src/test/resources/test.txt");
+ p.put("contextPrefix", "");
+
+ PropertiesNode rcn = new PropertiesNode();
+ rcn.readProperties(p, ctx);
+
+ assertEquals(ctx.getAttribute("service-data.service-information.service-type"),"AVPN");
+ assertEquals(ctx.getAttribute("service-configuration-notification-input.response-code"),"0");
+ assertEquals(ctx.getAttribute("operational-data.avpn-ip-port-information.port-" +
+ "level-cos.queueing.pe-per-class-queueing-behaviors.cos3-queueing"),"WRED");
+ assertEquals(ctx.getAttribute("service-data.avpn-ip-port-information.avpn-" +
+ "access-information.l1-customer-handoff"),"_1000BASELX");
+ assertEquals(ctx.getAttribute("service-data.avpn-ip-port-information.avpn-" +
+ "access-information.vlan-tag-control"),"_1Q");
+ }
+
+ @Test
+ public void testTXTFileParsingNoPrefixNotFileBased() throws SvcLogicException {
+ SvcLogicContext ctx = new SvcLogicContext();
+
+ Map<String, String> p = new HashMap<String, String>();
+ p.put("fileName", "src/test/resources/test.txt");
+
+ PropertiesNode rcn = new PropertiesNode();
+ rcn.readProperties(p, ctx);
+
+ assertEquals(ctx.getAttribute("service-data.service-information.service-type"),"AVPN");
+ assertEquals(ctx.getAttribute("service-configuration-notification-input.response-code"),"0");
+ assertEquals(ctx.getAttribute("operational-data.avpn-ip-port-information.port-" +
+ "level-cos.queueing.pe-per-class-queueing-behaviors.cos3-queueing"),"WRED");
+ assertEquals(ctx.getAttribute("service-data.avpn-ip-port-information.avpn-" +
+ "access-information.l1-customer-handoff"),"_1000BASELX");
+ assertEquals(ctx.getAttribute("service-data.avpn-ip-port-information.avpn-" +
+ "access-information.vlan-tag-control"),"_1Q");
+ }
+
+ @Test
+ public void testTXTFileParsingCtxCheckNotFileBased() throws SvcLogicException {
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute("tmp.sdn-circuit-req-row_length", "1");
+
+ Map<String, String> p = new HashMap<String, String>();
+ p.put("fileName", "src/test/resources/test.txt");
+
+ PropertiesNode rcn = new PropertiesNode();
+ rcn.readProperties(p, ctx);
+
+ assertEquals(ctx.getAttribute("service-data.service-information.service-type"),"AVPN");
+ assertEquals(ctx.getAttribute("service-configuration-notification-input.response-code"),"0");
+ assertEquals(ctx.getAttribute("operational-data.avpn-ip-port-information.port-" +
+ "level-cos.queueing.pe-per-class-queueing-behaviors.cos3-queueing"),"WRED");
+ assertEquals(ctx.getAttribute("service-data.avpn-ip-port-information.avpn-" +
+ "access-information.l1-customer-handoff"),"_1000BASELX");
+ assertEquals(ctx.getAttribute("service-data.avpn-ip-port-information.avpn-" +
+ "access-information.vlan-tag-control"),"_1Q");
+ assertEquals(ctx.getAttribute("tmp.sdn-circuit-req-row_length"),"1");
+ }
+
+ @Test
+ public void testJSONFileArrayParsingNotFileBased() throws SvcLogicException {
+ SvcLogicContext ctx = new SvcLogicContext();
+
+ Map<String, String> p = new HashMap<String, String>();
+ p.put("fileName", "src/test/resources/test.json");
+ p.put("contextPrefix", "NotFileBased");
+
+ PropertiesNode rcn = new PropertiesNode();
+ rcn.readProperties(p, ctx);
+
+ assertEquals(ctx.getAttribute("NotFileBased.\"limit-value\""),"\"1920000\"");
+ assertEquals(ctx.getAttribute("NotFileBased.\"hard-limit-expression\""),"\"max-server-speed * number-primary-servers\",");
+ assertEquals(ctx.getAttribute("NotFileBased.\"test-inner-node\""),"\"Test-Value\"");
+ }
+
+ @Test
+ public void testXMLFileInnerParsingNotFileBased() throws SvcLogicException {
+ SvcLogicContext ctx = new SvcLogicContext();
+
+ Map<String, String> p = new HashMap<String, String>();
+ p.put("fileName", "src/test/resources/test.xml");
+ p.put("contextPrefix", "NotFileBased");
+ p.put("listName", "project.modelVersion");
+
+ PropertiesNode rcn = new PropertiesNode();
+ rcn.readProperties(p, ctx);
+
+ assertEquals(ctx.getAttribute("NotFileBased.<name>RESTAPI"),"Call Node - Provider</name>");
+ assertEquals(ctx.getAttribute("NotFileBased.<project"),
+ "xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"" +
+ " xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">");
+ assertEquals(ctx.getAttribute("NotFileBased.openECOMP"),"SDN-C");
+ assertEquals(ctx.getAttribute("NotFileBased.<ignore"),"/>");
+ }
+
+ @Test
+ public void testNoFileTypeNoPrefixNotFileBased() throws SvcLogicException {
+ SvcLogicContext ctx = new SvcLogicContext();
+
+ Map<String, String> p = new HashMap<String, String>();
+ p.put("fileName", "src/test/resources/test");
+ p.put("fileBasedParsing","true");
+
+ PropertiesNode rcn = new PropertiesNode();
+ rcn.readProperties(p, ctx);
+
+ assertEquals(ctx.getAttribute("service-data.service-information.service-type"),"AVPN");
+ assertEquals(ctx.getAttribute("service-configuration-notification-input.response-code"),"0");
+ assertEquals(ctx.getAttribute("operational-data.avpn-ip-port-information.port-" +
+ "level-cos.queueing.pe-per-class-queueing-behaviors.cos3-queueing"),"WRED");
+ assertEquals(ctx.getAttribute("service-data.avpn-ip-port-information.avpn-" +
+ "access-information.l1-customer-handoff"),"_1000BASELX");
+ assertEquals(ctx.getAttribute("service-data.avpn-ip-port-information.avpn-" +
+ "access-information.vlan-tag-control"),"_1Q");
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void testNoFileTypeParseReqError() throws SvcLogicException {
+ SvcLogicContext ctx = new SvcLogicContext();
+
+ Map<String, String> p = new HashMap<String, String>();
+ p.put("file Name", "src/test/resources/test");
+ p.put("fileBasedParsing","true");
+
+ PropertiesNode rcn = new PropertiesNode();
+ rcn.readProperties(p, ctx);
+
+ assertEquals(ctx.getAttribute("service-data.service-information.service-type"),"AVPN");
+ assertEquals(ctx.getAttribute("service-configuration-notification-input.response-code"),"0");
+ assertEquals(ctx.getAttribute("operational-data.avpn-ip-port-information.port-" +
+ "level-cos.queueing.pe-per-class-queueing-behaviors.cos3-queueing"),"WRED");
+ assertEquals(ctx.getAttribute("service-data.avpn-ip-port-information.avpn-" +
+ "access-information.l1-customer-handoff"),"_1000BASELX");
+ assertEquals(ctx.getAttribute("service-data.avpn-ip-port-information.avpn-" +
+ "access-information.vlan-tag-control"),"_1Q");
+ }
+
+ @Test
+ public void testNoFileTypeParseError() throws SvcLogicException {
+ SvcLogicContext ctx = new SvcLogicContext();
+
+ Map<String, String> p = new HashMap<String, String>();
+ p.put("fileName", "src/test/resources/test");
+ p.put("file Based % Parsing","true");
+
+ PropertiesNode rcn = new PropertiesNode();
+ rcn.readProperties(p, ctx);
+
+ assertEquals(ctx.getAttribute("service-data.service-information.service-type"),"AVPN");
+ assertEquals(ctx.getAttribute("service-configuration-notification-input.response-code"),"0");
+ assertEquals(ctx.getAttribute("operational-data.avpn-ip-port-information.port-" +
+ "level-cos.queueing.pe-per-class-queueing-behaviors.cos3-queueing"),"WRED");
+ assertEquals(ctx.getAttribute("service-data.avpn-ip-port-information.avpn-" +
+ "access-information.l1-customer-handoff"),"_1000BASELX");
+ assertEquals(ctx.getAttribute("service-data.avpn-ip-port-information.avpn-" +
+ "access-information.vlan-tag-control"),"_1Q");
+ }
+}
diff --git a/plugins/properties-node/provider/src/test/java/jtest/org/onap/ccsdk/sli/plugins/prop/TestXmlParser.java b/plugins/properties-node/provider/src/test/java/jtest/org/onap/ccsdk/sli/plugins/prop/TestXmlParser.java
new file mode 100644
index 000000000..7cd072ed8
--- /dev/null
+++ b/plugins/properties-node/provider/src/test/java/jtest/org/onap/ccsdk/sli/plugins/prop/TestXmlParser.java
@@ -0,0 +1,121 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package jtest.org.onap.ccsdk.sli.plugins.prop;
+
+import org.junit.Test;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.plugins.prop.XmlParser;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+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 static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.Is.is;
+
+public class TestXmlParser {
+
+ private static final Logger log = LoggerFactory.getLogger(TestXmlParser.class);
+
+ @Test
+ public void test() throws Exception {
+ BufferedReader in = new BufferedReader(
+ new InputStreamReader(ClassLoader.getSystemResourceAsStream("test3.xml"))
+ );
+ StringBuilder b = new StringBuilder();
+ String line;
+ while ((line = in.readLine()) != null)
+ b.append(line).append('\n');
+
+ Set<String> listNameList = new HashSet<String>();
+ listNameList.add("project.dependencies.dependency");
+ listNameList.add("project.build.plugins.plugin");
+ listNameList.add("project.build.plugins.plugin.executions.execution");
+ listNameList.add("project.build.pluginManagement.plugins.plugin");
+ listNameList.add("project.build.pluginManagement." +
+ "plugins.plugin.configuration.lifecycleMappingMetadata.pluginExecutions.pluginExecution");
+
+ Map<String, String> mm = XmlParser.convertToProperties(b.toString(), listNameList);
+ logProperties(mm);
+ in.close();
+ }
+
+ @Test
+ public void testValidLength() throws Exception {
+ BufferedReader in = new BufferedReader(
+ new InputStreamReader(ClassLoader.getSystemResourceAsStream("test3.xml"))
+ );
+ StringBuilder b = new StringBuilder();
+ String line;
+ while ((line = in.readLine()) != null)
+ b.append(line).append('\n');
+
+ Set<String> listNameList = new HashSet<String>();
+ listNameList.add("ApplyGroupResponse.ApplyGroupResponseData.VrfDetails.VrfImport");
+ listNameList.add("ApplyGroupResponse.ApplyGroupResponseData.VrfDetails.VrfExport");
+
+ Map<String, String> mm = XmlParser.convertToProperties(b.toString(), listNameList);
+
+ assertThat(mm.get("ApplyGroupResponse.ApplyGroupResponseData.VrfDetails.VrfExport[5]"), is("SET_RESET_LP"));
+ assertThat(mm.get("ApplyGroupResponse.ApplyGroupResponseData.VrfDetails.VrfImport[0]"), is("SET_BVOIP_IN"));
+
+ logProperties(mm);
+ in.close();
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void testInvalidLength() throws Exception {
+ BufferedReader in = new BufferedReader(
+ new InputStreamReader(ClassLoader.getSystemResourceAsStream("invalidlength.xml"))
+ );
+ StringBuilder b = new StringBuilder();
+ String line;
+ while ((line = in.readLine()) != null)
+ b.append(line).append('\n');
+
+ Set<String> listNameList = new HashSet<String>();
+ listNameList.add("ApplyGroupResponse.ApplyGroupResponseData.VrfDetails.VrfImport");
+ listNameList.add("ApplyGroupResponse.ApplyGroupResponseData.VrfDetails.VrfExport");
+
+ Map<String, String> mm = XmlParser.convertToProperties(b.toString(), listNameList);
+ logProperties(mm);
+ in.close();
+ }
+
+ private void logProperties(Map<String, String> mm) {
+ List<String> ll = new ArrayList<>();
+ for (Object o : mm.keySet())
+ ll.add((String) o);
+ Collections.sort(ll);
+
+ log.info("Properties:");
+ for (String name : ll)
+ log.info("--- " + name + ": " + mm.get(name));
+ }
+}
diff --git a/plugins/properties-node/provider/src/test/resources/invalidlength.xml b/plugins/properties-node/provider/src/test/resources/invalidlength.xml
new file mode 100644
index 000000000..c086d564e
--- /dev/null
+++ b/plugins/properties-node/provider/src/test/resources/invalidlength.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!--
+ ============LICENSE_START=======================================================
+ openECOMP : SDN-C
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property. All rights
+ reserved.
+ ================================================================================
+ 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.
+ ============LICENSE_END=========================================================
+ -->
+
+<ApplyGroupResponse xmlns="http://onap.org/vpn/schema/v1"
+ xmlns:ns2="http://onap.org/prov/vpn/schema/v2">
+ <ApplyGroupResponseData>
+ <ServiceInstanceId>ICOREPVC-81114561</ServiceInstanceId>
+ <VrfDetails>
+ <End2EndVpnKey>VPNL811182</End2EndVpnKey>
+ <VpnId>811182</VpnId>
+ <VrfName>21302:811182</VrfName>
+ <VrfImport>SET_BVOIP_IN</VrfImport>
+ <VrfImport>SET6_BVOIP_IN</VrfImport>
+ <VrfExport_length>a</VrfExport_length>
+ <VrfExport>SET6_DSU</VrfExport>
+ <VrfExport>SET_DSU</VrfExport>
+ <VrfExport>SET6_MANAGED</VrfExport>
+ <VrfExport>SET_MANAGED</VrfExport>
+ <VrfExport>SET_LOVRF_COMMUNITY</VrfExport>
+ <VrfExport>SET_RESET_LP</VrfExport>
+ <ApplyGroup>
+ <ns2:ApplyGroup>AG_MAX_MCASTROUTES</ns2:ApplyGroup>
+ </ApplyGroup>
+ </VrfDetails>
+ </ApplyGroupResponseData>
+ <response-code>200</response-code>
+ <response-message>Success</response-message>
+ <ack-final-indicator>Y</ack-final-indicator>
+</ApplyGroupResponse>
+
diff --git a/plugins/properties-node/provider/src/test/resources/test b/plugins/properties-node/provider/src/test/resources/test
new file mode 100644
index 000000000..79e8acff4
--- /dev/null
+++ b/plugins/properties-node/provider/src/test/resources/test
@@ -0,0 +1,30 @@
+operational-data.avpn-ip-port-information.port-level-cos.queueing.pe-egress-class-queueing-policing-codes.cos2v-queueing-code = P
+operational-data.avpn-ip-port-information.port-level-cos.queueing.pe-egress-class-queueing-policing-codes.cos3-queueing-code = W
+operational-data.avpn-ip-port-information.port-level-cos.queueing.pe-per-class-queueing-behaviors.cos2-queueing = WRED
+operational-data.avpn-ip-port-information.port-level-cos.queueing.pe-per-class-queueing-behaviors.cos2v-queueing = QueueLimit
+operational-data.avpn-ip-port-information.port-level-cos.queueing.pe-per-class-queueing-behaviors.cos3-queueing = WRED
+operational-data.avpn-ip-port-information.port-level-cos.shaping.pe-egress-per-class-shaping-behaviors.cos2-shaping = Disable
+operational-data.avpn-ip-port-information.port-level-cos.shaping.pe-egress-per-class-shaping-behaviors.cos2v-shaping = Enable
+operational-data.avpn-ip-port-information.port-level-cos.shaping.pe-egress-per-class-shaping-behaviors.cos3-shaping = Disable
+operational-data.avpn-ip-port-information.port-level-cos.shaping.pe-egress-per-class-shaping-codes.cos2-shaping-code = W
+operational-data.avpn-ip-port-information.port-level-cos.shaping.pe-egress-per-class-shaping-codes.cos2v-shaping-code = P
+service-configuration-notification-input.ack-final-indicator = Y
+service-configuration-notification-input.response-code = 0
+service-configuration-notification-input.response-message = Plc Activation Failed: Device gblond2005me6 Sync-from Failed. Please check device IP address and NCS setup.
+service-configuration-notification-input.service-information.service-instance-id = TEST7
+service-configuration-notification-input.service-information.service-type = AVPN
+service-configuration-notification-input.svc-request-id = TEST7
+service-data.avpn-ip-port-information.avpn-access-information.access-circuit-id = DHEC.54831.170.ATI
+service-data.avpn-ip-port-information.avpn-access-information.access-interface = _1G
+service-data.avpn-ip-port-information.avpn-access-information.access-speed = 10000
+service-data.avpn-ip-port-information.avpn-access-information.access-speed-units = Kbps
+service-data.avpn-ip-port-information.avpn-access-information.l1-customer-handoff = _1000BASELX
+service-data.avpn-ip-port-information.avpn-access-information.managed-ce = N
+service-data.avpn-ip-port-information.avpn-access-information.vlan-tag-control = _1Q
+service-data.avpn-ip-port-information.clli = LONDENEH
+service-data.avpn-ip-port-information.contracted-port-speed = 10000
+service-data.avpn-ip-port-information.contracted-port-speed-units = Kbps
+service-data.avpn-ip-port-information.endpoint-information.bundle-id = 33
+service-data.avpn-ip-port-information.endpoint-information.interface-string = ae0
+service-data.service-information.service-instance-id = ICORESITE-2751508
+service-data.service-information.service-type = AVPN \ No newline at end of file
diff --git a/plugins/properties-node/provider/src/test/resources/test-invalid.json b/plugins/properties-node/provider/src/test/resources/test-invalid.json
new file mode 100644
index 000000000..21af3ac1d
--- /dev/null
+++ b/plugins/properties-node/provider/src/test/resources/test-invalid.json
@@ -0,0 +1,29 @@
+ "equipment-data": [
+ {
+ "server-count": "4",
+ "max-server-speed": "1600000",
+ "number-primary-servers": "2",
+ "equipment-id": "Server1",
+ "server-model": "Unknown",
+ "server-id": "Server1",
+ "test-node" : {
+ "test-inner-node" : "Test-Value"
+ }
+ }
+ ],
+ "resource-state": {
+ "threshold-value": "1600000",
+ "last-added": "1605000",
+ "used": "1605000",
+ "limit-value": "1920000"
+ },
+ "resource-rule": {
+ "endpoint-position": "VCE-Cust",
+ "soft-limit-expression": "0.6 * max-server-speed * number-primary-servers",
+ "resource-name": "Bandwidth",
+ "service-model": "DUMMY",
+ "hard-limit-expression": "max-server-speed * number-primary-servers",
+ "equipment-level": "Server"
+ },
+ "message": "The provisioned access bandwidth is at or exceeds 50% of the total server capacity."
+}
diff --git a/plugins/properties-node/provider/src/test/resources/test-invalid.xml b/plugins/properties-node/provider/src/test/resources/test-invalid.xml
new file mode 100644
index 000000000..50bd0fff2
--- /dev/null
+++ b/plugins/properties-node/provider/src/test/resources/test-invalid.xml
@@ -0,0 +1,170 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ============LICENSE_START=======================================================
+ openECOMP : SDN-C
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property. All rights
+ reserved.
+ ================================================================================
+ 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.
+ ============LICENSE_END=========================================================
+ -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.onap.ccsdk.sli.plugins</groupId>
+ <artifactId>restapi-call-node</artifactId>
+ <version>6.0.0-SNAPSHOT</version>
+ </parent>
+ <artifactId>restapi-call-node-provider</artifactId>
+ <packaging>bundle</packaging>
+ <name>RESTAPI Call Node - Provider</name>
+ <url>http://maven.apache.org</url>
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-test</artifactId>
+ <version>3.1.4.RELEASE</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli</groupId>
+ <artifactId>sli-common</artifactId>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli</groupId>
+ <artifactId>sli-provider</artifactId>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ <version>${slf4j.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>jcl-over-slf4j</artifactId>
+ <version>${slf4j.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-beans</artifactId>
+ <version>3.1.4.RELEASE</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-context</artifactId>
+ <version>3.1.4.RELEASE</version>
+ </dependency>
+ <dependency>
+ <groupId>xerces</groupId>
+ <artifactId>xerces</artifactId>
+ <version>2.4.0</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.sun.jersey</groupId>
+ <artifactId>jersey-client</artifactId>
+ <version>1.17</version>
+ </dependency>
+ <dependency>
+ <groupId>com.s
+
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>com.brocade.developer</groupId>
+ <artifactId>providermodule-plugin</artifactId>
+ <configuration>
+ <packageId>org.onap.ccsdk.sli.plugins</packageId>
+ <appName>restapi-call-node</appName>
+ </configuration>
+ <executions>
+ <execution>
+ <phase>process-sources</phase>
+ <goals>
+ <goal>process</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+
+
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Bundle-SymbolicName>org.onap.ccsdk.sli.plugins.restapicall</Bundle-SymbolicName>
+ <Export-Package>org.onap.ccsdk.sli.plugins.restapicall</Export-Package>
+ <Import-Package>*</Import-Package>
+ </instructions>
+
+ <manifestLocation>${project.basedir}/src/main/resources/META-INF</manifestLocation>
+
+ </configuration>
+
+ </plugin>
+
+
+ </plugins>
+ <pluginManagement>
+ <plugins>
+ <!--This plugin's configuration is used to store Eclipse m2e settings
+ only. It has no influence on the Maven build itself. -->
+ <plugin>
+ <groupId>org.eclipse.m2e</groupId>
+ <artifactId>lifecycle-mapping</artifactId>
+ <version>1.0.0</version>
+ <configuration>
+ <lifecycleMappingMetadata>
+ <pluginExecutions>
+ <pluginExecution>
+ <pluginExecutionFilter>
+ <groupId>
+ com.brocade.developer
+ </groupId>
+ <artifactId>
+ providermodule-plugin
+ </artifactId>
+ <versionRange>
+ [1.2.0.100-SNAPSHOT,)
+ </versionRange>
+ <goals>
+ <goal>process</goal>
+ </goals>
+ </pluginExecutionFilter>
+ <action>
+ <ignore />
+ </action>
+ </pluginExecution>
+ </pluginExecutions>
+ </lifecycleMappingMetadata>
+ </configuration>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+</project>
diff --git a/plugins/properties-node/provider/src/test/resources/test.json b/plugins/properties-node/provider/src/test/resources/test.json
new file mode 100644
index 000000000..75155393c
--- /dev/null
+++ b/plugins/properties-node/provider/src/test/resources/test.json
@@ -0,0 +1,30 @@
+{
+ "equipment-data": [
+ {
+ "server-count": "4",
+ "max-server-speed": "1600000",
+ "number-primary-servers": "2",
+ "equipment-id": "Server1",
+ "server-model": "Unknown",
+ "server-id": "Server1",
+ "test-node" : {
+ "test-inner-node" : "Test-Value"
+ }
+ }
+ ],
+ "resource-state": {
+ "threshold-value": "1600000",
+ "last-added": "1605000",
+ "used": "1605000",
+ "limit-value": "1920000"
+ },
+ "resource-rule": {
+ "endpoint-position": "VCE-Cust",
+ "soft-limit-expression": "0.6 * max-server-speed * number-primary-servers",
+ "resource-name": "Bandwidth",
+ "service-model": "DUMMY",
+ "hard-limit-expression": "max-server-speed * number-primary-servers",
+ "equipment-level": "Server"
+ },
+ "message": "The provisioned access bandwidth is at or exceeds 50% of the total server capacity."
+}
diff --git a/plugins/properties-node/provider/src/test/resources/test.txt b/plugins/properties-node/provider/src/test/resources/test.txt
new file mode 100644
index 000000000..68b916cbb
--- /dev/null
+++ b/plugins/properties-node/provider/src/test/resources/test.txt
@@ -0,0 +1,31 @@
+operational-data.avpn-ip-port-information.port-level-cos.queueing.pe-egress-class-queueing-policing-codes.cos2v-queueing-code = P
+operational-data.avpn-ip-port-information.port-level-cos.queueing.pe-egress-class-queueing-policing-codes.cos3-queueing-code = W
+operational-data.avpn-ip-port-information.port-level-cos.queueing.pe-per-class-queueing-behaviors.cos2-queueing = WRED
+operational-data.avpn-ip-port-information.port-level-cos.queueing.pe-per-class-queueing-behaviors.cos2v-queueing = QueueLimit
+operational-data.avpn-ip-port-information.port-level-cos.queueing.pe-per-class-queueing-behaviors.cos3-queueing = WRED
+operational-data.avpn-ip-port-information.port-level-cos.shaping.pe-egress-per-class-shaping-behaviors.cos2-shaping = Disable
+operational-data.avpn-ip-port-information.port-level-cos.shaping.pe-egress-per-class-shaping-behaviors.cos2v-shaping = Enable
+operational-data.avpn-ip-port-information.port-level-cos.shaping.pe-egress-per-class-shaping-behaviors.cos3-shaping = Disable
+operational-data.avpn-ip-port-information.port-level-cos.shaping.pe-egress-per-class-shaping-codes.cos2-shaping-code = W
+operational-data.avpn-ip-port-information.port-level-cos.shaping.pe-egress-per-class-shaping-codes.cos2v-shaping-code = P
+service-configuration-notification-input.ack-final-indicator = Y
+service-configuration-notification-input.response-code = 0
+service-configuration-notification-input.response-message = Plc Activation Failed: Device gblond2005me6 Sync-from Failed. Please check device IP address and NCS setup.
+service-configuration-notification-input.service-information.service-instance-id = TEST7
+service-configuration-notification-input.service-information.service-type = AVPN
+service-configuration-notification-input.svc-request-id = TEST7
+service-data.avpn-ip-port-information.avpn-access-information.access-circuit-id = DHEC.54831.170.ATI
+service-data.avpn-ip-port-information.avpn-access-information.access-interface = _1G
+service-data.avpn-ip-port-information.avpn-access-information.access-speed = 10000
+service-data.avpn-ip-port-information.avpn-access-information.access-speed-units = Kbps
+service-data.avpn-ip-port-information.avpn-access-information.l1-customer-handoff = _1000BASELX
+service-data.avpn-ip-port-information.avpn-access-information.managed-ce = N
+service-data.avpn-ip-port-information.avpn-access-information.vlan-tag-control = _1Q
+service-data.avpn-ip-port-information.clli = LONDENEH
+service-data.avpn-ip-port-information.contracted-port-speed = 10000
+service-data.avpn-ip-port-information.contracted-port-speed-units = Kbps
+service-data.avpn-ip-port-information.endpoint-information.bundle-id = 33
+service-data.avpn-ip-port-information.endpoint-information.interface-string = ae0
+service-data.service-information.service-instance-id = ICORESITE-2751508
+service-data.service-information.service-type = AVPN
+obfuscated-var=${deployer_pass}
diff --git a/plugins/properties-node/provider/src/test/resources/test.xml b/plugins/properties-node/provider/src/test/resources/test.xml
new file mode 100644
index 000000000..19e3b7139
--- /dev/null
+++ b/plugins/properties-node/provider/src/test/resources/test.xml
@@ -0,0 +1,182 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ============LICENSE_START=======================================================
+ openECOMP : SDN-C
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property. All rights
+ reserved.
+ ================================================================================
+ 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.
+ ============LICENSE_END=========================================================
+ -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.onap.ccsdk.sli.plugins</groupId>
+ <artifactId>restapi-call-node</artifactId>
+ <version>6.0.0-SNAPSHOT</version>
+ </parent>
+ <artifactId>restapi-call-node-provider</artifactId>
+ <packaging>bundle</packaging>
+ <name>RESTAPI Call Node - Provider</name>
+ <url>http://maven.apache.org</url>
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-test</artifactId>
+ <version>3.1.4.RELEASE</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli</groupId>
+ <artifactId>sli-common</artifactId>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli</groupId>
+ <artifactId>sli-provider</artifactId>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ <version>${slf4j.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>jcl-over-slf4j</artifactId>
+ <version>${slf4j.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-beans</artifactId>
+ <version>3.1.4.RELEASE</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-context</artifactId>
+ <version>3.1.4.RELEASE</version>
+ </dependency>
+ <dependency>
+ <groupId>xerces</groupId>
+ <artifactId>xerces</artifactId>
+ <version>2.4.0</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.sun.jersey</groupId>
+ <artifactId>jersey-client</artifactId>
+ <version>1.17</version>
+ </dependency>
+ <dependency>
+ <groupId>com.sun.jersey.contribs.jersey-oauth</groupId>
+ <artifactId>oauth-signature</artifactId>
+ <version>1.17</version>
+ </dependency>
+ <dependency>
+ <groupId>com.sun.jersey.contribs.jersey-oauth</groupId>
+ <artifactId>oauth-client</artifactId>
+ <version>1.17</version>
+ </dependency>
+ <dependency>
+ <groupId>commons-codec</groupId>
+ <artifactId>commons-codec</artifactId>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>com.brocade.developer</groupId>
+ <artifactId>providermodule-plugin</artifactId>
+ <configuration>
+ <packageId>org.onap.ccsdk.sli.plugins</packageId>
+ <appName>restapi-call-node</appName>
+ </configuration>
+ <executions>
+ <execution>
+ <phase>process-sources</phase>
+ <goals>
+ <goal>process</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+
+
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Bundle-SymbolicName>org.onap.ccsdk.sli.plugins.restapicall</Bundle-SymbolicName>
+ <Export-Package>org.onap.ccsdk.sli.plugins.restapicall</Export-Package>
+ <Import-Package>*</Import-Package>
+ </instructions>
+
+ <manifestLocation>${project.basedir}/src/main/resources/META-INF</manifestLocation>
+
+ </configuration>
+
+ </plugin>
+
+
+ </plugins>
+ <pluginManagement>
+ <plugins>
+ <!--This plugin's configuration is used to store Eclipse m2e settings
+ only. It has no influence on the Maven build itself. -->
+ <plugin>
+ <groupId>org.eclipse.m2e</groupId>
+ <artifactId>lifecycle-mapping</artifactId>
+ <version>1.0.0</version>
+ <configuration>
+ <lifecycleMappingMetadata>
+ <pluginExecutions>
+ <pluginExecution>
+ <pluginExecutionFilter>
+ <groupId>
+ com.brocade.developer
+ </groupId>
+ <artifactId>
+ providermodule-plugin
+ </artifactId>
+ <versionRange>
+ [1.2.0.100,)
+ </versionRange>
+ <goals>
+ <goal>process</goal>
+ </goals>
+ </pluginExecutionFilter>
+ <action>
+ <ignore />
+ </action>
+ </pluginExecution>
+ </pluginExecutions>
+ </lifecycleMappingMetadata>
+ </configuration>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+</project>
diff --git a/plugins/properties-node/provider/src/test/resources/test3.xml b/plugins/properties-node/provider/src/test/resources/test3.xml
new file mode 100644
index 000000000..ade412681
--- /dev/null
+++ b/plugins/properties-node/provider/src/test/resources/test3.xml
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!--
+ ============LICENSE_START=======================================================
+ openECOMP : SDN-C
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property. All rights
+ reserved.
+ ================================================================================
+ 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.
+ ============LICENSE_END=========================================================
+ -->
+
+<ApplyGroupResponse xmlns="http://onap.org/vpn/schema/v1"
+ xmlns:ns2="http://onap.org/prov/vpn/schema/v2">
+ <ApplyGroupResponseData>
+ <ServiceInstanceId>ICOREPVC-81114561</ServiceInstanceId>
+ <VrfDetails>
+ <End2EndVpnKey>VPNL811182</End2EndVpnKey>
+ <VpnId>811182</VpnId>
+ <VrfName>21302:811182</VrfName>
+ <VrfImport>SET_BVOIP_IN</VrfImport>
+ <VrfImport>SET6_BVOIP_IN</VrfImport>
+ <VrfExport>SET6_DSU</VrfExport>
+ <VrfExport>SET_DSU</VrfExport>
+ <VrfExport>SET6_MANAGED</VrfExport>
+ <VrfExport>SET_MANAGED</VrfExport>
+ <VrfExport>SET_LOVRF_COMMUNITY</VrfExport>
+ <VrfExport>SET_RESET_LP</VrfExport>
+ <ApplyGroup>
+ <ns2:ApplyGroup>AG_MAX_MCASTROUTES</ns2:ApplyGroup>
+ </ApplyGroup>
+ </VrfDetails>
+ <RoutingApplyGroups>
+ <RoutingProtocol>BGP4_PROTOCOL</RoutingProtocol>
+ <Family>v4</Family>
+ <PeerGroupName>gp_21302:811182</PeerGroupName>
+ <ApplyGroupPeer>
+ <ns2:ApplyGroup>AG_L3VPN_EBGP</ns2:ApplyGroup>
+ </ApplyGroupPeer>
+ <ApplyGroupPeer>
+ <ns2:ApplyGroup>AG_MAX_PREFIX</ns2:ApplyGroup>
+ </ApplyGroupPeer>
+ <ApplyGroupNeighbour>
+ <ns2:ApplyGroup>AG_BGP_UNMANAGED</ns2:ApplyGroup>
+ </ApplyGroupNeighbour>
+ <ApplyGroupNeighbour>
+ <ns2:ApplyGroup>AG_BFD_BGP_3000</ns2:ApplyGroup>
+ </ApplyGroupNeighbour>
+ </RoutingApplyGroups>
+ <RoutingApplyGroups>
+ <RoutingProtocol>BGP4_PROTOCOL</RoutingProtocol>
+ <Family>v6</Family>
+ <PeerGroupName>gp6_21302:811182</PeerGroupName>
+ <ApplyGroupPeer>
+ <ns2:ApplyGroup>AG6_L3VPN_EBGP</ns2:ApplyGroup>
+ </ApplyGroupPeer>
+ <ApplyGroupPeer>
+ <ns2:ApplyGroup>AG6_MAX_PREFIX</ns2:ApplyGroup>
+ </ApplyGroupPeer>
+ <ApplyGroupNeighbour>
+ <ns2:ApplyGroup>AG6_BGP_UNMANAGED</ns2:ApplyGroup>
+ </ApplyGroupNeighbour>
+ <ApplyGroupNeighbour>
+ <ns2:ApplyGroup>AG6_BFD_BGP_3000</ns2:ApplyGroup>
+ </ApplyGroupNeighbour>
+ </RoutingApplyGroups>
+ </ApplyGroupResponseData>
+ <response-code>200</response-code>
+ <response-message>Success</response-message>
+ <ack-final-indicator>Y</ack-final-indicator>
+</ApplyGroupResponse>
+
diff --git a/plugins/releases/0.5.0.yaml b/plugins/releases/0.5.0.yaml
new file mode 100644
index 000000000..37ba918ab
--- /dev/null
+++ b/plugins/releases/0.5.0.yaml
@@ -0,0 +1,5 @@
+---
+distribution_type: 'maven'
+version: '0.5.0'
+project: 'ccsdk-sli-plugins'
+log_dir: 'ccsdk-sli-plugins-maven-stage-master/160/'
diff --git a/plugins/releases/0.5.1.yaml b/plugins/releases/0.5.1.yaml
new file mode 100644
index 000000000..ca3ff0c0e
--- /dev/null
+++ b/plugins/releases/0.5.1.yaml
@@ -0,0 +1,5 @@
+---
+distribution_type: 'maven'
+version: '0.5.1'
+project: 'ccsdk-sli-plugins'
+log_dir: 'ccsdk-sli-plugins-maven-stage-master/166/'
diff --git a/plugins/releases/0.5.2.yaml b/plugins/releases/0.5.2.yaml
new file mode 100644
index 000000000..4c7946b28
--- /dev/null
+++ b/plugins/releases/0.5.2.yaml
@@ -0,0 +1,5 @@
+---
+distribution_type: 'maven'
+version: '0.5.2'
+project: 'ccsdk-sli-plugins'
+log_dir: 'ccsdk-sli-plugins-maven-stage-master/173/'
diff --git a/plugins/releases/0.6.0.yaml b/plugins/releases/0.6.0.yaml
new file mode 100644
index 000000000..8f32b423b
--- /dev/null
+++ b/plugins/releases/0.6.0.yaml
@@ -0,0 +1,5 @@
+---
+distribution_type: 'maven'
+version: '0.6.0'
+project: 'ccsdk-sli-plugins'
+log_dir: 'ccsdk-sli-plugins-maven-stage-master/187/'
diff --git a/plugins/releases/0.6.1.yaml b/plugins/releases/0.6.1.yaml
new file mode 100644
index 000000000..7739acdeb
--- /dev/null
+++ b/plugins/releases/0.6.1.yaml
@@ -0,0 +1,5 @@
+---
+distribution_type: 'maven'
+version: '0.6.1'
+project: 'ccsdk-sli-plugins'
+log_dir: 'ccsdk-sli-plugins-maven-stage-master/204/'
diff --git a/plugins/releases/0.7.0.yaml b/plugins/releases/0.7.0.yaml
new file mode 100644
index 000000000..e86406631
--- /dev/null
+++ b/plugins/releases/0.7.0.yaml
@@ -0,0 +1,5 @@
+---
+distribution_type: 'maven'
+version: '0.7.0'
+project: 'ccsdk-sli-plugins'
+log_dir: 'ccsdk-sli-plugins-maven-stage-master/300/'
diff --git a/plugins/releases/0.7.1.yaml b/plugins/releases/0.7.1.yaml
new file mode 100644
index 000000000..990922216
--- /dev/null
+++ b/plugins/releases/0.7.1.yaml
@@ -0,0 +1,5 @@
+---
+distribution_type: 'maven'
+version: '0.7.1'
+project: 'ccsdk-sli-plugins'
+log_dir: 'ccsdk-sli-plugins-maven-stage-master/301/'
diff --git a/plugins/releases/1.0.0.yaml b/plugins/releases/1.0.0.yaml
new file mode 100644
index 000000000..ca1f69cf8
--- /dev/null
+++ b/plugins/releases/1.0.0.yaml
@@ -0,0 +1,5 @@
+---
+distribution_type: 'maven'
+version: '1.0.0'
+project: 'ccsdk-sli-plugins'
+log_dir: 'ccsdk-sli-plugins-maven-stage-master/302/'
diff --git a/plugins/releases/1.0.1.yaml b/plugins/releases/1.0.1.yaml
new file mode 100644
index 000000000..bb233a9a5
--- /dev/null
+++ b/plugins/releases/1.0.1.yaml
@@ -0,0 +1,5 @@
+---
+distribution_type: 'maven'
+version: '1.0.1'
+project: 'ccsdk-sli-plugins'
+log_dir: 'ccsdk-sli-plugins-maven-stage-master/303/'
diff --git a/plugins/releases/1.1.0.yaml b/plugins/releases/1.1.0.yaml
new file mode 100644
index 000000000..75773b2c3
--- /dev/null
+++ b/plugins/releases/1.1.0.yaml
@@ -0,0 +1,5 @@
+---
+distribution_type: 'maven'
+version: '1.1.0'
+project: 'ccsdk-sli-plugins'
+log_dir: 'ccsdk-sli-plugins-maven-stage-master/304/'
diff --git a/plugins/restapi-call-node/.gitignore b/plugins/restapi-call-node/.gitignore
new file mode 100755
index 000000000..b73caf31e
--- /dev/null
+++ b/plugins/restapi-call-node/.gitignore
@@ -0,0 +1,34 @@
+#####standard .git ignore entries#####
+
+## IDE Specific Files ##
+org.eclipse.core.resources.prefs
+.classpath
+.project
+.settings
+.idea
+.externalToolBuilders
+maven-eclipse.xml
+workspace
+
+## Compilation Files ##
+*.class
+**/target
+target
+target-ide
+MANIFEST.MF
+
+## Misc Ignores (OS specific etc) ##
+bin/
+dist
+*~
+*.ipr
+*.iml
+*.iws
+classes
+out/
+.DS_STORE
+.metadata
+
+## Folders which contain auto generated source code ##
+yang-gen-config
+yang-gen-sal
diff --git a/plugins/restapi-call-node/installer/pom.xml b/plugins/restapi-call-node/installer/pom.xml
new file mode 100755
index 000000000..fbf2cff60
--- /dev/null
+++ b/plugins/restapi-call-node/installer/pom.xml
@@ -0,0 +1,125 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>odlparent-lite</artifactId>
+ <version>2.1.0</version>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.plugins</groupId>
+ <artifactId>restapi-call-node-installer</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>pom</packaging>
+
+ <name>ccsdk-sli-plugins :: restapi-call-node :: ${project.artifactId}</name>
+
+ <properties>
+ <application.name>ccsdk-restapi-call-node</application.name>
+ <features.boot>${application.name}</features.boot>
+ <features.repositories>mvn:org.onap.ccsdk.sli.plugins/${features.boot}/${project.version}/xml/features</features.repositories>
+ <include.transitive.dependencies>false</include.transitive.dependencies>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.plugins</groupId>
+ <artifactId>restapi-call-node-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <version>2.6</version>
+ <executions>
+ <execution>
+ <id>maven-repo-zip</id>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ <phase>package</phase>
+ <configuration>
+ <attach>true</attach>
+ <finalName>stage/${application.name}-${project.version}</finalName>
+ <descriptors>
+ <descriptor>src/assembly/assemble_mvnrepo_zip.xml</descriptor>
+ </descriptors>
+ <appendAssemblyId>true</appendAssemblyId>
+ </configuration>
+ </execution>
+ <execution>
+ <id>installer-zip</id>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ <phase>package</phase>
+ <configuration>
+ <attach>true</attach>
+ <finalName>${application.name}-${project.version}-installer</finalName>
+ <descriptors>
+ <descriptor>src/assembly/assemble_installer_zip.xml</descriptor>
+ </descriptors>
+ <appendAssemblyId>false</appendAssemblyId>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>copy-dependencies</id>
+ <goals>
+ <goal>copy-dependencies</goal>
+ </goals>
+ <phase>prepare-package</phase>
+ <configuration>
+ <transitive>false</transitive>
+ <outputDirectory>${project.build.directory}/assembly/system</outputDirectory>
+ <overWriteReleases>false</overWriteReleases>
+ <overWriteSnapshots>true</overWriteSnapshots>
+ <overWriteIfNewer>true</overWriteIfNewer>
+ <useRepositoryLayout>true</useRepositoryLayout>
+ <addParentPoms>false</addParentPoms>
+ <copyPom>false</copyPom>
+ <includeGroupIds>org.onap.ccsdk.sli.plugins</includeGroupIds>
+ <scope>provided</scope>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <artifactId>maven-resources-plugin</artifactId>
+ <version>2.6</version>
+ <executions>
+ <execution>
+ <id>copy-version</id>
+ <goals>
+ <goal>copy-resources</goal>
+ </goals><!-- here the phase you need -->
+ <phase>validate</phase>
+ <configuration>
+ <outputDirectory>${basedir}/target/stage</outputDirectory>
+ <resources>
+ <resource>
+ <directory>src/main/resources/scripts</directory>
+ <includes>
+ <include>install-feature.sh</include>
+ </includes>
+ <filtering>true</filtering>
+ </resource>
+ </resources>
+ </configuration>
+ </execution>
+
+ </executions>
+ </plugin>
+
+ </plugins>
+ </build>
+</project>
diff --git a/plugins/restapi-call-node/installer/src/assembly/assemble_installer_zip.xml b/plugins/restapi-call-node/installer/src/assembly/assemble_installer_zip.xml
new file mode 100644
index 000000000..3bed4b5ef
--- /dev/null
+++ b/plugins/restapi-call-node/installer/src/assembly/assemble_installer_zip.xml
@@ -0,0 +1,59 @@
+<!--
+ ============LICENSE_START=======================================================
+ openECOMP : SDN-C
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property. All rights
+ reserved.
+ ================================================================================
+ 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.
+ ============LICENSE_END=========================================================
+ -->
+
+<!-- Defines how we build the .zip file which is our distribution. -->
+
+<assembly
+ xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
+ <id>installer_zip</id>
+ <formats>
+ <format>zip</format>
+ </formats>
+
+ <!-- we want "system" and related files right at the root level
+ as this file is suppose to be unzip on top of a karaf
+ distro. -->
+ <includeBaseDirectory>false</includeBaseDirectory>
+
+ <fileSets>
+ <fileSet>
+ <directory>target/stage/</directory>
+ <outputDirectory>${application.name}</outputDirectory>
+ <fileMode>755</fileMode>
+ <includes>
+ <include>*.sh</include>
+ </includes>
+ </fileSet>
+ <fileSet>
+ <directory>target/stage/</directory>
+ <outputDirectory>${application.name}</outputDirectory>
+ <fileMode>644</fileMode>
+ <excludes>
+ <exclude>*.sh</exclude>
+ </excludes>
+ </fileSet>
+ </fileSets>
+
+
+
+</assembly>
diff --git a/plugins/restapi-call-node/installer/src/assembly/assemble_mvnrepo_zip.xml b/plugins/restapi-call-node/installer/src/assembly/assemble_mvnrepo_zip.xml
new file mode 100644
index 000000000..35e79db18
--- /dev/null
+++ b/plugins/restapi-call-node/installer/src/assembly/assemble_mvnrepo_zip.xml
@@ -0,0 +1,49 @@
+<!--
+ ============LICENSE_START=======================================================
+ openECOMP : SDN-C
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property. All rights
+ reserved.
+ ================================================================================
+ 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.
+ ============LICENSE_END=========================================================
+ -->
+
+<!-- Defines how we build the .zip file which is our distribution. -->
+
+<assembly
+ xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
+ <id>repo</id>
+ <formats>
+ <format>zip</format>
+ </formats>
+
+ <!-- we want "system" and related files right at the root level
+ as this file is suppose to be unzip on top of a karaf
+ distro. -->
+ <includeBaseDirectory>false</includeBaseDirectory>
+
+ <fileSets>
+ <fileSet>
+ <directory>target/assembly/</directory>
+ <outputDirectory>.</outputDirectory>
+ <excludes>
+ </excludes>
+ </fileSet>
+ </fileSets>
+
+
+
+</assembly>
diff --git a/plugins/restapi-call-node/installer/src/main/resources/scripts/install-feature.sh b/plugins/restapi-call-node/installer/src/main/resources/scripts/install-feature.sh
new file mode 100644
index 000000000..6e3d4169d
--- /dev/null
+++ b/plugins/restapi-call-node/installer/src/main/resources/scripts/install-feature.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+
+###
+# ============LICENSE_START=======================================================
+# openECOMP : SDN-C
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights
+# reserved.
+# ================================================================================
+# 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.
+# ============LICENSE_END=========================================================
+###
+
+ODL_HOME=${ODL_HOME:-/opt/opendaylight/current}
+ODL_KARAF_CLIENT=${ODL_KARAF_CLIENT:-${ODL_HOME}/bin/client}
+INSTALLERDIR=$(dirname $0)
+
+REPOZIP=${INSTALLERDIR}/${features.boot}-${project.version}.zip
+
+if [ -f ${REPOZIP} ]
+then
+ unzip -nd ${ODL_HOME} ${REPOZIP}
+else
+ echo "ERROR : repo zip ($REPOZIP) not found"
+ exit 1
+fi
+
+${ODL_KARAF_CLIENT} feature:repo-add ${features.repositories}
+${ODL_KARAF_CLIENT} feature:install ${features.boot}
diff --git a/plugins/restapi-call-node/pom.xml b/plugins/restapi-call-node/pom.xml
new file mode 100755
index 000000000..c5b753305
--- /dev/null
+++ b/plugins/restapi-call-node/pom.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>odlparent-lite</artifactId>
+ <version>2.1.0</version>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.plugins</groupId>
+ <artifactId>restapi-call-node</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>pom</packaging>
+
+ <name>ccsdk-sli-plugins :: restapi-call-node</name>
+ <description>This is an implementation of DG Execute Node that makes a call to an external REST API</description>
+
+ <modules>
+ <module>provider</module>
+ <module>installer</module>
+ </modules>
+</project>
diff --git a/plugins/restapi-call-node/provider/pom.xml b/plugins/restapi-call-node/provider/pom.xml
new file mode 100755
index 000000000..89711519a
--- /dev/null
+++ b/plugins/restapi-call-node/provider/pom.xml
@@ -0,0 +1,94 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>binding-parent</artifactId>
+ <version>2.1.0</version>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.plugins</groupId>
+ <artifactId>restapi-call-node-provider</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>bundle</packaging>
+
+ <name>ccsdk-sli-plugins :: restapi-call-node :: ${project.artifactId}</name>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sli-core-artifacts</artifactId>
+ <version>${ccsdk.sli.core.version}</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>javax.ws.rs</groupId>
+ <artifactId>javax.ws.rs-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sli-common</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.bundles.repackaged</groupId>
+ <artifactId>jersey-guava</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.security</groupId>
+ <artifactId>oauth1-signature</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.security</groupId>
+ <artifactId>oauth1-client</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.codehaus.jettison</groupId>
+ <artifactId>jettison</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.core</groupId>
+ <artifactId>jersey-client</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.media</groupId>
+ <artifactId>jersey-media-multipart</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.logging-analytics</groupId>
+ <artifactId>logging-filter-base</artifactId>
+ </dependency>
+ <!-- For test -->
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.github.stefanbirkner</groupId>
+ <artifactId>system-rules</artifactId>
+ <version>1.19.0</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-grizzly2-http</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/plugins/restapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/restapicall/AuthType.java b/plugins/restapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/restapicall/AuthType.java
new file mode 100644
index 000000000..851dc9cc8
--- /dev/null
+++ b/plugins/restapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/restapicall/AuthType.java
@@ -0,0 +1,19 @@
+package org.onap.ccsdk.sli.plugins.restapicall;
+
+public enum AuthType {
+ NONE, BASIC, DIGEST, OAUTH, Unspecified;
+
+ public static AuthType fromString(String s) {
+ if ("basic".equalsIgnoreCase(s))
+ return BASIC;
+ if ("digest".equalsIgnoreCase(s))
+ return DIGEST;
+ if ("oauth".equalsIgnoreCase(s))
+ return OAUTH;
+ if ("none".equalsIgnoreCase(s))
+ return NONE;
+ if ("unspecified".equalsIgnoreCase(s))
+ return Unspecified;
+ throw new IllegalArgumentException("Invalid value for format: " + s);
+ }
+}
diff --git a/plugins/restapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/restapicall/Format.java b/plugins/restapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/restapicall/Format.java
new file mode 100644
index 000000000..1578ee320
--- /dev/null
+++ b/plugins/restapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/restapicall/Format.java
@@ -0,0 +1,36 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.restapicall;
+
+public enum Format {
+ JSON, XML, NONE;
+
+ public static Format fromString(String s) {
+ if ("json".equalsIgnoreCase(s))
+ return JSON;
+ if ("xml".equalsIgnoreCase(s))
+ return XML;
+ if ("none".equalsIgnoreCase(s))
+ return NONE;
+ throw new IllegalArgumentException("Invalid value for format: " + s);
+ }
+}
diff --git a/plugins/restapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/restapicall/HttpMethod.java b/plugins/restapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/restapicall/HttpMethod.java
new file mode 100644
index 000000000..b2f618a1c
--- /dev/null
+++ b/plugins/restapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/restapicall/HttpMethod.java
@@ -0,0 +1,43 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * Modifications Copyright © 2018 IBM.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.restapicall;
+
+public enum HttpMethod {
+ GET, POST, PUT, DELETE, PATCH;
+
+ public static HttpMethod fromString(String s) {
+ if (s == null)
+ return null;
+ if (("get").equalsIgnoreCase(s))
+ return GET;
+ if (("post").equalsIgnoreCase(s))
+ return POST;
+ if (("put").equalsIgnoreCase(s))
+ return PUT;
+ if (("delete").equalsIgnoreCase(s))
+ return DELETE;
+ if (("patch").equalsIgnoreCase(s))
+ return PATCH;
+ throw new IllegalArgumentException("Invalid value for HTTP Method: " + s);
+ }
+}
diff --git a/plugins/restapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/restapicall/HttpResponse.java b/plugins/restapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/restapicall/HttpResponse.java
new file mode 100644
index 000000000..574089528
--- /dev/null
+++ b/plugins/restapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/restapicall/HttpResponse.java
@@ -0,0 +1,34 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.restapicall;
+
+import java.util.List;
+import java.util.Map;
+import javax.ws.rs.core.MultivaluedMap;
+
+public class HttpResponse {
+ public int code;
+ public String message;
+ public String body;
+ public MultivaluedMap<String, String> headers;
+ public Map<String, List<String>> headers2;
+}
diff --git a/plugins/restapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/restapicall/JsonParser.java b/plugins/restapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/restapicall/JsonParser.java
new file mode 100644
index 000000000..60d43df7a
--- /dev/null
+++ b/plugins/restapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/restapicall/JsonParser.java
@@ -0,0 +1,153 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.restapicall;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import org.apache.commons.lang3.StringUtils;
+import org.codehaus.jettison.json.JSONArray;
+import org.codehaus.jettison.json.JSONException;
+import org.codehaus.jettison.json.JSONObject;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+public final class JsonParser {
+
+ private static final Logger log = LoggerFactory.getLogger(JsonParser.class);
+
+ private JsonParser() {
+ // Preventing instantiation of the same.
+ }
+
+
+ private static void handleJsonArray(String key, Map<String, Object> jArrayMap, JSONArray jsonArr) throws JSONException {
+ JSONObject jsonObj;
+ JSONArray subJsonArr;
+ boolean stripKey = false;
+
+ for (int i = 0, length = jsonArr.length(); i < length; i++) {
+ if (stripKey)
+ key = key.substring(0, key.length()-3);
+
+ subJsonArr = jsonArr.optJSONArray(i);
+ if (subJsonArr != null) {
+ key = StringUtils.trimToEmpty(key) + "[" + i + "]";
+ jArrayMap.putIfAbsent(key + "_length", String.valueOf(subJsonArr.length()));
+ handleJsonArray(key, jArrayMap, subJsonArr);
+ stripKey = true;
+ continue;
+ }
+
+ jsonObj = jsonArr.optJSONObject(i);
+ if (jsonObj != null) {
+ Iterator<String> ii = jsonObj.keys();
+ while (ii.hasNext()) {
+ String nodeKey = ii.next();
+ String key1 = "[" + i + "]." + nodeKey;
+ String[] subKey = key1.split(":");
+ if (subKey.length == 2) {
+ jArrayMap.putIfAbsent(subKey[1], jsonObj.get(nodeKey));
+ } else {
+ jArrayMap.putIfAbsent(key1, jsonObj.get(nodeKey));
+ }
+ }
+ }
+ else {
+ jArrayMap.putIfAbsent(StringUtils.trimToEmpty(key), jsonArr);
+ break;
+ }
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public static Map<String, String> convertToProperties(String s)
+ throws SvcLogicException {
+
+ checkNotNull(s, "Input should not be null.");
+
+ try {
+ Map<String, Object> wm = new HashMap<>();
+ JSONObject json;
+ JSONArray jsonArr;
+ //support top level list in json response
+ if (s.startsWith("[")) {
+ jsonArr = new JSONArray(s);
+ wm.put("_length", String.valueOf(jsonArr.length()));
+ handleJsonArray(null, wm, jsonArr);
+ } else {
+ json = new JSONObject(s);
+ Iterator<String> ii = json.keys();
+ while (ii.hasNext()) {
+ String key1 = ii.next();
+ String[] subKey = key1.split(":");
+ if (subKey.length == 2) {
+ wm.put(subKey[1], json.get(key1));
+ } else {
+ wm.put(key1, json.get(key1));
+ }
+ }
+ }
+
+ Map<String, String> mm = new HashMap<>();
+ while (!wm.isEmpty()) {
+ for (String key : new ArrayList<>(wm.keySet())) {
+ Object o = wm.get(key);
+ wm.remove(key);
+
+ if (o instanceof Boolean || o instanceof Number || o instanceof String) {
+ mm.put(key, o.toString());
+ log.info("Added property: {} : {}", key, o.toString());
+ } else if (o instanceof JSONObject) {
+ JSONObject jo = (JSONObject) o;
+ Iterator<String> i = jo.keys();
+ while (i.hasNext()) {
+ String key1 = i.next();
+ String[] subKey = key1.split(":");
+ if (subKey.length == 2) {
+ wm.put(key + "." + subKey[1], jo.get(key1));
+ } else {
+ wm.put(key + "." + key1, jo.get(key1));
+ }
+ }
+ } else if (o instanceof JSONArray) {
+ JSONArray ja = (JSONArray) o;
+ mm.put(key + "_length", String.valueOf(ja.length()));
+ log.info("Added property: {}_length: {}", key, ja.length());
+
+ for (int i = 0; i < ja.length(); i++) {
+ wm.put(key + '[' + i + ']', ja.get(i));
+ }
+ }
+ }
+ }
+ return mm;
+ } catch (JSONException e) {
+ throw new SvcLogicException("Unable to convert JSON to properties" + e.getLocalizedMessage(), e);
+ }
+ }
+
+}
diff --git a/plugins/restapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/restapicall/Parameters.java b/plugins/restapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/restapicall/Parameters.java
new file mode 100755
index 000000000..9b542af91
--- /dev/null
+++ b/plugins/restapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/restapicall/Parameters.java
@@ -0,0 +1,56 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.restapicall;
+
+import java.util.Set;
+
+public class Parameters {
+ public String templateFileName;
+ public String restapiUrl;
+ public String restapiUrlSuffix;
+ public String restapiUser;
+ public String restapiPassword;
+ public Format format;
+ public String contentType;
+ public HttpMethod httpMethod;
+ public String responsePrefix;
+ public Set<String> listNameList;
+ public boolean skipSending;
+ public boolean convertResponse;
+ public String keyStoreFileName;
+ public String keyStorePassword;
+ public boolean ssl;
+ public String customHttpHeaders;
+ public String partner;
+ public Boolean dumpHeaders;
+ public String requestBody;
+ public String oAuthConsumerKey;
+ public String oAuthConsumerSecret;
+ public String oAuthSignatureMethod;
+ public String oAuthVersion;
+ public AuthType authtype;
+ public Boolean returnRequestPayload;
+ public String accept;
+ public boolean multipartFormData;
+ public String multipartFile;
+ public String targetEntity;
+}
diff --git a/plugins/restapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/restapicall/PartnerDetails.java b/plugins/restapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/restapicall/PartnerDetails.java
new file mode 100755
index 000000000..1cd4b99bb
--- /dev/null
+++ b/plugins/restapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/restapicall/PartnerDetails.java
@@ -0,0 +1,14 @@
+package org.onap.ccsdk.sli.plugins.restapicall;
+
+public class PartnerDetails {
+ protected String username;
+ protected String password;
+ protected String url;
+
+ public PartnerDetails(String username, String password, String url) {
+ this.username = username;
+ this.password = password;
+ this.url = url;
+ }
+
+}
diff --git a/plugins/restapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/restapicall/RestapiCallNode.java b/plugins/restapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/restapicall/RestapiCallNode.java
new file mode 100755
index 000000000..3d7042493
--- /dev/null
+++ b/plugins/restapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/restapicall/RestapiCallNode.java
@@ -0,0 +1,1306 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * Modifications Copyright © 2018 IBM.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.restapicall;
+
+import static java.lang.Boolean.valueOf;
+import static javax.ws.rs.client.Entity.entity;
+import static org.onap.ccsdk.sli.plugins.restapicall.AuthType.fromString;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.net.HttpURLConnection;
+import java.net.ProtocolException;
+import java.net.SocketException;
+import java.net.URI;
+import java.net.URL;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.security.KeyStore;
+import java.util.ArrayList;
+import java.util.Base64;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Properties;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import javax.net.ssl.HttpsURLConnection;
+import javax.net.ssl.KeyManagerFactory;
+import javax.net.ssl.SSLContext;
+import javax.ws.rs.ProcessingException;
+import javax.ws.rs.client.Client;
+import javax.ws.rs.client.ClientBuilder;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.Invocation;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.EntityTag;
+import javax.ws.rs.core.Feature;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriBuilder;
+import org.apache.commons.lang3.StringUtils;
+import org.codehaus.jettison.json.JSONException;
+import org.codehaus.jettison.json.JSONObject;
+import org.glassfish.jersey.client.ClientProperties;
+import org.glassfish.jersey.client.HttpUrlConnectorProvider;
+import org.glassfish.jersey.client.authentication.HttpAuthenticationFeature;
+import org.glassfish.jersey.client.oauth1.ConsumerCredentials;
+import org.glassfish.jersey.client.oauth1.OAuth1ClientSupport;
+import org.glassfish.jersey.media.multipart.MultiPart;
+import org.glassfish.jersey.media.multipart.MultiPartFeature;
+import org.glassfish.jersey.media.multipart.file.FileDataBodyPart;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.core.sli.SvcLogicJavaPlugin;
+import org.onap.logging.filter.base.HttpURLConnectionMetricUtil;
+import org.onap.logging.filter.base.MetricLogClientFilter;
+import org.onap.logging.filter.base.ONAPComponents;
+import org.onap.logging.ref.slf4j.ONAPLogConstants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.slf4j.MDC;
+
+public class RestapiCallNode implements SvcLogicJavaPlugin {
+
+ protected static final String PARTNERS_FILE_NAME = "partners.json";
+ protected static final String UEB_PROPERTIES_FILE_NAME = "ueb.properties";
+ protected static final String DEFAULT_PROPERTIES_DIR = "/opt/onap/ccsdk/data/properties";
+ protected static final String PROPERTIES_DIR_KEY = "SDNC_CONFIG_DIR";
+ protected static final int DEFAULT_HTTP_CONNECT_TIMEOUT_MS = 30000; // 30 seconds
+ protected static final int DEFAULT_HTTP_READ_TIMEOUT_MS = 600000; // 10 minutes
+
+ private static final Logger log = LoggerFactory.getLogger(RestapiCallNode.class);
+ private String uebServers;
+ private String defaultUebTemplateFileName = "/opt/bvc/restapi/templates/default-ueb-message.json";
+
+ private String responseReceivedMessage = "Response received. Time: {}";
+ private String responseHttpCodeMessage = "HTTP response code: {}";
+ private String requestPostingException = "Exception while posting http request to client ";
+ protected static final String skipSendingMessage = "skipSending";
+ protected static final String responsePrefix = "responsePrefix";
+ protected static final String restapiUrlString = "restapiUrl";
+ protected static final String restapiUserKey = "restapiUser";
+ protected static final String restapiPasswordKey = "restapiPassword";
+ protected Integer httpConnectTimeout;
+ protected Integer httpReadTimeout;
+
+ protected HashMap<String, PartnerDetails> partnerStore;
+ private static final Pattern retryPattern = Pattern.compile(".*,(http|https):.*");
+
+ public RestapiCallNode() {
+ String configDir = System.getProperty(PROPERTIES_DIR_KEY, DEFAULT_PROPERTIES_DIR);
+ try {
+ String jsonString = readFile(configDir + "/" + PARTNERS_FILE_NAME);
+ JSONObject partners = new JSONObject(jsonString);
+ partnerStore = new HashMap<>();
+ loadPartners(partners);
+ log.info("Partners support enabled");
+ } catch (Exception e) {
+ log.warn("Partners file could not be read, Partner support will not be enabled. " + e.getMessage());
+ }
+
+ try (FileInputStream in = new FileInputStream(configDir + "/" + UEB_PROPERTIES_FILE_NAME)) {
+ Properties props = new Properties();
+ props.load(in);
+ uebServers = props.getProperty("servers");
+ log.info("UEB support enabled");
+ } catch (Exception e) {
+ log.warn("UEB properties could not be read, UEB support will not be enabled. " + e.getMessage());
+ }
+ httpConnectTimeout = readOptionalInteger("HTTP_CONNECT_TIMEOUT_MS",DEFAULT_HTTP_CONNECT_TIMEOUT_MS);
+ httpReadTimeout = readOptionalInteger("HTTP_READ_TIMEOUT_MS",DEFAULT_HTTP_READ_TIMEOUT_MS);
+ }
+
+ @SuppressWarnings("unchecked")
+ protected void loadPartners(JSONObject partners) {
+ Iterator<String> keys = partners.keys();
+ String partnerUserKey = "user";
+ String partnerPasswordKey = "password";
+ String partnerUrlKey = "url";
+
+ while (keys.hasNext()) {
+ String partnerKey = keys.next();
+ try {
+ JSONObject partnerObject = (JSONObject) partners.get(partnerKey);
+ if (partnerObject.has(partnerUserKey) && partnerObject.has(partnerPasswordKey)) {
+ String url = null;
+ if (partnerObject.has(partnerUrlKey)) {
+ url = partnerObject.getString(partnerUrlKey);
+ }
+ String userName = partnerObject.getString(partnerUserKey);
+ String password = partnerObject.getString(partnerPasswordKey);
+ PartnerDetails details = new PartnerDetails(userName, getObfuscatedVal(password), url);
+ partnerStore.put(partnerKey, details);
+ log.info("mapped partner using partner key " + partnerKey);
+ } else {
+ log.info("Partner " + partnerKey + " is missing required keys, it won't be mapped");
+ }
+ } catch (JSONException e) {
+ log.info("Couldn't map the partner using partner key " + partnerKey, e);
+ }
+ }
+ }
+
+ /* Unobfuscate param value */
+ private static String getObfuscatedVal(String paramValue) {
+ String resValue = paramValue;
+ if (paramValue != null && paramValue.startsWith("${") && paramValue.endsWith("}"))
+ {
+ String paramStr = paramValue.substring(2, paramValue.length()-1);
+ if (paramStr != null && paramStr.length() > 0)
+ {
+ String val = System.getenv(paramStr);
+ if (val != null && val.length() > 0)
+ {
+ resValue=val;
+ log.info("Obfuscated value RESET for param value:" + paramValue);
+ }
+ }
+ }
+ return resValue;
+ }
+
+ /**
+ * Returns parameters from the parameter map.
+ *
+ * @param paramMap parameter map
+ * @param p parameters instance
+ * @return parameters filed instance
+ * @throws SvcLogicException when svc logic exception occurs
+ */
+ public static Parameters getParameters(Map<String, String> paramMap, Parameters p) throws SvcLogicException {
+
+ p.templateFileName = parseParam(paramMap, "templateFileName", false, null);
+ p.requestBody = parseParam(paramMap, "requestBody", false, null);
+ p.restapiUrl = parseParam(paramMap, restapiUrlString, true, null);
+ p.restapiUrlSuffix = parseParam(paramMap, "restapiUrlSuffix", false, null);
+ if (p.restapiUrlSuffix != null) {
+ p.restapiUrl = p.restapiUrl + p.restapiUrlSuffix;
+ }
+
+ p.restapiUrl = UriBuilder.fromUri(p.restapiUrl).toTemplate();
+ validateUrl(p.restapiUrl);
+
+ p.restapiUser = parseParam(paramMap, restapiUserKey, false, null);
+ p.restapiPassword = parseParam(paramMap, restapiPasswordKey, false, null);
+ p.oAuthConsumerKey = parseParam(paramMap, "oAuthConsumerKey", false, null);
+ p.oAuthConsumerSecret = parseParam(paramMap, "oAuthConsumerSecret", false, null);
+ p.oAuthSignatureMethod = parseParam(paramMap, "oAuthSignatureMethod", false, null);
+ p.oAuthVersion = parseParam(paramMap, "oAuthVersion", false, null);
+ p.contentType = parseParam(paramMap, "contentType", false, null);
+ p.format = Format.fromString(parseParam(paramMap, "format", false, "json"));
+ p.authtype = fromString(parseParam(paramMap, "authType", false, "unspecified"));
+ p.httpMethod = HttpMethod.fromString(parseParam(paramMap, "httpMethod", false, "post"));
+ p.responsePrefix = parseParam(paramMap, responsePrefix, false, null);
+ p.listNameList = getListNameList(paramMap);
+ String skipSendingStr = paramMap.get(skipSendingMessage);
+ p.skipSending = "true".equalsIgnoreCase(skipSendingStr);
+ p.convertResponse = valueOf(parseParam(paramMap, "convertResponse", false, "true"));
+ p.keyStoreFileName = parseParam(paramMap, "keyStoreFileName", false, null);
+ p.keyStorePassword = parseParam(paramMap, "keyStorePassword", false, null);
+ p.ssl = p.keyStoreFileName != null && p.keyStorePassword != null;
+ p.customHttpHeaders = parseParam(paramMap, "customHttpHeaders", false, null);
+ p.partner = parseParam(paramMap, "partner", false, null);
+ p.dumpHeaders = valueOf(parseParam(paramMap, "dumpHeaders", false, null));
+ p.returnRequestPayload = valueOf(parseParam(paramMap, "returnRequestPayload", false, null));
+ p.accept = parseParam(paramMap, "accept", false, null);
+ p.multipartFormData = valueOf(parseParam(paramMap, "multipartFormData", false, "false"));
+ p.multipartFile = parseParam(paramMap, "multipartFile", false, null);
+ p.targetEntity = parseParam(paramMap, "targetEntity", false, null);
+ return p;
+ }
+
+ /**
+ * Validates the given URL in the parameters.
+ *
+ * @param restapiUrl rest api URL
+ * @throws SvcLogicException when URL validation fails
+ */
+ private static void validateUrl(String restapiUrl) throws SvcLogicException {
+ if (containsMultipleUrls(restapiUrl)) {
+ String[] urls = getMultipleUrls(restapiUrl);
+ for (String url : urls) {
+ validateUrl(url);
+ }
+ } else {
+ try {
+ URI.create(restapiUrl);
+ } catch (IllegalArgumentException e) {
+ throw new SvcLogicException("Invalid input of url " + e.getLocalizedMessage(), e);
+ }
+ }
+ }
+
+ /**
+ * Returns the list of list name.
+ *
+ * @param paramMap parameters map
+ * @return list of list name
+ */
+ private static Set<String> getListNameList(Map<String, String> paramMap) {
+ Set<String> ll = new HashSet<>();
+ for (Map.Entry<String, String> entry : paramMap.entrySet()) {
+ if (entry.getKey().startsWith("listName")) {
+ ll.add(entry.getValue());
+ }
+ }
+ return ll;
+ }
+
+ /**
+ * Parses the parameter string map of property, validates if required, assigns default value if
+ * present and returns the value.
+ *
+ * @param paramMap string param map
+ * @param name name of the property
+ * @param required if value required
+ * @param def default value
+ * @return value of the property
+ * @throws SvcLogicException if required parameter value is empty
+ */
+ public static String parseParam(Map<String, String> paramMap, String name, boolean required, String def)
+ throws SvcLogicException {
+ String s = paramMap.get(name);
+
+ if (s == null || s.trim().length() == 0) {
+ if (!required) {
+ return def;
+ }
+ throw new SvcLogicException("Parameter " + name + " is required in RestapiCallNode");
+ }
+
+ s = s.trim();
+ StringBuilder value = new StringBuilder();
+ int i = 0;
+ int i1 = s.indexOf('%');
+ while (i1 >= 0) {
+ int i2 = s.indexOf('%', i1 + 1);
+ if (i2 < 0) {
+ break;
+ }
+
+ String varName = s.substring(i1 + 1, i2);
+ String varValue = System.getenv(varName);
+ if (varValue == null) {
+ varValue = "%" + varName + "%";
+ }
+
+ value.append(s.substring(i, i1));
+ value.append(varValue);
+
+ i = i2 + 1;
+ i1 = s.indexOf('%', i);
+ }
+ value.append(s.substring(i));
+
+ log.info("Parameter {}: [{}]", name, maskPassword(name, value));
+
+ return value.toString();
+ }
+
+ private static Object maskPassword(String name, Object value) {
+ String[] pwdNames = {"pwd", "passwd", "password", "Pwd", "Passwd", "Password"};
+ for (String pwdName : pwdNames) {
+ if (name.contains(pwdName)) {
+ return "**********";
+ }
+ }
+ return value;
+ }
+
+ /**
+ * Allows Directed Graphs the ability to interact with REST APIs.
+ *
+ * @param paramMap HashMap<String,String> of parameters passed by the DG to this function
+ * <table border="1">
+ * <thead>
+ * <th>parameter</th>
+ * <th>Mandatory/Optional</th>
+ * <th>description</th>
+ * <th>example values</th></thead> <tbody>
+ * <tr>
+ * <td>templateFileName</td>
+ * <td>Optional</td>
+ * <td>full path to template file that can be used to build a request</td>
+ * <td>/sdncopt/bvc/restapi/templates/vnf_service-configuration-operation_minimal.json</td>
+ * </tr>
+ * <tr>
+ * <td>restapiUrl</td>
+ * <td>Mandatory</td>
+ * <td>url to send the request to</td>
+ * <td>https://sdncodl:8543/restconf/operations/L3VNF-API:create-update-vnf-request</td>
+ * </tr>
+ * <tr>
+ * <td>restapiUser</td>
+ * <td>Optional</td>
+ * <td>user name to use for http basic authentication</td>
+ * <td>sdnc_ws</td>
+ * </tr>
+ * <tr>
+ * <td>restapiPassword</td>
+ * <td>Optional</td>
+ * <td>unencrypted password to use for http basic authentication</td>
+ * <td>plain_password</td>
+ * </tr>
+ * <tr>
+ * <td>oAuthConsumerKey</td>
+ * <td>Optional</td>
+ * <td>Consumer key to use for http oAuth authentication</td>
+ * <td>plain_key</td>
+ * </tr>
+ * <tr>
+ * <td>oAuthConsumerSecret</td>
+ * <td>Optional</td>
+ * <td>Consumer secret to use for http oAuth authentication</td>
+ * <td>plain_secret</td>
+ * </tr>
+ * <tr>
+ * <td>oAuthSignatureMethod</td>
+ * <td>Optional</td>
+ * <td>Consumer method to use for http oAuth authentication</td>
+ * <td>method</td>
+ * </tr>
+ * <tr>
+ * <td>oAuthVersion</td>
+ * <td>Optional</td>
+ * <td>Version http oAuth authentication</td>
+ * <td>version</td>
+ * </tr>
+ * <tr>
+ * <td>contentType</td>
+ * <td>Optional</td>
+ * <td>http content type to set in the http header</td>
+ * <td>usually application/json or application/xml</td>
+ * </tr>
+ * <tr>
+ * <td>format</td>
+ * <td>Optional</td>
+ * <td>should match request body format</td>
+ * <td>json or xml</td>
+ * </tr>
+ * <tr>
+ * <td>httpMethod</td>
+ * <td>Optional</td>
+ * <td>http method to use when sending the request</td>
+ * <td>get post put delete patch</td>
+ * </tr>
+ * <tr>
+ * <td>responsePrefix</td>
+ * <td>Optional</td>
+ * <td>location the response will be written to in context memory</td>
+ * <td>tmp.restapi.result</td>
+ * </tr>
+ * <tr>
+ * <td>listName[i]</td>
+ * <td>Optional</td>
+ * <td>Used for processing XML responses with repeating
+ * elements.</td>vpn-information.vrf-details
+ * <td></td>
+ * </tr>
+ * <tr>
+ * <td>skipSending</td>
+ * <td>Optional</td>
+ * <td></td>
+ * <td>true or false</td>
+ * </tr>
+ * <tr>
+ * <td>convertResponse</td>
+ * <td>Optional</td>
+ * <td>whether the response should be converted</td>
+ * <td>true or false</td>
+ * </tr>
+ * <tr>
+ * <td>customHttpHeaders</td>
+ * <td>Optional</td>
+ * <td>a list additional http headers to be passed in, follow the format in the example</td>
+ * <td>X-CSI-MessageId=messageId,headerFieldName=headerFieldValue</td>
+ * </tr>
+ * <tr>
+ * <td>dumpHeaders</td>
+ * <td>Optional</td>
+ * <td>when true writes http header content to context memory</td>
+ * <td>true or false</td>
+ * </tr>
+ * <tr>
+ * <td>partner</td>
+ * <td>Optional</td>
+ * <td>used to retrieve username, password and url if partner store exists</td>
+ * <td>aaf</td>
+ * </tr>
+ * <tr>
+ * <td>returnRequestPayload</td>
+ * <td>Optional</td>
+ * <td>used to return payload built in the request</td>
+ * <td>true or false</td>
+ * </tr>
+ * </tbody>
+ * </table>
+ * @param ctx Reference to context memory
+ * @throws SvcLogicException
+ * @since 11.0.2
+ * @see String#split(String, int)
+ */
+ public void sendRequest(Map<String, String> paramMap, SvcLogicContext ctx) throws SvcLogicException {
+ sendRequest(paramMap, ctx, null);
+ }
+
+ protected void sendRequest(Map<String, String> paramMap, SvcLogicContext ctx, RetryPolicy retryPolicy)
+ throws SvcLogicException {
+
+ HttpResponse r = new HttpResponse();
+ try {
+ handlePartner(paramMap);
+ Parameters p = getParameters(paramMap, new Parameters());
+ if(p.targetEntity != null && !p.targetEntity.isEmpty()) {
+ MDC.put(ONAPLogConstants.MDCs.TARGET_ENTITY, p.targetEntity);
+ }
+ if (containsMultipleUrls(p.restapiUrl) && retryPolicy == null) {
+ String[] urls = getMultipleUrls(p.restapiUrl);
+ retryPolicy = new RetryPolicy(urls, urls.length * 2);
+ p.restapiUrl = urls[0];
+ }
+ String pp = p.responsePrefix != null ? p.responsePrefix + '.' : "";
+
+ String req = null;
+ if (p.templateFileName != null) {
+ String reqTemplate = readFile(p.templateFileName);
+ req = buildXmlJsonRequest(ctx, reqTemplate, p.format);
+ } else if (p.requestBody != null) {
+ req = p.requestBody;
+ }
+ r = sendHttpRequest(req, p);
+ setResponseStatus(ctx, p.responsePrefix, r);
+
+ if (p.dumpHeaders && r.headers != null) {
+ for (Entry<String, List<String>> a : r.headers.entrySet()) {
+ ctx.setAttribute(pp + "header." + a.getKey(), StringUtils.join(a.getValue(), ","));
+ }
+ }
+
+ if (p.returnRequestPayload && req != null) {
+ ctx.setAttribute(pp + "httpRequest", req);
+ }
+
+ if (r.body != null && r.body.trim().length() > 0) {
+ ctx.setAttribute(pp + "httpResponse", r.body);
+
+ if (p.convertResponse) {
+ Map<String, String> mm = null;
+ if (p.format == Format.XML) {
+ mm = XmlParser.convertToProperties(r.body, p.listNameList);
+ } else if (p.format == Format.JSON) {
+ mm = JsonParser.convertToProperties(r.body);
+ }
+
+ if (mm != null) {
+ for (Map.Entry<String, String> entry : mm.entrySet()) {
+ ctx.setAttribute(pp + entry.getKey(), entry.getValue());
+ }
+ }
+ }
+ }
+ } catch (SvcLogicException e) {
+ boolean shouldRetry = false;
+ if (e.getCause().getCause() instanceof SocketException) {
+ shouldRetry = true;
+ }
+
+ log.error("Error sending the request: " + e.getMessage(), e);
+ String prefix = parseParam(paramMap, responsePrefix, false, null);
+ if (retryPolicy == null || !shouldRetry) {
+ setFailureResponseStatus(ctx, prefix, e.getMessage(), r);
+ } else {
+ log.debug(retryPolicy.getRetryMessage());
+ try {
+ // calling getNextHostName increments the retry count so it should be called before shouldRetry
+ String retryString = retryPolicy.getNextHostName();
+ if (retryPolicy.shouldRetry()) {
+ paramMap.put(restapiUrlString, retryString);
+ log.debug("retry attempt {} will use the retry url {}", retryPolicy.getRetryCount(),
+ retryString);
+ sendRequest(paramMap, ctx, retryPolicy);
+ } else {
+ log.debug("Maximum retries reached, won't attempt to retry. Calling setFailureResponseStatus.");
+ setFailureResponseStatus(ctx, prefix, e.getMessage(), r);
+ }
+ } catch (Exception ex) {
+ String retryErrorMessage = "Retry attempt " + retryPolicy.getRetryCount()
+ + "has failed with error message " + ex.getMessage();
+ setFailureResponseStatus(ctx, prefix, retryErrorMessage, r);
+ }
+ }
+ }
+
+ if (r != null && r.code >= 300) {
+ throw new SvcLogicException(String.valueOf(r.code) + ": " + r.message);
+ }
+ }
+
+ protected void handlePartner(Map<String, String> paramMap) {
+ String partner = paramMap.get("partner");
+ if (partner != null && partner.length() > 0) {
+ PartnerDetails details = partnerStore.get(partner);
+ paramMap.put(restapiUserKey, details.username);
+ paramMap.put(restapiPasswordKey, details.password);
+ if (paramMap.get(restapiUrlString) == null) {
+ paramMap.put(restapiUrlString, details.url);
+ }
+ }
+ }
+
+ protected String buildXmlJsonRequest(SvcLogicContext ctx, String template, Format format) throws SvcLogicException {
+ log.info("Building {} started", format);
+ long t1 = System.currentTimeMillis();
+ String originalTemplate = template;
+
+ template = expandRepeats(ctx, template, 1);
+
+ Map<String, String> mm = new HashMap<>();
+ for (String s : ctx.getAttributeKeySet()) {
+ mm.put(s, ctx.getAttribute(s));
+ }
+
+ StringBuilder ss = new StringBuilder();
+ int i = 0;
+ while (i < template.length()) {
+ int i1 = template.indexOf("${", i);
+ if (i1 < 0) {
+ ss.append(template.substring(i));
+ break;
+ }
+
+ int i2 = template.indexOf('}', i1 + 2);
+ if (i2 < 0) {
+ throw new SvcLogicException("Template error: Matching } not found");
+ }
+
+ String var1 = template.substring(i1 + 2, i2);
+ String value1 = format == Format.XML ? XmlJsonUtil.getXml(mm, var1) : XmlJsonUtil.getJson(mm, var1);
+ if (value1 == null || value1.trim().length() == 0) {
+ // delete the whole element (line)
+ int i3 = template.lastIndexOf('\n', i1);
+ if (i3 < 0) {
+ i3 = 0;
+ }
+ int i4 = template.indexOf('\n', i1);
+ if (i4 < 0) {
+ i4 = template.length();
+ }
+
+ if (i < i3) {
+ ss.append(template.substring(i, i3));
+ }
+ i = i4;
+ } else {
+ ss.append(template.substring(i, i1)).append(value1);
+ i = i2 + 1;
+ }
+ }
+
+ String req = format == Format.XML ? XmlJsonUtil.removeEmptyStructXml(ss.toString())
+ : XmlJsonUtil.removeEmptyStructJson(originalTemplate, ss.toString());
+
+ if (format == Format.JSON) {
+ req = XmlJsonUtil.removeLastCommaJson(req);
+ }
+
+ long t2 = System.currentTimeMillis();
+ log.info("Building {} completed. Time: {}", format, t2 - t1);
+
+ return req;
+ }
+
+ protected String expandRepeats(SvcLogicContext ctx, String template, int level) throws SvcLogicException {
+ StringBuilder newTemplate = new StringBuilder();
+ int k = 0;
+ while (k < template.length()) {
+ int i1 = template.indexOf("${repeat:", k);
+ if (i1 < 0) {
+ newTemplate.append(template.substring(k));
+ break;
+ }
+
+ int i2 = template.indexOf(':', i1 + 9);
+ if (i2 < 0) {
+ throw new SvcLogicException(
+ "Template error: Context variable name followed by : is required after repeat");
+ }
+
+ // Find the closing }, store in i3
+ int nn = 1;
+ int i3 = -1;
+ int i = i2;
+ while (nn > 0 && i < template.length()) {
+ i3 = template.indexOf('}', i);
+ if (i3 < 0) {
+ throw new SvcLogicException("Template error: Matching } not found");
+ }
+ int i32 = template.indexOf('{', i);
+ if (i32 >= 0 && i32 < i3) {
+ nn++;
+ i = i32 + 1;
+ } else {
+ nn--;
+ i = i3 + 1;
+ }
+ }
+
+ String var1 = template.substring(i1 + 9, i2);
+ String value1 = ctx.getAttribute(var1);
+ log.info(" {}:{}", var1, value1);
+ int n = 0;
+ try {
+ n = Integer.parseInt(value1);
+ } catch (NumberFormatException e) {
+ log.info("value1 not set or not a number, n will remain set at zero");
+ }
+
+ newTemplate.append(template.substring(k, i1));
+
+ String rpt = template.substring(i2 + 1, i3);
+
+ for (int ii = 0; ii < n; ii++) {
+ String ss = rpt.replaceAll("\\[\\$\\{" + level + "\\}\\]", "[" + ii + "]");
+ if (ii == n - 1 && ss.trim().endsWith(",")) {
+ int i4 = ss.lastIndexOf(',');
+ if (i4 > 0) {
+ ss = ss.substring(0, i4) + ss.substring(i4 + 1);
+ }
+ }
+ newTemplate.append(ss);
+ }
+
+ k = i3 + 1;
+ }
+
+ if (k == 0) {
+ return newTemplate.toString();
+ }
+
+ return expandRepeats(ctx, newTemplate.toString(), level + 1);
+ }
+
+ protected String readFile(String fileName) throws SvcLogicException {
+ try {
+ byte[] encoded = Files.readAllBytes(Paths.get(fileName));
+ return new String(encoded, "UTF-8");
+ } catch (IOException | SecurityException e) {
+ throw new SvcLogicException("Unable to read file " + fileName + e.getLocalizedMessage(), e);
+ }
+ }
+
+ protected Client addAuthType(Client c, FileParam fp) throws SvcLogicException {
+ Parameters p = new Parameters();
+ p.restapiUser = fp.user;
+ p.restapiPassword = fp.password;
+ p.oAuthConsumerKey = fp.oAuthConsumerKey;
+ p.oAuthVersion = fp.oAuthVersion;
+ p.oAuthConsumerSecret = fp.oAuthConsumerSecret;
+ p.oAuthSignatureMethod = fp.oAuthSignatureMethod;
+ p.authtype = fp.authtype;
+ return addAuthType(c, p);
+ }
+
+ public Client addAuthType(Client client, Parameters p) throws SvcLogicException {
+ if (p.authtype == AuthType.Unspecified) {
+ if (p.restapiUser != null && p.restapiPassword != null) {
+ client.register(HttpAuthenticationFeature.basic(p.restapiUser, p.restapiPassword));
+ } else if (p.oAuthConsumerKey != null && p.oAuthConsumerSecret != null && p.oAuthSignatureMethod != null) {
+ Feature oAuth1Feature =
+ OAuth1ClientSupport.builder(new ConsumerCredentials(p.oAuthConsumerKey, p.oAuthConsumerSecret))
+ .version(p.oAuthVersion).signatureMethod(p.oAuthSignatureMethod).feature().build();
+ client.register(oAuth1Feature);
+
+ }
+ } else {
+ if (p.authtype == AuthType.DIGEST) {
+ if (p.restapiUser != null && p.restapiPassword != null) {
+ client.register(HttpAuthenticationFeature.digest(p.restapiUser, p.restapiPassword));
+ } else {
+ throw new SvcLogicException(
+ "oAUTH authentication type selected but all restapiUser and restapiPassword "
+ + "parameters doesn't exist",
+ new Throwable());
+ }
+ } else if (p.authtype == AuthType.BASIC) {
+ if (p.restapiUser != null && p.restapiPassword != null) {
+ client.register(HttpAuthenticationFeature.basic(p.restapiUser, p.restapiPassword));
+ } else {
+ throw new SvcLogicException(
+ "oAUTH authentication type selected but all restapiUser and restapiPassword "
+ + "parameters doesn't exist",
+ new Throwable());
+ }
+ } else if (p.authtype == AuthType.OAUTH) {
+ if (p.oAuthConsumerKey != null && p.oAuthConsumerSecret != null && p.oAuthSignatureMethod != null) {
+ Feature oAuth1Feature = OAuth1ClientSupport
+ .builder(new ConsumerCredentials(p.oAuthConsumerKey, p.oAuthConsumerSecret))
+ .version(p.oAuthVersion).signatureMethod(p.oAuthSignatureMethod).feature().build();
+ client.register(oAuth1Feature);
+ } else {
+ throw new SvcLogicException(
+ "oAUTH authentication type selected but all oAuthConsumerKey, oAuthConsumerSecret "
+ + "and oAuthSignatureMethod parameters doesn't exist",
+ new Throwable());
+ }
+ }
+ }
+ return client;
+ }
+
+ /**
+ * Receives the http response for the http request sent.
+ *
+ * @param request request msg
+ * @param p parameters
+ * @return HTTP response
+ * @throws SvcLogicException when sending http request fails
+ */
+ public HttpResponse sendHttpRequest(String request, Parameters p) throws SvcLogicException {
+
+ SSLContext ssl = null;
+ if (p.ssl && p.restapiUrl.startsWith("https")) {
+ ssl = createSSLContext(p);
+ }
+ Client client;
+ if (ssl != null) {
+ HttpsURLConnection.setDefaultSSLSocketFactory(ssl.getSocketFactory());
+ client = ClientBuilder.newBuilder().sslContext(ssl).hostnameVerifier((s, sslSession) -> true).build();
+ } else {
+ client = ClientBuilder.newBuilder().hostnameVerifier((s, sslSession) -> true).build();
+ }
+
+ setClientTimeouts(client);
+ // Needed to support additional HTTP methods such as PATCH
+ client.property(HttpUrlConnectorProvider.SET_METHOD_WORKAROUND, true);
+ client.register(new MetricLogClientFilter());
+ WebTarget webTarget = addAuthType(client, p).target(p.restapiUrl);
+
+ long t1 = System.currentTimeMillis();
+
+ HttpResponse r = new HttpResponse();
+ r.code = 200;
+ String accept = p.accept;
+ if (accept == null) {
+ accept = p.format == Format.XML ? "application/xml" : "application/json";
+ }
+
+ String contentType = p.contentType;
+ if (contentType == null) {
+ contentType = accept + ";charset=UTF-8";
+ }
+
+ if (!p.skipSending && !p.multipartFormData) {
+
+ Invocation.Builder invocationBuilder = webTarget.request(contentType).accept(accept);
+
+ if (p.format == Format.NONE) {
+ invocationBuilder.header("", "");
+ }
+
+ if (p.customHttpHeaders != null && p.customHttpHeaders.length() > 0) {
+ String[] keyValuePairs = p.customHttpHeaders.split(",");
+ for (String singlePair : keyValuePairs) {
+ int equalPosition = singlePair.indexOf('=');
+ invocationBuilder.header(singlePair.substring(0, equalPosition),
+ singlePair.substring(equalPosition + 1, singlePair.length()));
+ }
+ }
+
+ invocationBuilder.property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true);
+
+ Response response;
+
+ try {
+ // When the HTTP operation has no body do not set the content-type
+ //setting content-type has caused errors with some servers when no body is present
+ if (request == null) {
+ response = invocationBuilder.method(p.httpMethod.toString());
+ } else {
+ log.info("Sending request below to url " + p.restapiUrl);
+ log.info(request);
+ response = invocationBuilder.method(p.httpMethod.toString(), entity(request, contentType));
+ }
+ } catch (ProcessingException | IllegalStateException e) {
+ throw new SvcLogicException(requestPostingException + e.getLocalizedMessage(), e);
+ }
+
+ r.code = response.getStatus();
+ r.headers = response.getStringHeaders();
+ EntityTag etag = response.getEntityTag();
+ if (etag != null) {
+ r.message = etag.getValue();
+ }
+ if (response.hasEntity() && r.code != 204) {
+ r.body = response.readEntity(String.class);
+ }
+ } else if (!p.skipSending && p.multipartFormData) {
+
+ WebTarget wt = client.register(MultiPartFeature.class).target(p.restapiUrl);
+
+ MultiPart multiPart = new MultiPart();
+ multiPart.setMediaType(MediaType.MULTIPART_FORM_DATA_TYPE);
+
+ FileDataBodyPart fileDataBodyPart =
+ new FileDataBodyPart("file", new File(p.multipartFile), MediaType.APPLICATION_OCTET_STREAM_TYPE);
+ multiPart.bodyPart(fileDataBodyPart);
+
+
+ Invocation.Builder invocationBuilder = wt.request(contentType).accept(accept);
+
+ if (p.format == Format.NONE) {
+ invocationBuilder.header("", "");
+ }
+
+ if (p.customHttpHeaders != null && p.customHttpHeaders.length() > 0) {
+ String[] keyValuePairs = p.customHttpHeaders.split(",");
+ for (String singlePair : keyValuePairs) {
+ int equalPosition = singlePair.indexOf('=');
+ invocationBuilder.header(singlePair.substring(0, equalPosition),
+ singlePair.substring(equalPosition + 1, singlePair.length()));
+ }
+ }
+
+ Response response;
+
+ try {
+ response =
+ invocationBuilder.method(p.httpMethod.toString(), entity(multiPart, multiPart.getMediaType()));
+ } catch (ProcessingException | IllegalStateException e) {
+ throw new SvcLogicException(requestPostingException + e.getLocalizedMessage(), e);
+ }
+
+ r.code = response.getStatus();
+ r.headers = response.getStringHeaders();
+ EntityTag etag = response.getEntityTag();
+ if (etag != null) {
+ r.message = etag.getValue();
+ }
+ if (response.hasEntity() && r.code != 204) {
+ r.body = response.readEntity(String.class);
+ }
+
+ }
+
+ long t2 = System.currentTimeMillis();
+ log.info(responseReceivedMessage, t2 - t1);
+ log.info(responseHttpCodeMessage, r.code);
+ log.info("HTTP response message: {}", r.message);
+ logHeaders(r.headers);
+ log.info("HTTP response: {}", r.body);
+
+ return r;
+ }
+
+ protected SSLContext createSSLContext(Parameters p) {
+ try (FileInputStream in = new FileInputStream(p.keyStoreFileName)) {
+ HttpsURLConnection.setDefaultHostnameVerifier((string, ssls) -> true);
+ KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
+ KeyStore ks = KeyStore.getInstance("PKCS12");
+ char[] pwd = p.keyStorePassword.toCharArray();
+ ks.load(in, pwd);
+ kmf.init(ks, pwd);
+ SSLContext ctx = SSLContext.getInstance("TLS");
+ ctx.init(kmf.getKeyManagers(), null, null);
+ return ctx;
+ } catch (Exception e) {
+ log.error("Error creating SSLContext: {}", e.getMessage(), e);
+ }
+ return null;
+ }
+
+ protected void setFailureResponseStatus(SvcLogicContext ctx, String prefix, String errorMessage,
+ HttpResponse resp) {
+ resp.code = 500;
+ resp.message = errorMessage;
+ String pp = prefix != null ? prefix + '.' : "";
+ ctx.setAttribute(pp + "response-code", String.valueOf(resp.code));
+ ctx.setAttribute(pp + "response-message", resp.message);
+ }
+
+ protected void setResponseStatus(SvcLogicContext ctx, String prefix, HttpResponse r) {
+ String pp = prefix != null ? prefix + '.' : "";
+ ctx.setAttribute(pp + "response-code", String.valueOf(r.code));
+ ctx.setAttribute(pp + "response-message", r.message);
+ }
+
+ public void sendFile(Map<String, String> paramMap, SvcLogicContext ctx) throws SvcLogicException {
+ HttpResponse r = null;
+ try {
+ FileParam p = getFileParameters(paramMap);
+ byte[] data = Files.readAllBytes(Paths.get(p.fileName));
+
+ r = sendHttpData(data, p);
+
+ for (int i = 0; i < 10 && r.code == 301; i++) {
+ String newUrl = r.headers2.get("Location").get(0);
+
+ log.info("Got response code 301. Sending same request to URL: " + newUrl);
+
+ p.url = newUrl;
+ r = sendHttpData(data, p);
+ }
+
+ setResponseStatus(ctx, p.responsePrefix, r);
+
+ } catch (SvcLogicException | IOException e) {
+ log.error("Error sending the request: {}", e.getMessage(), e);
+
+ r = new HttpResponse();
+ r.code = 500;
+ r.message = e.getMessage();
+ String prefix = parseParam(paramMap, responsePrefix, false, null);
+ setResponseStatus(ctx, prefix, r);
+ }
+
+ if (r != null && r.code >= 300) {
+ throw new SvcLogicException(String.valueOf(r.code) + ": " + r.message);
+ }
+ }
+
+ private FileParam getFileParameters(Map<String, String> paramMap) throws SvcLogicException {
+ FileParam p = new FileParam();
+ p.fileName = parseParam(paramMap, "fileName", true, null);
+ p.url = parseParam(paramMap, "url", true, null);
+ p.user = parseParam(paramMap, "user", false, null);
+ p.password = parseParam(paramMap, "password", false, null);
+ p.httpMethod = HttpMethod.fromString(parseParam(paramMap, "httpMethod", false, "post"));
+ p.responsePrefix = parseParam(paramMap, responsePrefix, false, null);
+ String skipSendingStr = paramMap.get(skipSendingMessage);
+ p.skipSending = "true".equalsIgnoreCase(skipSendingStr);
+ p.oAuthConsumerKey = parseParam(paramMap, "oAuthConsumerKey", false, null);
+ p.oAuthVersion = parseParam(paramMap, "oAuthVersion", false, null);
+ p.oAuthConsumerSecret = parseParam(paramMap, "oAuthConsumerSecret", false, null);
+ p.oAuthSignatureMethod = parseParam(paramMap, "oAuthSignatureMethod", false, null);
+ p.authtype = fromString(parseParam(paramMap, "authType", false, "unspecified"));
+ return p;
+ }
+
+ public void postMessageOnUeb(Map<String, String> paramMap, SvcLogicContext ctx) throws SvcLogicException {
+ HttpResponse r;
+ try {
+ UebParam p = getUebParameters(paramMap);
+
+ String pp = p.responsePrefix != null ? p.responsePrefix + '.' : "";
+
+ String req;
+
+ if (p.templateFileName == null) {
+ log.info("No template file name specified. Using default UEB template: {}", defaultUebTemplateFileName);
+ p.templateFileName = defaultUebTemplateFileName;
+ }
+
+ String reqTemplate = readFile(p.templateFileName);
+ reqTemplate = reqTemplate.replaceAll("rootVarName", p.rootVarName);
+ req = buildXmlJsonRequest(ctx, reqTemplate, Format.JSON);
+
+ r = postOnUeb(req, p);
+ setResponseStatus(ctx, p.responsePrefix, r);
+ if (r.body != null) {
+ ctx.setAttribute(pp + "httpResponse", r.body);
+ }
+
+ } catch (SvcLogicException e) {
+ log.error("Error sending the request: {}", e.getMessage(), e);
+
+ r = new HttpResponse();
+ r.code = 500;
+ r.message = e.getMessage();
+ String prefix = parseParam(paramMap, responsePrefix, false, null);
+ setResponseStatus(ctx, prefix, r);
+ }
+
+ if (r.code >= 300) {
+ throw new SvcLogicException(String.valueOf(r.code) + ": " + r.message);
+ }
+ }
+
+ protected HttpResponse sendHttpData(byte[] data, FileParam p) throws IOException {
+ URL url = new URL(p.url);
+ HttpURLConnection con = (HttpURLConnection) url.openConnection();
+
+ log.info("Connection: " + con.getClass().getName());
+
+ con.setRequestMethod(p.httpMethod.toString());
+ con.setRequestProperty("Content-Type", "application/octet-stream");
+ con.setRequestProperty("Accept", "*/*");
+ con.setRequestProperty("Expect", "100-continue");
+ con.setFixedLengthStreamingMode(data.length);
+ con.setInstanceFollowRedirects(false);
+
+ if (p.user != null && p.password != null) {
+ String authString = p.user + ":" + p.password;
+ String authStringEnc = Base64.getEncoder().encodeToString(authString.getBytes());
+ con.setRequestProperty("Authorization", "Basic " + authStringEnc);
+ }
+
+ con.setDoInput(true);
+ con.setDoOutput(true);
+
+ log.info("Sending file");
+ long t1 = System.currentTimeMillis();
+
+ HttpResponse r = new HttpResponse();
+ r.code = 200;
+
+ if (!p.skipSending) {
+ HttpURLConnectionMetricUtil util = new HttpURLConnectionMetricUtil();
+ util.logBefore(con, ONAPComponents.DMAAP);
+
+ con.connect();
+
+ boolean continue100failed = false;
+ try {
+ OutputStream os = con.getOutputStream();
+ os.write(data);
+ os.flush();
+ os.close();
+ } catch (ProtocolException e) {
+ continue100failed = true;
+ }
+
+ r.code = con.getResponseCode();
+ r.headers2 = con.getHeaderFields();
+
+ if (r.code != 204 && !continue100failed) {
+ BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
+ String inputLine;
+ StringBuffer response = new StringBuffer();
+ while ((inputLine = in.readLine()) != null) {
+ response.append(inputLine);
+ }
+ in.close();
+
+ r.body = response.toString();
+ }
+
+ util.logAfter(con);
+
+ con.disconnect();
+ }
+
+ long t2 = System.currentTimeMillis();
+ log.info("Response received. Time: {}", t2 - t1);
+ log.info("HTTP response code: {}", r.code);
+ log.info("HTTP response message: {}", r.message);
+ logHeaders(r.headers2);
+ log.info("HTTP response: {}", r.body);
+
+ return r;
+ }
+
+ private UebParam getUebParameters(Map<String, String> paramMap) throws SvcLogicException {
+ UebParam p = new UebParam();
+ p.topic = parseParam(paramMap, "topic", true, null);
+ p.templateFileName = parseParam(paramMap, "templateFileName", false, null);
+ p.rootVarName = parseParam(paramMap, "rootVarName", false, null);
+ p.responsePrefix = parseParam(paramMap, responsePrefix, false, null);
+ String skipSendingStr = paramMap.get(skipSendingMessage);
+ p.skipSending = "true".equalsIgnoreCase(skipSendingStr);
+ return p;
+ }
+
+ protected void logProperties(Map<String, Object> mm) {
+ List<String> ll = new ArrayList<>();
+ for (Object o : mm.keySet()) {
+ ll.add((String) o);
+ }
+ Collections.sort(ll);
+
+ log.info("Properties:");
+ for (String name : ll) {
+ log.info("--- {}:{}", name, String.valueOf(mm.get(name)));
+ }
+ }
+
+ protected void logHeaders(MultivaluedMap<String, String> mm) {
+ log.info("HTTP response headers:");
+
+ if (mm == null) {
+ return;
+ }
+
+ List<String> ll = new ArrayList<>();
+ for (Object o : mm.keySet()) {
+ ll.add((String) o);
+ }
+ Collections.sort(ll);
+
+ for (String name : ll) {
+ log.info("--- {}:{}", name, String.valueOf(mm.get(name)));
+ }
+ }
+
+ private void logHeaders(Map<String, List<String>> mm) {
+ if (mm == null || mm.isEmpty()) {
+ return;
+ }
+
+ List<String> ll = new ArrayList<>();
+ for (String s : mm.keySet()) {
+ if (s != null) {
+ ll.add(s);
+ }
+ }
+ Collections.sort(ll);
+
+ for (String name : ll) {
+ List<String> v = mm.get(name);
+ log.info("--- {}:{}", name, String.valueOf(mm.get(name)));
+ log.info("--- " + name + ": " + (v.size() == 1 ? v.get(0) : v));
+ }
+ }
+
+ protected HttpResponse postOnUeb(String request, UebParam p) throws SvcLogicException {
+ String[] urls = uebServers.split(" ");
+ for (int i = 0; i < urls.length; i++) {
+ if (!urls[i].endsWith("/")) {
+ urls[i] += "/";
+ }
+ urls[i] += "events/" + p.topic;
+ }
+
+ Client client = ClientBuilder.newBuilder().build();
+ setClientTimeouts(client);
+ WebTarget webTarget = client.target(urls[0]);
+
+ log.info("UEB URL: {}", urls[0]);
+ log.info("Sending request:");
+ log.info(request);
+ long t1 = System.currentTimeMillis();
+
+ HttpResponse r = new HttpResponse();
+ r.code = 200;
+
+ if (!p.skipSending) {
+ String tt = "application/json";
+ String tt1 = tt + ";charset=UTF-8";
+
+ Response response;
+ Invocation.Builder invocationBuilder = webTarget.request(tt1).accept(tt);
+
+ try {
+ response = invocationBuilder.post(Entity.entity(request, tt1));
+ } catch (ProcessingException e) {
+ throw new SvcLogicException(requestPostingException + e.getLocalizedMessage(), e);
+ }
+ r.code = response.getStatus();
+ r.headers = response.getStringHeaders();
+ if (response.hasEntity()) {
+ r.body = response.readEntity(String.class);
+ }
+ }
+
+ long t2 = System.currentTimeMillis();
+ log.info(responseReceivedMessage, t2 - t1);
+ log.info(responseHttpCodeMessage, r.code);
+ logHeaders(r.headers);
+ log.info("HTTP response:\n {}", r.body);
+
+ return r;
+ }
+
+ public void setUebServers(String uebServers) {
+ this.uebServers = uebServers;
+ }
+
+ public void setDefaultUebTemplateFileName(String defaultUebTemplateFileName) {
+ this.defaultUebTemplateFileName = defaultUebTemplateFileName;
+ }
+
+ protected void setClientTimeouts(Client client) {
+ client.property(ClientProperties.CONNECT_TIMEOUT, httpConnectTimeout);
+ client.property(ClientProperties.READ_TIMEOUT, httpReadTimeout);
+ }
+
+ protected Integer readOptionalInteger(String propertyName, Integer defaultValue) {
+ String stringValue = System.getProperty(propertyName);
+ if (stringValue != null && stringValue.length() > 0) {
+ try {
+ return Integer.valueOf(stringValue);
+ } catch (NumberFormatException e) {
+ log.warn("property " + propertyName + " had the value " + stringValue + " that could not be converted to an Integer, default " + defaultValue + " will be used instead", e);
+ }
+ }
+ return defaultValue;
+ }
+
+ protected static String[] getMultipleUrls(String restapiUrl) {
+ List<String> urls = new ArrayList<>();
+ int start = 0;
+ for (int i = 0; i < restapiUrl.length(); i++) {
+ if (restapiUrl.charAt(i) == ',') {
+ if (i + 9 < restapiUrl.length()) {
+ String part = restapiUrl.substring(i + 1, i + 9);
+ if (part.equals("https://") || part.startsWith("http://")) {
+ urls.add(restapiUrl.substring(start, i));
+ start = i + 1;
+ }
+ }
+ } else if (i == restapiUrl.length() - 1) {
+ urls.add(restapiUrl.substring(start, i + 1));
+ }
+ }
+ String[] arr = new String[urls.size()];
+ return urls.toArray(arr);
+ }
+
+ protected static boolean containsMultipleUrls(String restapiUrl) {
+ Matcher m = retryPattern.matcher(restapiUrl);
+ return m.matches();
+ }
+
+ private static class FileParam {
+
+ public String fileName;
+ public String url;
+ public String user;
+ public String password;
+ public HttpMethod httpMethod;
+ public String responsePrefix;
+ public boolean skipSending;
+ public String oAuthConsumerKey;
+ public String oAuthConsumerSecret;
+ public String oAuthSignatureMethod;
+ public String oAuthVersion;
+ public AuthType authtype;
+ }
+
+ private static class UebParam {
+
+ public String topic;
+ public String templateFileName;
+ public String rootVarName;
+ public String responsePrefix;
+ public boolean skipSending;
+ }
+}
diff --git a/plugins/restapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/restapicall/RetryException.java b/plugins/restapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/restapicall/RetryException.java
new file mode 100644
index 000000000..03078c652
--- /dev/null
+++ b/plugins/restapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/restapicall/RetryException.java
@@ -0,0 +1,30 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.restapicall;
+
+public class RetryException extends Exception {
+
+ public RetryException(String message) {
+ super(message);
+ }
+
+}
diff --git a/plugins/restapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/restapicall/RetryPolicy.java b/plugins/restapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/restapicall/RetryPolicy.java
new file mode 100644
index 000000000..8d5143be3
--- /dev/null
+++ b/plugins/restapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/restapicall/RetryPolicy.java
@@ -0,0 +1,64 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * Modifications Copyright © 2018 IBM
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.restapicall;
+
+public class RetryPolicy {
+ private String[] hostnames;
+ private Integer maximumRetries;
+ private int position;
+ private int retryCount;
+
+ public RetryPolicy(String[] hostnames, Integer maximumRetries) {
+ this.hostnames = hostnames;
+ this.maximumRetries = maximumRetries;
+ this.position = 0;
+ this.retryCount = 0;
+
+ }
+
+ public Integer getMaximumRetries() {
+ return maximumRetries;
+ }
+
+ public int getRetryCount() {
+ return retryCount;
+ }
+
+ public Boolean shouldRetry() {
+ return retryCount < maximumRetries + 1;
+ }
+
+ public String getRetryMessage() {
+ return retryCount + " retry attempts were made out of " + maximumRetries + " maximum retry attempts.";
+ }
+
+ public String getNextHostName() throws RetryException {
+ retryCount++;
+ position++;
+ if (position > hostnames.length - 1) {
+ position = 0;
+ }
+ return hostnames[position];
+ }
+
+}
diff --git a/plugins/restapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/restapicall/XmlJsonUtil.java b/plugins/restapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/restapicall/XmlJsonUtil.java
new file mode 100644
index 000000000..9870221d7
--- /dev/null
+++ b/plugins/restapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/restapicall/XmlJsonUtil.java
@@ -0,0 +1,518 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.restapicall;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.apache.commons.text.StringEscapeUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public final class XmlJsonUtil {
+
+ @SuppressWarnings("unused")
+ private static final Logger log = LoggerFactory.getLogger(XmlJsonUtil.class);
+
+ private XmlJsonUtil() {
+ // Preventing instantiation of the same.
+ }
+
+ public static String getXml(Map<String, String> varmap, String var) {
+ boolean escape = true;
+ if (var.startsWith("'")) {
+ var = var.substring(1);
+ escape = false;
+ }
+
+ Object o = createStructure(varmap, var);
+ return generateXml(o, 0, escape);
+ }
+
+ public static String getJson(Map<String, String> varmap, String var) {
+ boolean escape = true;
+ if (var.startsWith("'")) {
+ var = var.substring(1);
+ escape = false;
+ }
+
+ boolean quotes = true;
+ if (var.startsWith("\"")) {
+ var = var.substring(1);
+ quotes = false;
+ }
+
+ Object o = createStructure(varmap, var);
+ return generateJson(o, escape, quotes);
+ }
+
+ private static Object createStructure(Map<String, String> flatmap, String var) {
+ if (flatmap.containsKey(var)) {
+ return flatmap.get(var);
+ }
+
+ Map<String, Object> mm = new HashMap<>();
+ List<Object> ll = new ArrayList<>();
+
+ for (Map.Entry<String, String> e : flatmap.entrySet()) {
+ String key = e.getKey();
+ String value = e.getValue();
+
+ if (key.endsWith("_length") || key.endsWith("].key")) {
+ continue;
+ }
+
+ if (value == null || value.trim().isEmpty()) {
+ continue;
+ }
+
+ if (key.startsWith(var + "[")) {
+ String newKey = key.substring(var.length());
+ set(ll, newKey, value);
+ } else if (var == null || var.isEmpty()) {
+ set(mm, key, value);
+ } else if (key.startsWith(var + ".")) {
+ String newKey = key.substring(var.length() + 1);
+ set(mm, newKey, value);
+ }
+ }
+
+ if (!mm.isEmpty()) {
+ return mm;
+ }
+ if (!ll.isEmpty()) {
+ return ll;
+ }
+ return null;
+ }
+
+ @SuppressWarnings("unchecked")
+ public static void set(Object struct, String compositeKey, Object value) {
+ if (struct == null) {
+ throw new IllegalArgumentException("Null argument: struct");
+ }
+
+ if (compositeKey == null || compositeKey.length() == 0) {
+ throw new IllegalArgumentException("Null or empty argument: compositeKey");
+ }
+
+ if (value == null) {
+ return;
+ }
+
+ List<Object> keys = splitCompositeKey(compositeKey);
+ Object currentValue = struct;
+ String currentKey = "";
+
+ for (int i = 0; i < keys.size() - 1; i++) {
+ Object key = keys.get(i);
+
+ if (key instanceof Integer) {
+ if (!(currentValue instanceof List)) {
+ throw new IllegalArgumentException("Cannot resolve: " + compositeKey + ": References list '" + currentKey + "', but '" + currentKey + "' is not a list");
+ }
+
+ Integer keyi = (Integer) key;
+ List<Object> currentValueL = (List<Object>) currentValue;
+ int size = currentValueL.size();
+
+ if (keyi >= size) {
+ for (int k = 0; k < keyi - size + 1; k++) {
+ currentValueL.add(null);
+ }
+ }
+
+ Object newValue = currentValueL.get(keyi);
+ if (newValue == null) {
+ Object nextKey = keys.get(i + 1);
+ if (nextKey instanceof Integer) {
+ newValue = new ArrayList<>();
+ } else {
+ newValue = new HashMap<>();
+ }
+ currentValueL.set(keyi, newValue);
+ }
+
+ currentValue = newValue;
+ currentKey += "[" + key + "]";
+
+ } else {
+ if (!(currentValue instanceof Map)) {
+ throw new IllegalArgumentException("Cannot resolve: " + compositeKey + ": References map '" + currentKey + "', but '" + currentKey + "' is not a map");
+ }
+
+ Object newValue = ((Map<String, Object>) currentValue).get(key);
+ if (newValue == null) {
+ Object nextKey = keys.get(i + 1);
+ if (nextKey instanceof Integer) {
+ newValue = new ArrayList<>();
+ } else {
+ newValue = new HashMap<>();
+ }
+ ((Map<String, Object>) currentValue).put((String) key, newValue);
+ }
+
+ currentValue = newValue;
+ currentKey += "." + key;
+ }
+ }
+
+ Object key = keys.get(keys.size() - 1);
+ if (key instanceof Integer) {
+ if (!(currentValue instanceof List)) {
+ throw new IllegalArgumentException("Cannot resolve: " + compositeKey + ": References list '" + currentKey + "', but '" + currentKey + "' is not a list");
+ }
+
+ Integer keyi = (Integer) key;
+ List<Object> currentValueL = (List<Object>) currentValue;
+ int size = currentValueL.size();
+
+ if (keyi >= size) {
+ for (int k = 0; k < keyi - size + 1; k++) {
+ currentValueL.add(null);
+ }
+ }
+
+ currentValueL.set(keyi, value);
+
+ } else {
+ if (!(currentValue instanceof Map)) {
+ throw new IllegalArgumentException("Cannot resolve: " + compositeKey + ": References map '" + currentKey + "', but '" + currentKey + "' is not a map");
+ }
+
+ ((Map<String, Object>) currentValue).put((String) key, value);
+ }
+ }
+
+ private static List<Object> splitCompositeKey(String compositeKey) {
+ if (compositeKey == null) {
+ return Collections.emptyList();
+ }
+
+ String[] ss = compositeKey.split("\\.");
+ List<Object> ll = new ArrayList<>();
+ for (String s : ss) {
+ if (s.length() == 0) {
+ continue;
+ }
+
+ int i1 = s.indexOf('[');
+ if (i1 < 0) {
+ ll.add(s);
+ } else {
+ if (!s.endsWith("]")) {
+ throw new IllegalArgumentException("Invalid composite key: " + compositeKey + ": No matching ] found");
+ }
+
+ String s1 = s.substring(0, i1);
+ if (s1.length() > 0) {
+ ll.add(s1);
+ }
+
+ String s2 = s.substring(i1 + 1, s.length() - 1);
+ try {
+ int n = Integer.parseInt(s2);
+ if (n < 0) {
+ throw new IllegalArgumentException("Invalid composite key: " + compositeKey + ": Index must be >= 0: " + n);
+ }
+
+ ll.add(n);
+ } catch (NumberFormatException e) {
+ throw new IllegalArgumentException("Invalid composite key: " + compositeKey + ": Index not a number: " + s2);
+ }
+ }
+ }
+
+ return ll;
+ }
+
+ @SuppressWarnings("unchecked")
+ private static String generateXml(Object o, int indent, boolean escape) {
+ if (o == null) {
+ return null;
+ }
+
+ if (o instanceof String) {
+ return escape ? StringEscapeUtils.escapeXml10((String) o) : (String) o;
+ };
+
+ if (o instanceof Map) {
+ StringBuilder ss = new StringBuilder();
+ Map<String, Object> mm = (Map<String, Object>) o;
+ for (Map.Entry<String, Object> entry : mm.entrySet()) {
+ Object v = entry.getValue();
+ String key = entry.getKey();
+ if (v instanceof String) {
+ String s = escape ? StringEscapeUtils.escapeXml10((String) v) : (String) v;
+ ss.append(pad(indent)).append('<').append(key).append('>');
+ ss.append(s);
+ ss.append("</").append(key).append('>').append('\n');
+ } else if (v instanceof Map) {
+ ss.append(pad(indent)).append('<').append(key).append('>').append('\n');
+ ss.append(generateXml(v, indent + 1, escape));
+ ss.append(pad(indent)).append("</").append(key).append('>').append('\n');
+ } else if (v instanceof List) {
+ List<Object> ll = (List<Object>) v;
+ for (Object o1 : ll) {
+ ss.append(pad(indent)).append('<').append(key).append('>').append('\n');
+ ss.append(generateXml(o1, indent + 1, escape));
+ ss.append(pad(indent)).append("</").append(key).append('>').append('\n');
+ }
+ }
+ }
+ return ss.toString();
+ }
+
+ return null;
+ }
+ private static String generateJson(Object o, boolean escape, boolean quotes) {
+ if (o == null) {
+ return null;
+ }
+ if (o instanceof String && ((String) o).length() == 0) {
+ return null;
+ }
+
+ StringBuilder ss = new StringBuilder();
+ generateJson(ss, o, 0, false, escape, quotes);
+ return ss.toString();
+ }
+
+ @SuppressWarnings("unchecked")
+ private static void generateJson(StringBuilder ss, Object o, int indent, boolean padFirst, boolean escape, boolean quotes) {
+ if (o instanceof String) {
+ String s = escape ? StringEscapeUtils.escapeJson((String) o) : (String) o;
+ if (padFirst) {
+ ss.append(pad(indent));
+ }
+ if (quotes) {
+ ss.append('"').append(s).append('"');
+ } else {
+ ss.append(s);
+ }
+ return;
+ }
+
+ if (o instanceof Map) {
+ Map<String, Object> mm = (Map<String, Object>) o;
+
+ if (padFirst) {
+ ss.append(pad(indent));
+ }
+ ss.append("{\n");
+
+ boolean first = true;
+ for (Map.Entry<String, Object> entry : mm.entrySet()) {
+ if (!first) {
+ ss.append(",\n");
+ }
+ first = false;
+ Object v = entry.getValue();
+ String key = entry.getKey();
+ ss.append(pad(indent + 1)).append('"').append(key).append("\": ");
+ generateJson(ss, v, indent + 1, false, escape, true);
+ }
+
+ ss.append("\n");
+ ss.append(pad(indent)).append('}');
+
+ return;
+ }
+
+ if (o instanceof List) {
+ List<Object> ll = (List<Object>) o;
+
+ if (padFirst) {
+ ss.append(pad(indent));
+ }
+ ss.append("[\n");
+
+ boolean first = true;
+ for (Object o1 : ll) {
+ if (!first) {
+ ss.append(",\n");
+ }
+ first = false;
+
+ generateJson(ss, o1, indent + 1, true, escape, quotes);
+ }
+
+ ss.append("\n");
+ ss.append(pad(indent)).append(']');
+ }
+ }
+
+ public static String removeLastCommaJson(String s) {
+ StringBuilder sb = new StringBuilder();
+ int k = 0;
+ int start = 0;
+ while (k < s.length()) {
+ int i11 = s.indexOf('}', k);
+ int i12 = s.indexOf(']', k);
+ int i1 = -1;
+ if (i11 < 0) {
+ i1 = i12;
+ } else if (i12 < 0) {
+ i1 = i11;
+ } else {
+ i1 = i11 < i12 ? i11 : i12;
+ }
+ if (i1 < 0) {
+ break;
+ }
+
+ int i2 = s.lastIndexOf(',', i1);
+ if (i2 < 0) {
+ k = i1 + 1;
+ continue;
+ }
+
+ String between = s.substring(i2 + 1, i1);
+ if (between.trim().length() > 0) {
+ k = i1 + 1;
+ continue;
+ }
+
+ sb.append(s.substring(start, i2));
+ start = i2 + 1;
+ k = i1 + 1;
+ }
+
+ sb.append(s.substring(start, s.length()));
+
+ return sb.toString();
+ }
+
+ public static String removeEmptyStructJson(String template, String s) {
+ int k = 0;
+ while (k < s.length()) {
+ boolean curly = true;
+ int i11 = s.indexOf('{', k);
+ int i12 = s.indexOf('[', k);
+ int i1 = -1;
+ if (i11 < 0) {
+ i1 = i12;
+ curly = false;
+ } else if (i12 < 0) {
+ i1 = i11;
+ } else if (i11 < i12) {
+ i1 = i11;
+ } else {
+ i1 = i12;
+ curly = false;
+ }
+
+ if (i1 >= 0) {
+ int i2 = curly ? s.indexOf('}', i1) : s.indexOf(']', i1);
+ if (i2 > 0) {
+ String value = s.substring(i1 + 1, i2);
+ if (value.trim().length() == 0) {
+ int i4 = s.lastIndexOf('\n', i1);
+ if (i4 < 0) {
+ i4 = 0;
+ }
+ int i5 = s.indexOf('\n', i2);
+ if (i5 < 0) {
+ i5 = s.length();
+ }
+
+
+ /*If template mandates empty construct to be present, those should not be removed.*/
+ if (template != null && template.contains(s.substring(i4))) {
+ k = i1 + 1;
+ } else {
+ s = s.substring(0, i4) + s.substring(i5);
+ k = 0;
+ }
+ } else {
+ k = i1 + 1;
+ }
+ } else {
+ break;
+ }
+ } else {
+ break;
+ }
+ }
+
+ return s;
+ }
+
+ public static String removeEmptyStructXml(String s) {
+ int k = 0;
+ while (k < s.length()) {
+ int i1 = s.indexOf('<', k);
+ if (i1 < 0 || i1 == s.length() - 1) {
+ break;
+ }
+
+ char c1 = s.charAt(i1 + 1);
+ if (c1 == '?' || c1 == '!') {
+ k = i1 + 2;
+ continue;
+ }
+
+ int i2 = s.indexOf('>', i1);
+ if (i2 < 0) {
+ k = i1 + 1;
+ continue;
+ }
+
+ String closingTag = "</" + s.substring(i1 + 1, i2 + 1);
+ int i3 = s.indexOf(closingTag, i2 + 1);
+ if (i3 < 0) {
+ k = i2 + 1;
+ continue;
+ }
+
+ String value = s.substring(i2 + 1, i3);
+ if (value.trim().length() > 0) {
+ k = i2 + 1;
+ continue;
+ }
+
+ int i4 = s.lastIndexOf('\n', i1);
+ if (i4 < 0) {
+ i4 = 0;
+ }
+ int i5 = s.indexOf('\n', i3);
+ if (i5 < 0) {
+ i5 = s.length();
+ }
+
+ s = s.substring(0, i4) + s.substring(i5);
+ k = 0;
+ }
+
+ return s;
+ }
+
+ private static String pad(int n) {
+ StringBuilder s = new StringBuilder();
+ for (int i = 0; i < n; i++) {
+ s.append(Character.toString('\t'));
+ }
+ return s.toString();
+ }
+}
diff --git a/plugins/restapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/restapicall/XmlParser.java b/plugins/restapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/restapicall/XmlParser.java
new file mode 100644
index 000000000..42e9e57ad
--- /dev/null
+++ b/plugins/restapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/restapicall/XmlParser.java
@@ -0,0 +1,180 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * Modifications Copyright © 2018 IBM
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.restapicall;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+import javax.xml.XMLConstants;
+
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+import org.xml.sax.XMLReader;
+
+public final class XmlParser {
+
+ private static final Logger log = LoggerFactory.getLogger(XmlParser.class);
+
+ private XmlParser() {
+ // Preventing instantiation of the same.
+ }
+
+ public static Map<String, String> convertToProperties(String s, Set<String> listNameList)
+ throws SvcLogicException {
+
+ checkNotNull(s, "Input should not be null.");
+
+ Handler handler = new Handler(listNameList);
+ try {
+ SAXParserFactory spf = SAXParserFactory.newInstance();
+ spf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
+ spf.setFeature("http://xml.org/sax/features/external-general-entities", false);
+ spf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
+ spf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
+ InputStream in = new ByteArrayInputStream(s.getBytes());
+ SAXParser saxParser = spf.newSAXParser();
+ saxParser.parse(in, handler);
+
+ } catch (ParserConfigurationException | IOException | SAXException | NumberFormatException e) {
+ throw new SvcLogicException("Unable to convert XML to properties" + e.getLocalizedMessage(), e);
+ }
+ return handler.getProperties();
+ }
+
+ private static class Handler extends DefaultHandler {
+
+ private Set<String> listNameList;
+
+ private Map<String, String> properties = new HashMap<>();
+
+ StringBuilder currentName = new StringBuilder();
+ StringBuilder currentValue = new StringBuilder();
+
+ public Handler(Set<String> listNameList) {
+ super();
+ this.listNameList = listNameList;
+ if (this.listNameList == null)
+ this.listNameList = new HashSet<>();
+ }
+
+ public Map<String, String> getProperties() {
+ return properties;
+ }
+
+ @Override
+ public void startElement(String uri, String localName, String qName, Attributes attributes)
+ throws SAXException {
+ super.startElement(uri, localName, qName, attributes);
+
+ String name = localName;
+ if (name == null || name.trim().length() == 0)
+ name = qName;
+ int i2 = name.indexOf(':');
+ if (i2 >= 0)
+ name = name.substring(i2 + 1);
+
+ if (currentName.length() > 0)
+ currentName.append(Character.toString('.'));
+ currentName.append(name);
+
+ String listName = removeIndexes(currentName.toString());
+
+ if (listNameList.contains(listName)) {
+ String n = currentName.toString() + "_length";
+ int len = getInt(properties, n);
+ properties.put(n, String.valueOf(len + 1));
+ currentName.append("[").append(len).append("]");
+ }
+ }
+
+ @Override
+ public void endElement(String uri, String localName, String qName) throws SAXException {
+ super.endElement(uri, localName, qName);
+
+ String name = localName;
+ if (name == null || name.trim().length() == 0)
+ name = qName;
+ int i2 = name.indexOf(':');
+ if (i2 >= 0)
+ name = name.substring(i2 + 1);
+
+ String s = currentValue.toString().trim();
+ if (s.length() > 0) {
+ properties.put(currentName.toString(), s);
+
+ log.info("Added property: {} : {}", currentName, s);
+ currentValue = new StringBuilder();
+ }
+
+ int i1 = currentName.lastIndexOf("." + name);
+ if (i1 <= 0)
+ currentName = new StringBuilder();
+ else
+ currentName = new StringBuilder(currentName.substring(0, i1));
+ }
+
+ @Override
+ public void characters(char[] ch, int start, int length) throws SAXException {
+ super.characters(ch, start, length);
+
+ String value = new String(ch, start, length);
+ currentValue.append(value);
+ }
+
+ private static int getInt(Map<String, String> mm, String name) {
+ String s = mm.get(name);
+ if (s == null)
+ return 0;
+ return Integer.parseInt(s);
+ }
+
+ private String removeIndexes(String currentName) {
+ StringBuilder b = new StringBuilder();
+ boolean add = true;
+ for (int i = 0; i < currentName.length(); i++) {
+ char c = currentName.charAt(i);
+ if (c == '[')
+ add = false;
+ else if (c == ']')
+ add = true;
+ else if (add)
+ b.append(Character.toString(c));
+ }
+ return b.toString();
+ }
+ }
+}
diff --git a/plugins/restapi-call-node/provider/src/main/resources/OSGI-INF/blueprint/restapi-call-node-blueprint.xml b/plugins/restapi-call-node/provider/src/main/resources/OSGI-INF/blueprint/restapi-call-node-blueprint.xml
new file mode 100755
index 000000000..390bb0a35
--- /dev/null
+++ b/plugins/restapi-call-node/provider/src/main/resources/OSGI-INF/blueprint/restapi-call-node-blueprint.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+ xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0"
+ odl:use-default-for-reference-types="true">
+
+ <bean id="restapiCallNodeProvider" class="org.onap.ccsdk.sli.plugins.restapicall.RestapiCallNode" />
+
+
+
+ <service ref="restapiCallNodeProvider">
+ <interfaces>
+ <value>org.onap.ccsdk.sli.plugins.restapicall.RestapiCallNode</value>
+ </interfaces>
+ </service>
+
+</blueprint> \ No newline at end of file
diff --git a/plugins/restapi-call-node/provider/src/main/resources/actokentemplate.json b/plugins/restapi-call-node/provider/src/main/resources/actokentemplate.json
new file mode 100644
index 000000000..02e62400f
--- /dev/null
+++ b/plugins/restapi-call-node/provider/src/main/resources/actokentemplate.json
@@ -0,0 +1,4 @@
+{
+ "userName": ${prop.sdncRestApi.thirdpartySdnc.user},
+ "password": ${prop.sdncRestApi.thirdpartySdnc.password}
+}
diff --git a/plugins/restapi-call-node/provider/src/main/resources/default-ueb-message.json b/plugins/restapi-call-node/provider/src/main/resources/default-ueb-message.json
new file mode 100644
index 000000000..484d872f5
--- /dev/null
+++ b/plugins/restapi-call-node/provider/src/main/resources/default-ueb-message.json
@@ -0,0 +1,11 @@
+{
+ "event":{
+ "header":{
+ "eventSource":"sdn-c"
+ },
+ "body":
+
+${rootVarName}
+
+ }
+}
diff --git a/plugins/restapi-call-node/provider/src/main/resources/get-multicast-data.json b/plugins/restapi-call-node/provider/src/main/resources/get-multicast-data.json
new file mode 100644
index 000000000..3b9997f64
--- /dev/null
+++ b/plugins/restapi-call-node/provider/src/main/resources/get-multicast-data.json
@@ -0,0 +1,13 @@
+{
+ "input": {
+ "sdnc-request-header": {
+ "svc-request-id": ${connection-details-notification-input.configuration-response-common.svc-request-id},
+ "svc-action": "updatemulticastvpn"
+ },
+ "service-information": {
+ "service-type": "AVPN",
+ "service-instance-id": ${tmp.ete-vpn-key}
+ }
+ }
+}
+
diff --git a/plugins/restapi-call-node/provider/src/main/resources/l2-dci-connects-template.json b/plugins/restapi-call-node/provider/src/main/resources/l2-dci-connects-template.json
new file mode 100644
index 000000000..e0896bbaa
--- /dev/null
+++ b/plugins/restapi-call-node/provider/src/main/resources/l2-dci-connects-template.json
@@ -0,0 +1,11 @@
+{
+ "l2-dci-connect": {
+ "id": ${prop.dci-connects.id},
+ "name": ${prop.dci-connects.name},
+ "description": ${prop.dci-connects.description},
+ "network_id": ${prop.dci-connects.local_networks[0]},
+ "evpn_irts": ${prop.dci-connects.evpn_irts},
+ "evpn_erts": ${prop.dci-connects.evpn_erts},
+ "vni": ${prop.dci-connects.vni}
+ }
+}
diff --git a/plugins/restapi-call-node/provider/src/main/resources/l3-dci-connects-template.json b/plugins/restapi-call-node/provider/src/main/resources/l3-dci-connects-template.json
new file mode 100644
index 000000000..41df794fd
--- /dev/null
+++ b/plugins/restapi-call-node/provider/src/main/resources/l3-dci-connects-template.json
@@ -0,0 +1,14 @@
+{
+ "l3-dci-connect": {
+ "id": ${prop.dci-connects.id},
+ "name": ${prop.dci-connects.name},
+ "description": ${prop.dci-connects.description},
+ "router_id": ${prop.dci-connects.router_id},
+ "firewall_enable": false,
+ "local_networks": ${prop.dci-connects.local_networks},
+ "local_network_all": false,
+ "evpn_irts": ${prop.dci-connects.evpn_irts},
+ "evpn_erts": ${prop.dci-connects.evpn_erts},
+ "l3_vni": ${prop.dci-connects.vni}
+ }
+}
diff --git a/plugins/restapi-call-node/provider/src/main/resources/l3smsitetemplate.json b/plugins/restapi-call-node/provider/src/main/resources/l3smsitetemplate.json
new file mode 100644
index 000000000..8f8156698
--- /dev/null
+++ b/plugins/restapi-call-node/provider/src/main/resources/l3smsitetemplate.json
@@ -0,0 +1,162 @@
+{
+ "site":[
+ {
+ "site-id": ${prop.l3vpn.site1_name},
+ "vpn-policies": {
+ "vpn-policy": [
+ {
+ "vpn-policy-id": ${prop.l3vpn.vpn-policy1-id},
+ "entries": [
+ {
+ "id": ${prop.l3vpn.entry1-id},
+ "vpn": {
+ "vpn-id": ${prop.l3vpn.name},
+ "site-role": "huawei-ac-net-l3vpn-svc:any-to-any-role"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ "site-network-accesses": {
+ "site-network-access": [
+ {
+ "site-network-access-id": ${prop.l3vpn.sna1_name},
+ "bearer": {
+ "appointed-access": {
+ "ne-id": ${prop.l3vpn.pe1_id},
+ "ltp-id": ${prop.l3vpn.ac1_id},
+ "vlan": {
+ "type": "huawei-ac-net-l3vpn-svc:vlan-dot1q",
+ "vlan-id": ${prop.l3vpn.sna1_svlan}
+ }
+ }
+ },
+ "ip-connection": {
+ "ipv4": {
+ "address-allocation-type": "huawei-ac-net-l3vpn-svc:static-address",
+ "addresses": {
+ "provider-address": ${prop.l3vpn.ac1-peer-ip},
+ "customer-address": ${prop.l3vpn.ac1-ip},
+ "mask": "24"
+ }
+ }
+ },
+ "service": {
+ "mtu": "1500"
+ },
+ "routing-protocols": {
+ "routing-protocol": [
+ {
+ "type": ${prop.l3vpn.ac1_protocol},
+ "static": {
+ "cascaded-lan-prefixes": [
+ {
+ "ipv4-lan-prefixes": [
+ {
+ "ip-prefix": ${prop.l3vpn.sna1-route.ip-prefix},
+ "next-hop": ${prop.l3vpn.sna1-route.next-hop}
+ }
+ ]
+ }
+ ]
+ }
+ "bgp": {
+ "peers": [
+ {
+ "peer-ip": ${prop.l3vpn.peer1-ip},
+ "remote-as": ${prop.l3vpn.ac1_protocol_bgp_as}
+ }
+ ]
+ }
+ }
+ }
+ ]
+ },
+ "vpn-attachment": {
+ "vpn-policy-id": ${prop.l3vpn.name}
+ }
+ }
+ ]
+ },
+ {
+ "site-id": ${prop.l3vpn.site2_name},
+ "vpn-policies": {
+ "vpn-policy": [
+ {
+ "vpn-policy-id": ${prop.l3vpn.vpn-policy2-id},
+ "entries": [
+ {
+ "id": ${prop.l3vpn.entry2-id},
+ "vpn": {
+ "vpn-id": ${prop.l3vpn.name},
+ "site-role": "huawei-ac-net-l3vpn-svc:any-to-any-role"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ "site-network-accesses": {
+ "site-network-access": [
+ {
+ "site-network-access-id": ${prop.l3vpn.sna2_name},
+ "bearer": {
+ "appointed-access": {
+ "ne-id": ${prop.l3vpn.pe2_id},
+ "ltp-id": ${prop.l3vpn.ac2_id},
+ "vlan": {
+ "type": "huawei-ac-net-l3vpn-svc:vlan-dot1q",
+ "vlan-id": ${prop.l3vpn.sna2_svlan}
+ }
+ }
+ },
+ "ip-connection": {
+ "ipv4": {
+ "address-allocation-type": "huawei-ac-net-l3vpn-svc:static-address",
+ "addresses": {
+ "provider-address": ${prop.l3vpn.ac2-peer-ip},
+ "customer-address": ${prop.l3vpn.ac2-ip},
+ "mask": "24"
+ }
+ }
+ },
+ "service": {
+ "mtu": "1500"
+ },
+ "routing-protocols": {
+ "routing-protocol": [
+ {
+ "type": ${prop.l3vpn.ac2_protocol},
+ "static": {
+ "cascaded-lan-prefixes": [
+ {
+ "ipv4-lan-prefixes": [
+ {
+ "ip-prefix": ${prop.l3vpn.sna2-route.ip-prefix},
+ "next-hop": ${prop.l3vpn.sna2-route.next-hop}
+ }
+ ]
+ }
+ ]
+ }
+ "bgp": {
+ "peers": [
+ {
+ "peer-ip": ${prop.l3vpn.peer2-ip},
+ "remote-as": ${prop.l3vpn.ac2_protocol_bgp_as}
+ }
+ ]
+ }
+ }
+ ]
+ },
+ "vpn-attachment": {
+ "vpn-policy-id": ${prop.l3vpn.name}
+ }
+ }
+ ]
+ }
+ ]
+}
+
diff --git a/plugins/restapi-call-node/provider/src/main/resources/l3smvpntemplate.json b/plugins/restapi-call-node/provider/src/main/resources/l3smvpntemplate.json
new file mode 100644
index 000000000..30f30a24f
--- /dev/null
+++ b/plugins/restapi-call-node/provider/src/main/resources/l3smvpntemplate.json
@@ -0,0 +1,10 @@
+{
+ "vpn-service": [
+ {
+ "vpn-id": ${prop.l3vpn.name},
+ "customer-name": "huawei",
+ "vpn-service-topology": ${prop.l3vpn.topology},
+ "route-exchange-policy": "huawei-ac-net-l3vpn-svc:vpnv4-way"
+ }
+ ]
+}
diff --git a/plugins/restapi-call-node/provider/src/main/resources/l3smvrftemplate.json b/plugins/restapi-call-node/provider/src/main/resources/l3smvrftemplate.json
new file mode 100644
index 000000000..52359a7fd
--- /dev/null
+++ b/plugins/restapi-call-node/provider/src/main/resources/l3smvrftemplate.json
@@ -0,0 +1,14 @@
+{
+ "vrf-attribute": [
+ {
+ "vrf-attribute-id": ${prop.l3vpn.vrf1-id},
+ "ne-id": ${prop.l3vpn.pe1_id},
+ "vpn-policy-id": ${prop.l3vpn.vpn-policy1-id}
+ },
+ {
+ "vrf-attribute-id": ${prop.l3vpn.vrf2-id},
+ "ne-id": ${prop.l3vpn.pe2_id},
+ "vpn-policy-id": ${prop.l3vpn.vpn-policy2-id}
+ }
+ ]
+}
diff --git a/plugins/restapi-call-node/provider/src/main/resources/northbound-api-template.json b/plugins/restapi-call-node/provider/src/main/resources/northbound-api-template.json
new file mode 100644
index 000000000..f185c8f5d
--- /dev/null
+++ b/plugins/restapi-call-node/provider/src/main/resources/northbound-api-template.json
@@ -0,0 +1,22 @@
+{
+"input":
+ {
+ "sdnc-request-header":{
+ "svc-request-id": ${service-topology-operation-input.sdnc-request-header.svc-request-id},
+ "svc-notification-url": ${service-topology-operation-input.sdnc-request-header.svc-notification-url}
+ },
+ "request-information":{
+ "request-id": ${service-topology-operation-input.request-information.request-id},
+ "request-action": ${service-topology-operation-input.request-information.request-action},
+ "request-sub-action": ${service-topology-operation-input.request-information.request-sub-action},
+ "source": ${service-topology-operation-input.request-information.source},
+ "notification-url": ${service-topology-operation-input.request-information.notification-url}
+ },
+ "service-information":{
+ "service-type": ${service-topology-operation-input.service-information.service-type},
+ "service-instance-id": ${service-topology-operation-input.service-information.service-instance-id},
+ "subscriber-name": ${service-topology-operation-input.service-information.subscriber-name},
+ "subscriber-global-id": ${service-topology-operation-input.service-information.subscriber-global-id}
+ }
+}
+
diff --git a/plugins/restapi-call-node/provider/src/main/resources/northbound-api-template.xml b/plugins/restapi-call-node/provider/src/main/resources/northbound-api-template.xml
new file mode 100644
index 000000000..aea0625c1
--- /dev/null
+++ b/plugins/restapi-call-node/provider/src/main/resources/northbound-api-template.xml
@@ -0,0 +1,43 @@
+<!--
+ ============LICENSE_START=======================================================
+ openECOMP : SDN-C
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property. All rights
+ reserved.
+ ================================================================================
+ 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.
+ ============LICENSE_END=========================================================
+ -->
+
+ <input xmlns="${northbound-xmlNS}">
+ <${northbound-Container}>
+ <request-information>
+ <notification-url>${service-topology-operation-input.request-information.notification-url}</notification-url>
+ <request-action>${service-topology-operation-input.request-information.request-action}</request-action>
+ <request-id>${service-topology-operation-input.request-information.request-id}</request-id>
+ <request-sub-action>${service-topology-operation-input.request-information.request-sub-action}</request-sub-action>
+ <source>${service-topology-operation-input.request-information.source}</source>
+ </request-information>
+ <sdnc-request-header>
+ <svc-notification-url>${service-topology-operation-input.sdnc-request-header.svc-notification-url}</svc-notification-url>
+ <svc-request-id>${service-topology-operation-input.sdnc-request-header.svc-request-id}</svc-request-id>
+ </sdnc-request-header>
+ <service-information>
+ <service-instance-id>${service-topology-operation-input.service-information.service-instance-id}</service-instance-id>
+ <service-type>${service-topology-operation-input.service-information.service-type}</service-type>
+ <subscriber-global-id>${service-topology-operation-input.service-information.subscriber-global-id}</subscriber-global-id>
+ <subscriber-name>${service-topology-operation-input.service-information.subscriber-name}</subscriber-name>
+ </service-information>
+ ${'northbound-anyData}
+ </${northbound-Container}>
+ </input>
diff --git a/plugins/restapi-call-node/provider/src/main/resources/org/opendaylight/blueprint/restapi-call-node-blueprint.xml b/plugins/restapi-call-node/provider/src/main/resources/org/opendaylight/blueprint/restapi-call-node-blueprint.xml
new file mode 100755
index 000000000..390bb0a35
--- /dev/null
+++ b/plugins/restapi-call-node/provider/src/main/resources/org/opendaylight/blueprint/restapi-call-node-blueprint.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+ xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0"
+ odl:use-default-for-reference-types="true">
+
+ <bean id="restapiCallNodeProvider" class="org.onap.ccsdk.sli.plugins.restapicall.RestapiCallNode" />
+
+
+
+ <service ref="restapiCallNodeProvider">
+ <interfaces>
+ <value>org.onap.ccsdk.sli.plugins.restapicall.RestapiCallNode</value>
+ </interfaces>
+ </service>
+
+</blueprint> \ No newline at end of file
diff --git a/plugins/restapi-call-node/provider/src/main/resources/service-configuration-notification-northbound-template.json b/plugins/restapi-call-node/provider/src/main/resources/service-configuration-notification-northbound-template.json
new file mode 100644
index 000000000..c64661720
--- /dev/null
+++ b/plugins/restapi-call-node/provider/src/main/resources/service-configuration-notification-northbound-template.json
@@ -0,0 +1,23 @@
+{
+ "input": {
+ "svc-request-id": ${service-configuration-notification-input.svc-request-id},
+ "response-code": ${service-configuration-notification-input.response-code},
+ "response-message": ${service-configuration-notification-input.response-message},
+ "ack-final-indicator": ${service-configuration-notification-input.ack-final-indicator},
+ "service-information": {
+ "service-type": ${service-data.service-information.service-type},
+ "service-instance-id": ${service-data.service-information.service-instance-id},
+ "subscriber-name": ${service-data.service-information.subscriber-name},
+ "subscriber-global-id": ${service-data.service-information.subscriber-global-id}
+ },
+ "response-parameters": [
+ ${repeat:service-configuration-notification-input.response-parameters_length:
+ {
+ "sequence-number": ${service-configuration-notification-input.response-parameters[${1}].sequence-number},
+ "tag-name": ${service-configuration-notification-input.response-parameters[${1}].tag-name},
+ "tag-value": ${service-configuration-notification-input.response-parameters[${1}].tag-value}
+ }
+ }
+ ]
+ }
+}
diff --git a/plugins/restapi-call-node/provider/src/main/resources/sptn-l3vpn-template.json b/plugins/restapi-call-node/provider/src/main/resources/sptn-l3vpn-template.json
new file mode 100644
index 000000000..e850cb9a0
--- /dev/null
+++ b/plugins/restapi-call-node/provider/src/main/resources/sptn-l3vpn-template.json
@@ -0,0 +1,159 @@
+{
+ "snc-l3vpn": {
+ "-xmlns": "urn:chinamobile:l3vpn",
+ "operate-status": "operate-up",
+ "traffic-class": "BE",
+ "acs": {
+ "l3-acs": [
+ {
+ "id": "0",
+ "ne-id": ${prop.l3vpn.pe1_id},
+ "ltp-id": ${prop.l3vpn.ac1_id},
+ "ip-addr": ${prop.l3vpn.ac1_ip.value},
+ "ip-mask": ${prop.l3vpn.ac1_ip.mask},
+ "access-type": "Sub-interface",
+ "vlan": ${prop.l3vpn.ac1_svlan},
+ "qos": {
+ "belonged-id": ${prop.l3vpn.ac1_id},
+ "tunnel-mode": "pipeline",
+ "cac-mode": "1",
+ "convg-mode": "0",
+ "traffic-adj-mode": "0",
+ "a2z-policing": "1",
+ "z2a-policing": "1",
+ "a2z-cir": "5000",
+ "z2a-cir": "5000",
+ "a2z-pir": "1000000",
+ "z2a-pir": "1000000",
+ "a2z-cbs": "1024",
+ "z2a-cbs": "1024",
+ "a2z-pbs": "1024",
+ "z2a-pbs": "1024",
+ "a2z-color-mode": "0",
+ "z2a-color-mode": "0",
+ "traffic-class": "CS7"
+ },
+ "protocol-list": {
+ "protocols": {
+ "protocol-type": "static",
+ "static-route-list": {
+ "static-routes": [
+ {
+ "id": "0",
+ "dest-ip": ${prop.l3vpn.ac1_peer_ip.value},
+ "dest-mask": ${prop.l3vpn.ac1_peer_ip.mask},
+ "route-type": "direct-route",
+ "out-inf": ${prop.l3vpn.ac1_id},
+ "route-weight": "3",
+ "route-status": "up"
+ }
+ ]
+ }
+ }
+ }
+ },
+ {
+ "id": "1",
+ "ne-id": ${prop.l3vpn.pe2_id},
+ "ltp-id": ${prop.l3vpn.ac2_id},
+ "ip-addr": ${prop.l3vpn.ac2_ip.value},
+ "ip-mask": ${prop.l3vpn.ac2_ip.mask},
+ "access-type": "Sub-interface",
+ "vlan": ${prop.l3vpn.ac1_svlan},
+ "qos": {
+ "belonged-id": ${prop.l3vpn.ac2_id},
+ "tunnel-mode": "pipeline",
+ "cac-mode": "1",
+ "convg-mode": "0",
+ "traffic-adj-mode": "0",
+ "a2z-policing": "1",
+ "z2a-policing": "1",
+ "a2z-cir": "5000",
+ "z2a-cir": "5000",
+ "a2z-pir": "1000000",
+ "z2a-pir": "1000000",
+ "a2z-cbs": "1024",
+ "z2a-cbs": "1024",
+ "a2z-pbs": "1024",
+ "z2a-pbs": "1024",
+ "a2z-color-mode": "0",
+ "z2a-color-mode": "0",
+ "traffic-class": "CS7"
+ },
+ "protocol-list": {
+ "protocols": {
+ "protocol-type": "static",
+ "static-route-list": {
+ "static-routes": [
+ {
+ "id": "0",
+ "dest-ip": ${prop.l3vpn.ac2_peer_ip.value},
+ "dest-mask": ${prop.l3vpn.ac2_peer_ip.mask},
+ "route-type": "direct-route",
+ "out-inf": ${prop.l3vpn.ac2_id},
+ "route-weight": "4",
+ "route-status": "up"
+ }
+ ]
+ }
+ }
+ }
+ }
+ ]
+ },
+ "user-label": ${prop.l3vpn.name},
+ "topo-mode": "any-to-any",
+ "admin-status": "admin-up",
+ "tunnel-create-policy": {
+ "user-label": "tunnel",
+ "tenant-id": "tunnel",
+ "direction": "bidirection",
+ "type": "1",
+ "admin-status": "admin-up",
+ "qos": {
+ "tunnel-mode": "pipeline",
+ "cac-mode": "1",
+ "convg-mode": "0",
+ "traffic-adj-mode": "0",
+ "a2z-policing": "0",
+ "a2z-cir": "500",
+ "a2z-pir": "1000000",
+ "a2z-cbs": "1024",
+ "a2z-pbs": "1024",
+ "a2z-color-mode": "0",
+ "z2a-policing": "0",
+ "z2a-cir": "500",
+ "z2a-pir": "1000000",
+ "z2a-cbs": "1024",
+ "z2a-pbs": "1024",
+ "z2a-color-mode": "0",
+ "traffic-class": "CS7"
+ },
+ "snc-switch": {
+ "layer-rate": "LSP",
+ "linear-protection-type": "path-protection-1-to-1",
+ "linear-protection-protocol": "APS",
+ "switch-mode": "double-end-switch",
+ "revertive-mode": "revertive",
+ "wtr": "60",
+ "hold-off-time": "0",
+ "reroute-revertive-mode": "revertive",
+ "reroute-wtr": "50"
+ },
+ "lsp-oam": {
+ "cc-allow": "true",
+ "cc-exp": "CS7",
+ "cc-interval": "3.3",
+ "lm-mode": "preactive",
+ "dm-mode": "preactive",
+ "meps": {
+ "mep": [
+ { "id": "1" },
+ { "id": "2" }
+ ]
+ }
+ }
+ }
+ }
+}
+
diff --git a/plugins/restapi-call-node/provider/src/main/resources/update-vpe-data-with-apply-group.json b/plugins/restapi-call-node/provider/src/main/resources/update-vpe-data-with-apply-group.json
new file mode 100644
index 000000000..979857521
--- /dev/null
+++ b/plugins/restapi-call-node/provider/src/main/resources/update-vpe-data-with-apply-group.json
@@ -0,0 +1,32 @@
+{
+ "vrf-export-details": [
+ ${repeat:restapi-result.ApplyGroupResponse.ApplyGroupResponseData[0].VrfDetails.VrfExport_length:
+ {
+ "vrf-export": ${restapi-result.ApplyGroupResponse.ApplyGroupResponseData[0].VrfDetails.VrfExport[${1}]}
+ }
+ }
+ ],
+ "vrf-import-details": [
+ ${repeat:restapi-result.ApplyGroupResponse.ApplyGroupResponseData[0].VrfDetails.VrfImport_length:
+ {
+ "vrf-import": ${restapi-result.ApplyGroupResponse.ApplyGroupResponseData[0].VrfDetails.VrfImport[${1}]}
+ }
+ }
+ ],
+ "apply-group-template": [
+ ${repeat:restapi-result.ApplyGroupResponse.ApplyGroupResponseData[0].VrfDetails.ApplyGroup_length:
+ {
+ "apply-group": ${restapi-result.ApplyGroupResponse.ApplyGroupResponseData[0].VrfDetails.ApplyGroup[${1}].ApplyGroup}
+ }
+ }
+ ],
+ "community-list": [
+ ${repeat:restapi-result.ApplyGroupResponse.ApplyGroupResponseData[0].VrfDetails.CommunityList_length:
+ {
+ "member": ${restapi-result.ApplyGroupResponse.ApplyGroupResponseData[0].VrfDetails.CommunityList[${1}].member},
+ "name": ${restapi-result.ApplyGroupResponse.ApplyGroupResponseData[0].VrfDetails.CommunityList[${1}].name}
+ }
+ }
+ ]
+}
+
diff --git a/plugins/restapi-call-node/provider/src/main/resources/vnf-information-update.json b/plugins/restapi-call-node/provider/src/main/resources/vnf-information-update.json
new file mode 100644
index 000000000..d554624c7
--- /dev/null
+++ b/plugins/restapi-call-node/provider/src/main/resources/vnf-information-update.json
@@ -0,0 +1,3 @@
+{
+"generic-vnf-service" :${vnf-service.generic-vnf-service}
+}
diff --git a/plugins/restapi-call-node/provider/src/main/resources/vpn-allocation-request.json b/plugins/restapi-call-node/provider/src/main/resources/vpn-allocation-request.json
new file mode 100644
index 000000000..7a689bd5c
--- /dev/null
+++ b/plugins/restapi-call-node/provider/src/main/resources/vpn-allocation-request.json
@@ -0,0 +1,15 @@
+{
+ "AllocateVpnResourcesRequest": {
+ "message-id": "${service-data.oper-status.modify-timestamp}",
+ "service-instance-id": "${service-data.service-information.service-instance-id}",
+ "vrf-request-type": {
+ "vpn-id": "${service-data.avpn-logicalchannel-information.vpn-id}",
+ "vpn-service": "${service-data.service-information.service-type}",
+ "e2e-vpn-id": "${service-data.avpn-logicalchannel-information.e2e-vpn-id}",
+ "vpe-name": "${service-data.avpn-logicalchannel-information.evc-endpoint-information.vpe-name}",
+ "asn": "${service-data.avpn-logicalchannel-information.carrier-asn}",
+ "route-group-name": "${service-data.avpn-logicalchannel-information.bgp-options.neighbor-address-information.route-group-name}",
+ "hub-or-spoke": "${service-data.avpn-logicalchannel-information.hub-or-spoke}"
+ }
+ }
+}
diff --git a/plugins/restapi-call-node/provider/src/main/resources/vpn-information-update.json b/plugins/restapi-call-node/provider/src/main/resources/vpn-information-update.json
new file mode 100644
index 000000000..3ac16e291
--- /dev/null
+++ b/plugins/restapi-call-node/provider/src/main/resources/vpn-information-update.json
@@ -0,0 +1,3 @@
+{
+"vpn-information" :${vpe-vpn-service.vpn-information}
+}
diff --git a/plugins/restapi-call-node/provider/src/main/resources/vrf-service-configuration-information-template.json b/plugins/restapi-call-node/provider/src/main/resources/vrf-service-configuration-information-template.json
new file mode 100644
index 000000000..c6defb405
--- /dev/null
+++ b/plugins/restapi-call-node/provider/src/main/resources/vrf-service-configuration-information-template.json
@@ -0,0 +1,16 @@
+{
+ "input": {
+
+ "e2e-vpn-key": ${service-data.avpn-logicalchannel-information.e2e-vpn-id},
+ "logical-channel-id": ${service-data.service-information.service-instance-id},
+ "vpe-name": ${service-data.avpn-logicalchannel-information.evc-endpoint-information.vpe-name},
+ "rpc-action": ${tmp.rpc-action},
+
+ "vpn-information": ${vpe-vpn-service.vpn-information},
+ "vrf-details": ${vpe-vpn-service.vpn-information.vrf-details},
+ "vrf-vlan-resources": {
+ "logical-channel-id": ${service-data.service-information.service-instance-id},
+ "logical-channel-status": ${tmp.logical-channel-status}
+ }
+ }
+}
diff --git a/plugins/restapi-call-node/provider/src/main/resources/vrf-update-vlan-status-template.json b/plugins/restapi-call-node/provider/src/main/resources/vrf-update-vlan-status-template.json
new file mode 100644
index 000000000..f6381256f
--- /dev/null
+++ b/plugins/restapi-call-node/provider/src/main/resources/vrf-update-vlan-status-template.json
@@ -0,0 +1,12 @@
+{
+ "input": {
+ "e2e-vpn-key": ${service-data.avpn-logicalchannel-information.e2e-vpn-id},
+ "logical-channel-id": ${service-data.service-information.service-instance-id},
+ "vpe-name": ${service-data.avpn-logicalchannel-information.evc-endpoint-information.vpe-name},
+ "rpc-action": ${tmp.rpc-action},
+ "vrf-vlan-resources": {
+ "logical-channel-id": ${service-data.service-information.service-instance-id},
+ "logical-channel-status": ${tmp.logical-channel-status}
+ }
+ }
+}
diff --git a/plugins/restapi-call-node/provider/src/main/resources/vrf-update.json b/plugins/restapi-call-node/provider/src/main/resources/vrf-update.json
new file mode 100644
index 000000000..cdaef4d82
--- /dev/null
+++ b/plugins/restapi-call-node/provider/src/main/resources/vrf-update.json
@@ -0,0 +1,56 @@
+{
+ "vpn-vame": ${allocate-vpn-resource-notification-input.vpn-data[0].vpn-name},
+ "vpn-id": ${allocate-vpn-resource-notification-input.vpn-data[0].vpn-id},
+ "vrf-details": [
+ ${repeat:allocate-vpn-resource-notification-input.vpn-data[0].vrf-information_length:
+ {
+ "vrf-export-details": [
+ ${repeat:allocate-vpn-resource-notification-input.vpn-data[0].vrf-information[${1}].vrf-export-details_length:
+ {
+ "vrf-export": ${allocate-vpn-resource-notification-input.vpn-data[0].vrf-information[${1}].vrf-export-details[${2}].vrf-export}
+ }
+ }
+ ],
+ "vrf-name": ${allocate-vpn-resource-notification-input.vpn-data[0].vrf-information[${1}].vrf-name},
+ "vpe-name": ${allocate-vpn-resource-notification-input.vpn-data[0].vrf-information[${1}].vpe-name},
+ "vrf-import-details": [
+ ${repeat:allocate-vpn-resource-notification-input.vpn-data[0].vrf-information[${1}].vrf-import-details_length:
+ {
+ "vrf-import": ${allocate-vpn-resource-notification-input.vpn-data[0].vrf-information[${1}].vrf-import-details[${2}].vrf-import}
+ }
+ }
+ ],
+ "apply-group-template": [
+ ${repeat:allocate-vpn-resource-notification-input.vpn-data[0].vrf-information[${1}].apply-group-template_length:
+ {
+ "apply-group": ${allocate-vpn-resource-notification-input.vpn-data[0].vrf-information[${1}].apply-group-template[${2}].apply-group}
+ }
+ }
+ ],
+ "community-list": [
+ ${repeat:allocate-vpn-resource-notification-input.vpn-data[0].vrf-information[${1}].community-list_length:
+ {
+ "member": ${allocate-vpn-resource-notification-input.vpn-data[0].vrf-information[${1}].community-list[${2}].name},
+ "name": ${allocate-vpn-resource-notification-input.vpn-data[0].vrf-information[${1}].community-list[${2}].member}
+ }
+ }
+ ],
+ "router-distinguisher": ${allocate-vpn-resource-notification-input.vpn-data[0].vrf-information[${1}].router-distinguisher}
+ }
+ }
+ ],
+ "spoke-routes": {
+ "route-target": ${allocate-vpn-resource-notification-input.vpn-data[0].spoke-route-target.route-target}
+ },
+
+ "route-target-details": [
+ ${repeat:allocate-vpn-resource-notification-input.vpn-data[0].route-target-details_length:
+ {
+ "route-target": ${allocate-vpn-resource-notification-input.vpn-data[0].route-target-details[${1}].route-target},
+ "route-target-type": ${allocate-vpn-resource-notification-input.vpn-data[0].route-target-details[${1}].route-target-type}
+ }
+ }
+ ],
+
+ "e2e-vpn-key": ${allocate-vpn-resource-notification-input.vpn-data[0].e2e-vpn-id}
+}
diff --git a/plugins/restapi-call-node/provider/src/test/java/org/onap/ccsdk/sli/plugins/restapicall/MockCookieAuthServer.java b/plugins/restapi-call-node/provider/src/test/java/org/onap/ccsdk/sli/plugins/restapicall/MockCookieAuthServer.java
new file mode 100644
index 000000000..7e1e0d505
--- /dev/null
+++ b/plugins/restapi-call-node/provider/src/test/java/org/onap/ccsdk/sli/plugins/restapicall/MockCookieAuthServer.java
@@ -0,0 +1,40 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - CCSDK
+ * ================================================================================
+ * Copyright (C) 2019 Huawei Technologies Co., Ltd. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.ccsdk.sli.plugins.restapicall;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.Produces;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.NewCookie;
+import javax.ws.rs.core.Response;
+
+@Path("get-cookie")
+public class MockCookieAuthServer {
+ @GET
+ @Path("cookie")
+ @Produces(MediaType.APPLICATION_JSON)
+ @Consumes(MediaType.APPLICATION_JSON)
+ public Response getCookie() {
+ return Response.status(200).entity("success").cookie(new NewCookie("cookieResponse", "cookieValueInReturn")).build();
+ }
+}
diff --git a/plugins/restapi-call-node/provider/src/test/java/org/onap/ccsdk/sli/plugins/restapicall/MultipartServerMock.java b/plugins/restapi-call-node/provider/src/test/java/org/onap/ccsdk/sli/plugins/restapicall/MultipartServerMock.java
new file mode 100644
index 000000000..00b5c324d
--- /dev/null
+++ b/plugins/restapi-call-node/provider/src/test/java/org/onap/ccsdk/sli/plugins/restapicall/MultipartServerMock.java
@@ -0,0 +1,44 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - CCSDK
+ * ================================================================================
+ * Copyright (C) 2019 Huawei Technologies Co., Ltd. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.ccsdk.sli.plugins.restapicall;
+
+import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
+import org.glassfish.jersey.media.multipart.FormDataParam;
+
+import javax.ws.rs.Consumes;
+
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+import java.io.InputStream;
+
+@Path("file-upload")
+public class MultipartServerMock {
+
+ @POST
+ @Path("upload")
+ @Consumes(MediaType.MULTIPART_FORM_DATA)
+ public Response uploadFile(
+ @FormDataParam("file") InputStream inputStream,
+ @FormDataParam("file") FormDataContentDisposition fileDetail) {
+ return Response.status(200).entity(fileDetail.getFileName()).build();
+ }
+}
diff --git a/plugins/restapi-call-node/provider/src/test/java/org/onap/ccsdk/sli/plugins/restapicall/TestJsonParser.java b/plugins/restapi-call-node/provider/src/test/java/org/onap/ccsdk/sli/plugins/restapicall/TestJsonParser.java
new file mode 100644
index 000000000..cdffd4576
--- /dev/null
+++ b/plugins/restapi-call-node/provider/src/test/java/org/onap/ccsdk/sli/plugins/restapicall/TestJsonParser.java
@@ -0,0 +1,259 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.restapicall;
+
+import static org.junit.Assert.assertEquals;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.Map;
+import org.junit.Test;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+
+public class TestJsonParser {
+
+ @Test
+ public void test() throws SvcLogicException, IOException {
+ String path = "src/test/resources/test.json";
+ String content = new String(Files.readAllBytes(Paths.get(path)));
+ Map<String, String> mm = JsonParser.convertToProperties(content);
+ assertEquals("Server1", mm.get("equipment-data[0].equipment-id"));
+ assertEquals("1600000", mm.get("equipment-data[0].max-server-speed"));
+ assertEquals("2", mm.get("equipment-data[0].number-primary-servers"));
+ assertEquals("4", mm.get("equipment-data[0].server-count"));
+ assertEquals("Server1", mm.get("equipment-data[0].server-id"));
+ assertEquals("Unknown", mm.get("equipment-data[0].server-model"));
+ assertEquals("Test-Value", mm.get("equipment-data[0].test-node.test-inner-node"));
+ assertEquals("1", mm.get("equipment-data_length"));
+ assertEquals("The provisioned access bandwidth is at or exceeds 50% of the total server capacity.",
+ mm.get("message"));
+ assertEquals("VCE-Cust", mm.get("resource-rule.endpoint-position"));
+ assertEquals("Server", mm.get("resource-rule.equipment-level"));
+ assertEquals("max-server-speed * number-primary-servers", mm.get("resource-rule.hard-limit-expression"));
+ assertEquals("Bandwidth", mm.get("resource-rule.resource-name"));
+ assertEquals("DUMMY", mm.get("resource-rule.service-model"));
+ assertEquals("0.6 * max-server-speed * number-primary-servers", mm.get("resource-rule.soft-limit-expression"));
+ assertEquals("1605000", mm.get("resource-state.last-added"));
+ assertEquals("1920000", mm.get("resource-state.limit-value"));
+ assertEquals("1600000", mm.get("resource-state.threshold-value"));
+ assertEquals("1605000", mm.get("resource-state.used"));
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void testNullString() throws SvcLogicException {
+ JsonParser.convertToProperties(null);
+ }
+
+ @Test
+ public void testJsonStringToCtxToplevelArray() throws Exception {
+ String path = "src/test/resources/ArrayMenu.json";
+ String content = new String(Files.readAllBytes(Paths.get(path)));
+ Map<String, String> mm = JsonParser.convertToProperties(content);
+
+ assertEquals("1000", mm.get("[0].calories"));
+ assertEquals("1", mm.get("[0].id"));
+ assertEquals("plain", mm.get("[0].name"));
+ assertEquals("pizza", mm.get("[0].type"));
+ assertEquals("true", mm.get("[0].vegetarian"));
+ assertEquals("2000", mm.get("[1].calories"));
+ assertEquals("2", mm.get("[1].id"));
+ assertEquals("Tuesday Special", mm.get("[1].name"));
+ assertEquals("1", mm.get("[1].topping[0].id"));
+ assertEquals("onion", mm.get("[1].topping[0].name"));
+ assertEquals("2", mm.get("[1].topping[1].id"));
+ assertEquals("pepperoni", mm.get("[1].topping[1].name"));
+ assertEquals("2", mm.get("[1].topping_length"));
+ assertEquals("pizza", mm.get("[1].type"));
+ assertEquals("false", mm.get("[1].vegetarian"));
+ assertEquals("1500", mm.get("[2].calories"));
+ assertEquals("3", mm.get("[2].id"));
+ assertEquals("House Special", mm.get("[2].name"));
+ assertEquals("3", mm.get("[2].topping[0].id"));
+ assertEquals("basil", mm.get("[2].topping[0].name"));
+ assertEquals("4", mm.get("[2].topping[1].id"));
+ assertEquals("fresh mozzarella", mm.get("[2].topping[1].name"));
+ assertEquals("5", mm.get("[2].topping[2].id"));
+ assertEquals("tomato", mm.get("[2].topping[2].name"));
+ assertEquals("3", mm.get("[2].topping_length"));
+ assertEquals("pizza", mm.get("[2].type"));
+ assertEquals("true", mm.get("[2].vegetarian"));
+ assertEquals("3", mm.get("_length"));
+ }
+
+ @Test
+ public void testJsonStringToCtx() throws Exception {
+ String path = "src/test/resources/ObjectMenu.json";
+ String content = new String(Files.readAllBytes(Paths.get(path)));
+ Map<String, String> mm = JsonParser.convertToProperties(content);
+ assertEquals("1000", mm.get("menu[0].calories"));
+ assertEquals("1", mm.get("menu[0].id"));
+ assertEquals("plain", mm.get("menu[0].name"));
+ assertEquals("pizza", mm.get("menu[0].type"));
+ assertEquals("true", mm.get("menu[0].vegetarian"));
+ assertEquals("2000", mm.get("menu[1].calories"));
+ assertEquals("2", mm.get("menu[1].id"));
+ assertEquals("Tuesday Special", mm.get("menu[1].name"));
+ assertEquals("1", mm.get("menu[1].topping[0].id"));
+ assertEquals("onion", mm.get("menu[1].topping[0].name"));
+ assertEquals("2", mm.get("menu[1].topping[1].id"));
+ assertEquals("pepperoni", mm.get("menu[1].topping[1].name"));
+ assertEquals("2", mm.get("menu[1].topping_length"));
+ assertEquals("pizza", mm.get("menu[1].type"));
+ assertEquals("false", mm.get("menu[1].vegetarian"));
+ assertEquals("1500", mm.get("menu[2].calories"));
+ assertEquals("3", mm.get("menu[2].id"));
+ assertEquals("House Special", mm.get("menu[2].name"));
+ assertEquals("3", mm.get("menu[2].topping[0].id"));
+ assertEquals("basil", mm.get("menu[2].topping[0].name"));
+ assertEquals("4", mm.get("menu[2].topping[1].id"));
+ assertEquals("fresh mozzarella", mm.get("menu[2].topping[1].name"));
+ assertEquals("5", mm.get("menu[2].topping[2].id"));
+ assertEquals("tomato", mm.get("menu[2].topping[2].name"));
+ assertEquals("3", mm.get("menu[2].topping_length"));
+ assertEquals("pizza", mm.get("menu[2].type"));
+ assertEquals("true", mm.get("menu[2].vegetarian"));
+ assertEquals("3", mm.get("menu_length"));
+ }
+
+ @Test
+ public void test1dJsonStringToCtx() throws Exception {
+ String path = "src/test/resources/1dArray.json";
+ String content = new String(Files.readAllBytes(Paths.get(path)));
+ Map<String, String> mm = JsonParser.convertToProperties(content);
+
+ System.out.println(mm);
+ assertEquals("6", mm.get("_length"));
+ assertEquals("apple", mm.get("[0]"));
+ assertEquals("orange", mm.get("[1]"));
+ assertEquals("banana", mm.get("[2]"));
+ assertEquals("squash", mm.get("[3]"));
+ assertEquals("broccoli", mm.get("[4]"));
+ assertEquals("cauliflower", mm.get("[5]"));
+ }
+
+ @Test
+ public void test2dJsonStringToCtx() throws Exception {
+ String path = "src/test/resources/2dArray.json";
+ String content = new String(Files.readAllBytes(Paths.get(path)));
+ Map<String, String> mm = JsonParser.convertToProperties(content);
+
+ // code will crash before these tests
+ assertEquals("apple", mm.get("[0][0]"));
+ assertEquals("orange", mm.get("[0][1]"));
+ assertEquals("banana", mm.get("[0][2]"));
+ assertEquals("3", mm.get("[0]_length"));
+
+ assertEquals("squash", mm.get("[1][0]"));
+ assertEquals("broccoli", mm.get("[1][1]"));
+ assertEquals("cauliflower", mm.get("[1][2]"));
+ assertEquals("3", mm.get("[1]_length"));
+ assertEquals("2", mm.get("_length"));
+ }
+
+ @Test
+ public void test3dJsonStringToCtx() throws Exception {
+ String path = "src/test/resources/3dArray.json";
+ String content = new String(Files.readAllBytes(Paths.get(path)));
+ Map<String, String> mm = JsonParser.convertToProperties(content);
+
+ assertEquals("3", mm.get("_length"));
+ assertEquals("1", mm.get("[0]_length"));
+ assertEquals("3", mm.get("[0][0]_length"));
+
+ assertEquals("2", mm.get("[1]_length"));
+ assertEquals("3", mm.get("[1][0]_length"));
+ assertEquals("3", mm.get("[1][1]_length"));
+
+ assertEquals("3", mm.get("[2]_length"));
+ assertEquals("3", mm.get("[2][0]_length"));
+ assertEquals("3", mm.get("[2][1]_length"));
+ assertEquals("3", mm.get("[2][2]_length"));
+
+ assertEquals("x", mm.get("[0][0][0]"));
+ assertEquals("y", mm.get("[0][0][1]"));
+ assertEquals("z", mm.get("[0][0][2]"));
+
+ assertEquals("abc", mm.get("[1][0][0]"));
+ assertEquals("def", mm.get("[1][0][1]"));
+ assertEquals("xyz", mm.get("[1][0][2]"));
+
+ assertEquals("123", mm.get("[1][1][0]"));
+ assertEquals("456", mm.get("[1][1][1]"));
+ assertEquals("789", mm.get("[1][1][2]"));
+
+ assertEquals("a", mm.get("[2][0][0]"));
+ assertEquals("b", mm.get("[2][0][1]"));
+ assertEquals("c", mm.get("[2][0][2]"));
+
+ assertEquals("d", mm.get("[2][1][0]"));
+ assertEquals("e", mm.get("[2][1][1]"));
+ assertEquals("f", mm.get("[2][1][2]"));
+
+ assertEquals("1", mm.get("[2][2][0]"));
+ assertEquals("2", mm.get("[2][2][1]"));
+ assertEquals("3", mm.get("[2][2][2]"));
+ }
+
+ @Test
+ public void testJsonWidgetStringToCtx() throws Exception {
+ String path = "src/test/resources/Widget.json";
+ String content = new String(Files.readAllBytes(Paths.get(path)));
+ Map<String, String> mm = JsonParser.convertToProperties(content);
+ assertEquals("false", mm.get("widget.debug"));
+ assertEquals("center", mm.get("widget.image.alignment"));
+ assertEquals("150", mm.get("widget.image.hOffset"));
+ assertEquals("moon", mm.get("widget.image.name"));
+ assertEquals("images/moon.png", mm.get("widget.image.src"));
+ assertEquals("150", mm.get("widget.image.vOffset"));
+ assertEquals("center", mm.get("widget.text.alignment"));
+ assertEquals("Click Me", mm.get("widget.text.data"));
+ assertEquals("350", mm.get("widget.text.hOffset"));
+ assertEquals("text1", mm.get("widget.text.name"));
+ assertEquals("21", mm.get("widget.text.size"));
+ assertEquals("bold", mm.get("widget.text.style"));
+ assertEquals("200", mm.get("widget.text.vOffset"));
+ assertEquals("300", mm.get("widget.window.height"));
+ assertEquals("main_window", mm.get("widget.window.name"));
+ assertEquals("ONAP Widget", mm.get("widget.window.title"));
+ assertEquals("200", mm.get("widget.window.width"));
+ }
+
+ @Test
+ public void testEmbeddedEscapedJsonJsonStringToCtx() throws Exception {
+ String path = "src/test/resources/EmbeddedEscapedJson.json";
+ String content = new String(Files.readAllBytes(Paths.get(path)));
+ Map<String, String> mm = JsonParser.convertToProperties(content);
+ assertEquals("escapedJsonObject", mm.get("input.parameters[0].name"));
+ assertEquals("[{\"id\":\"0.2.0.0/16\"},{\"id\":\"ge04::/64\"}]", mm.get("input.parameters[0].value"));
+ assertEquals("Hello/World", mm.get("input.parameters[1].value"));
+ assertEquals("resourceName", mm.get("input.parameters[2].name"));
+ assertEquals("The\t\"Best\"\tName", mm.get("input.parameters[2].value"));
+ assertEquals("3", mm.get("input.parameters_length"));
+
+ // Break the embedded json object into properties
+ mm = JsonParser.convertToProperties(mm.get("input.parameters[0].value"));
+ assertEquals("0.2.0.0/16", mm.get("[0].id"));
+ assertEquals("ge04::/64", mm.get("[1].id"));
+ assertEquals("2", mm.get("_length"));
+ }
+
+}
diff --git a/plugins/restapi-call-node/provider/src/test/java/org/onap/ccsdk/sli/plugins/restapicall/TestRestapiCallNode.java b/plugins/restapi-call-node/provider/src/test/java/org/onap/ccsdk/sli/plugins/restapicall/TestRestapiCallNode.java
new file mode 100755
index 000000000..a993bb946
--- /dev/null
+++ b/plugins/restapi-call-node/provider/src/test/java/org/onap/ccsdk/sli/plugins/restapicall/TestRestapiCallNode.java
@@ -0,0 +1,604 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.restapicall;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.HashMap;
+import java.util.Map;
+import org.codehaus.jettison.json.JSONObject;
+import org.junit.Before;
+import org.junit.Test;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class TestRestapiCallNode {
+
+ @SuppressWarnings("unused")
+ private static final Logger log = LoggerFactory.getLogger(TestRestapiCallNode.class);
+
+ @Before
+ public void init() {
+ System.setProperty("SDNC_CONFIG_DIR", "src/test/resources");
+ }
+
+ @Test
+ public void testDelete() throws SvcLogicException {
+ SvcLogicContext ctx = new SvcLogicContext();
+
+ Map<String, String> p = new HashMap<>();
+ p.put("restapiUrl", "https://echo.getpostman.com/delete");
+ p.put("restapiUser", "user1");
+ p.put("restapiPassword", "pwd1");
+ p.put("httpMethod", "delete");
+ p.put("skipSending", "true");
+
+ RestapiCallNode rcn = new RestapiCallNode();
+ rcn.sendRequest(p, ctx);
+ }
+
+ @Test
+ public void testDeleteWithPayload() throws SvcLogicException {
+ SvcLogicContext ctx = new SvcLogicContext();
+
+ ctx.setAttribute("prop.name", "site1");
+
+ Map<String, String> p = new HashMap<>();
+ p.put("templateFileName", "src/test/resources/sdwan-site.json");
+ p.put("restapiUrl", "https://echo.getpostman.com/delete");
+ p.put("restapiUser", "user1");
+ p.put("restapiPassword", "pwd1");
+ p.put("httpMethod", "delete");
+ p.put("skipSending", "true");
+
+ RestapiCallNode rcn = new RestapiCallNode();
+ rcn.sendRequest(p, ctx);
+ }
+
+ @Test
+ public void testSendFile() throws SvcLogicException {
+ SvcLogicContext ctx = new SvcLogicContext();
+
+ Map<String, String> p = new HashMap<>();
+ p.put("fileName", "src/test/resources/test_file.txt");
+ p.put("url", "https://testurl.test");
+ p.put("user", "user");
+ p.put("password", "*******");
+ p.put("skipSending", "true"); // Set real url, user, password, when testing actual sending
+
+ RestapiCallNode rcn = new RestapiCallNode();
+ rcn.sendFile(p, ctx);
+ }
+
+ @Test
+ public void testJsonTemplate() throws SvcLogicException {
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute("tmp.sdn-circuit-req-row_length", "3");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[0].source-uid", "APIDOC-123");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[0].action", "delete");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[0].request-timestamp", "2016-09-09 16:30:35.0");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[0].request-status", "New");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[0].processing-status", "New");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[0].service-clfi", "testClfi1");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[0].clci", "clci");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[1].source-uid", "APIDOC-123");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[1].action", "delete");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[1].request-timestamp", "2016-09-09 16:30:35.0");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[1].request-status", "New");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[1].processing-status", "New");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[1].service-clfi", "testClfi1");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[1].clci", "clci");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[2].source-uid", "APIDOC-123");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[2].action", "delete");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[2].request-timestamp", "2016-09-09 16:30:35.0");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[2].request-status", "New");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[2].processing-status", "New");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[2].service-clfi", "testClfi1");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[2].clci", "clci");
+
+ Map<String, String> p = new HashMap<>();
+ p.put("templateFileName", "src/test/resources/test-template.json");
+ p.put("restapiUrl", "http://echo.getpostman.com");
+ p.put("restapiUser", "user1");
+ p.put("restapiPassword", "abc123");
+ p.put("format", "json");
+ p.put("httpMethod", "post");
+ p.put("responsePrefix", "response");
+ p.put("skipSending", "true");
+
+ RestapiCallNode rcn = new RestapiCallNode();
+ rcn.sendRequest(p, ctx);
+ }
+
+ @Test
+ public void testInvalidRepeatTimes() throws SvcLogicException {
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute("tmp.sdn-circuit-req-row_length", "a");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[0].source-uid", "APIDOC-123");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[0].action", "delete");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[0].request-timestamp", "2016-09-09 16:30:35.0");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[0].request-status", "New");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[0].processing-status", "New");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[0].service-clfi", "testClfi1");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[0].clci", "clci");
+
+ Map<String, String> p = new HashMap<>();
+ p.put("templateFileName", "src/test/resources/test-template.json");
+ p.put("restapiUrl", "http://echo.getpostman.com");
+ p.put("restapiUser", "user1");
+ p.put("restapiPassword", "abc123");
+ p.put("format", "json");
+ p.put("httpMethod", "post");
+ p.put("responsePrefix", "response");
+ p.put("skipSending", "true");
+
+ RestapiCallNode rcn = new RestapiCallNode();
+ rcn.sendRequest(p, ctx);
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void testInvalidTemplatePath() throws SvcLogicException {
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute("tmp.sdn-circuit-req-row_length", "1");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[0].source-uid", "APIDOC-123");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[0].action", "delete");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[0].request-timestamp", "2016-09-09 16:30:35.0");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[0].request-status", "New");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[0].processing-status", "New");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[0].service-clfi", "testClfi1");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[0].clci", "clci");
+
+ Map<String, String> p = new HashMap<>();
+ p.put("templateFileName", "src/test/resourcess/test-template.json");
+ p.put("restapiUrl", "http://echo.getpostman.com");
+ p.put("restapiUser", "user1");
+ p.put("restapiPassword", "abc123");
+ p.put("format", "json");
+ p.put("httpMethod", "post");
+ p.put("responsePrefix", "response");
+ p.put("skipSending", "true");
+
+ RestapiCallNode rcn = new RestapiCallNode();
+ rcn.sendRequest(p, ctx);
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void testWithoutSkipSending() throws SvcLogicException {
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute("tmp.sdn-circuit-req-row_length", "1");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[0].source-uid", "APIDOC-123");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[0].action", "delete");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[0].request-timestamp", "2016-09-09 16:30:35.0");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[0].request-status", "New");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[0].processing-status", "New");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[0].service-clfi", "testClfi1");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[0].clci", "clci");
+
+ Map<String, String> p = new HashMap<>();
+ p.put("templateFileName", "src/test/resources/test-template.json");
+ p.put("restapiUrl", "http://echo.getpostman.com");
+ p.put("restapiUser", "user1");
+ p.put("restapiPassword", "abc123");
+ p.put("format", "json");
+ p.put("httpMethod", "post");
+ p.put("responsePrefix", "response");
+ p.put("skipSending", "false");
+
+ RestapiCallNode rcn = new RestapiCallNode();
+ rcn.sendRequest(p, ctx);
+ }
+
+
+ @Test(expected = SvcLogicException.class)
+ public void testWithInvalidURI() throws SvcLogicException {
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute("tmp.sdn-circuit-req-row_length", "1");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[0].source-uid", "APIDOC-123");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[0].action", "delete");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[0].request-timestamp", "2016-09-09 16:30:35.0");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[0].request-status", "New");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[0].processing-status", "New");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[0].service-clfi", "testClfi1");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[0].clci", "clci");
+
+ Map<String, String> p = new HashMap<>();
+ p.put("templateFileName", "src/test/resources/test-template.json");
+ p.put("restapiUrl", "http://echo. getpostman.com");
+ p.put("restapiUser", "user1");
+ p.put("restapiPassword", "abc123");
+ p.put("format", "json");
+ p.put("httpMethod", "post");
+ p.put("responsePrefix", "response");
+ p.put("skipSending", "false");
+
+ RestapiCallNode rcn = new RestapiCallNode();
+ rcn.sendRequest(p, ctx);
+ }
+
+ @Test
+ public void testVpnJsonTemplate() throws SvcLogicException {
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute("prop.l3vpn.name", "10000000-0000-0000-0000-000000000001");
+ ctx.setAttribute("prop.l3vpn.topology", "point_to_point");
+
+ Map<String, String> p = new HashMap<>();
+ p.put("templateFileName", "src/test/resources/l3smvpntemplate.json");
+ p.put("restapiUrl", "http://ipwan:18002/restconf/data/huawei-ac-net-l3vpn-svc:l3vpn-svc-cfg/vpn-services");
+ p.put("restapiUser", "admin");
+ p.put("restapiPassword", "admin123");
+ p.put("format", "json");
+ p.put("httpMethod", "post");
+ p.put("responsePrefix", "restapi-result");
+ p.put("skipSending", "true");
+
+ RestapiCallNode rcn = new RestapiCallNode();
+ rcn.sendRequest(p, ctx);
+ }
+
+ @Test
+ public void testSiteJsonTemplate() throws SvcLogicException {
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute("prop.l3vpn.name", "10000000-0000-0000-0000-000000000001");
+ ctx.setAttribute("prop.l3vpn.topology", "point_to_point");
+
+ ctx.setAttribute("prop.l3vpn.site1_name", "10000000-0000-0000-0000-000000000002");
+ ctx.setAttribute("prop.l3vpn.vpn-policy1-id", "10000000-0000-0000-0000-000000000003");
+ ctx.setAttribute("prop.l3vpn.entry1-id", "1");
+ ctx.setAttribute("prop.l3vpn.sna1_name", "10000000-0000-0000-0000-000000000004");
+ ctx.setAttribute("prop.l3vpn.pe1_id", "a8098c1a-f86e-11da-bd1a-00112444be1e");
+ ctx.setAttribute("prop.l3vpn.ac1_id", "a8098c1a-f86e-11da-bd1a-00112444be1b");
+ ctx.setAttribute("prop.l3vpn.ac1-peer-ip", "192.168.1.1");
+ ctx.setAttribute("prop.l3vpn.ac1-ip", "192.168.1.2");
+ ctx.setAttribute("prop.l3vpn.sna1_svlan", "100");
+ ctx.setAttribute("prop.l3vpn.ac1_protocol", "static");
+ ctx.setAttribute("prop.l3vpn.sna1-route.ip-prefix", "192.168.1.1/24");
+ ctx.setAttribute("prop.l3vpn.sna1-route.next-hop", "192.168.1.4");
+
+ ctx.setAttribute("prop.l3vpn.site2_name", "10000000-0000-0000-0000-000000000005");
+ ctx.setAttribute("prop.l3vpn.vpn-policy2-id", "10000000-0000-0000-0000-000000000006");
+ ctx.setAttribute("prop.l3vpn.entry2-id", "1");
+ ctx.setAttribute("prop.l3vpn.sna2_name", "10000000-0000-0000-0000-000000000007");
+ ctx.setAttribute("prop.l3vpn.pe2_id", "a8098c1a-f86e-11da-bd1a-00112444be1a");
+ ctx.setAttribute("prop.l3vpn.ac2_id", "a8098c1a-f86e-11da-bd1a-00112444be1c");
+ ctx.setAttribute("prop.l3vpn.ac2-peer-ip", "192.168.1.6");
+ ctx.setAttribute("prop.l3vpn.ac2-ip", "192.168.1.5");
+ ctx.setAttribute("prop.l3vpn.sna2_svlan", "200");
+ ctx.setAttribute("prop.l3vpn.ac2_protocol", "bgp");
+ ctx.setAttribute("prop.l3vpn.peer2-ip", "192.168.1.7");
+ ctx.setAttribute("prop.l3vpn.ac2_protocol_bgp_as", "200");
+
+ Map<String, String> p = new HashMap<>();
+ p.put("templateFileName", "src/test/resources/l3smsitetemplate.json");
+ p.put("restapiUrl", "http://ipwan:18002/restconf/data/huawei-ac-net-l3vpn-svc:l3vpn-svc-cfg/sites");
+ p.put("restapiUser", "admin");
+ p.put("restapiPassword", "admin123");
+ p.put("format", "json");
+ p.put("httpMethod", "post");
+ p.put("responsePrefix", "restapi-result");
+ p.put("skipSending", "true");
+
+ RestapiCallNode rcn = new RestapiCallNode();
+ rcn.sendRequest(p, ctx);
+ }
+
+ @Test
+ public void testVrfJsonTemplate() throws SvcLogicException {
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute("prop.l3vpn.vrf1-id", "10000000-0000-0000-0000-000000000007");
+ ctx.setAttribute("prop.l3vpn.vpn-policy1-id", "10000000-0000-0000-0000-000000000003");
+ ctx.setAttribute("prop.l3vpn.pe1_id", "a8098c1a-f86e-11da-bd1a-00112444be1e");
+ ctx.setAttribute("prop.l3vpn.vrf2-id", "10000000-0000-0000-0000-000000000009");
+ ctx.setAttribute("prop.l3vpn.vpn-policy2-id", "10000000-0000-0000-0000-000000000006");
+ ctx.setAttribute("prop.l3vpn.pe2_id", "a8098c1a-f86e-11da-bd1a-00112444be1a");
+
+ Map<String, String> p = new HashMap<>();
+ p.put("templateFileName", "src/test/resources/l3smvrftemplate.json");
+ p.put("restapiUrl", "http://ipwan:18002/restconf/data/huawei-ac-net-l3vpn-svc:l3vpn-svc-cfg/vrf-attributes");
+ p.put("restapiUser", "admin");
+ p.put("restapiPassword", "admin123");
+ p.put("format", "json");
+ p.put("httpMethod", "post");
+ p.put("responsePrefix", "restapi-result");
+ p.put("skipSending", "true");
+
+ RestapiCallNode rcn = new RestapiCallNode();
+ rcn.sendRequest(p, ctx);
+ }
+
+ @Test
+ public void testDeleteVpnJsonTemplate() throws SvcLogicException {
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute("prop.l3vpn.name", "10000000-0000-0000-0000-000000000001");
+ ctx.setAttribute("prop.l3vpn.topology", "point_to_point");
+
+ Map<String, String> p = new HashMap<>();
+ //p.put("templateFileName", "src/test/resources/l3smvpntemplate.json");
+ p.put("restapiUrl", "http://ipwan:18002/restconf/data/huawei-ac-net-l3vpn-svc:l3vpn-svc-cfg/vpn-services"
+ + "/vpnservice=10000000-0000-0000-0000-000000000001");
+ p.put("restapiUser", "admin");
+ p.put("restapiPassword", "admin123");
+ p.put("format", "json");
+ p.put("httpMethod", "delete");
+ p.put("responsePrefix", "restapi-result");
+ p.put("skipSending", "true");
+
+ RestapiCallNode rcn = new RestapiCallNode();
+ rcn.sendRequest(p, ctx);
+ }
+
+ @Test
+ public void testL2DciTemplate() throws SvcLogicException {
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute("prop.dci-connects.id", "Id1");
+ ctx.setAttribute("prop.dci-connects.name", "Name1");
+ ctx.setAttribute("prop.dci-connects.local_networks[0]", "NetId1");
+ ctx.setAttribute("prop.dci-connects.local_networks[1]", "NetId2");
+ ctx.setAttribute("prop.dci-connects.evpn_irts[0]", "100:1");
+ ctx.setAttribute("prop.dci-connects.evpn_erts[0]", "100:2");
+ ctx.setAttribute("prop.dci-connects.evpn_irts[1]", "200:1");
+ ctx.setAttribute("prop.dci-connects.evpn_erts[1]", "200:2");
+ ctx.setAttribute("prop.dci-connects.vni", "1");
+
+ Map<String, String> p = new HashMap<>();
+ p.put("templateFileName", "src/test/resources/l2-dci-connects-template.json");
+ p.put("restapiUrl", "http://echo.getpostman.com");
+ p.put("restapiUser", "user1");
+ p.put("restapiPassword", "abc123");
+ p.put("format", "json");
+ p.put("httpMethod", "post");
+ p.put("responsePrefix", "response");
+ p.put("skipSending", "true");
+
+ RestapiCallNode rcn = new RestapiCallNode();
+ rcn.sendRequest(p, ctx);
+ }
+
+ @Test
+ public void testL3DciTemplate() throws SvcLogicException {
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute("prop.dci-connects.id", "Id1");
+ ctx.setAttribute("prop.dci-connects.name", "Name1");
+ ctx.setAttribute("prop.dci-connects.local_networks_length", "2");
+ ctx.setAttribute("prop.dci-connects.local_networks[0]", "NetId1");
+ ctx.setAttribute("prop.dci-connects.local_networks[1]", "NetId2");
+ ctx.setAttribute("prop.dci-connects.evpn_irts[0]", "100:1");
+ ctx.setAttribute("prop.dci-connects.evpn_erts[0]", "100:2");
+ ctx.setAttribute("prop.dci-connects.evpn_irts[1]", "200:1");
+ ctx.setAttribute("prop.dci-connects.evpn_erts[1]", "200:2");
+ ctx.setAttribute("prop.dci-connects.vni", "1");
+
+ Map<String, String> p = new HashMap<>();
+ p.put("templateFileName", "src/test/resources/l3-dci-connects-template.json");
+ p.put("restapiUrl", "http://echo.getpostman.com");
+ p.put("restapiUser", "user1");
+ p.put("restapiPassword", "abc123");
+ p.put("format", "json");
+ p.put("httpMethod", "post");
+ p.put("responsePrefix", "response");
+ p.put("skipSending", "true");
+
+ RestapiCallNode rcn = new RestapiCallNode();
+ rcn.sendRequest(p, ctx);
+
+ }
+
+ @Test
+ public void testControllerTokenTemplate() throws SvcLogicException {
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute("prop.sdncRestApi.thirdpartySdnc.user", "admin");
+ ctx.setAttribute("prop.sdncRestApi.thirdpartySdnc.password", "admin123");
+
+ Map<String, String> p = new HashMap<>();
+ p.put("templateFileName", "src/test/resources/actokentemplate.json");
+ p.put("restapiUrl", "https://ipwan:18002/controller/v2/tokens");
+ p.put("format", "json");
+ p.put("httpMethod", "post");
+ p.put("responsePrefix", "restapi-result");
+ p.put("skipSending", "true");
+
+ RestapiCallNode rcn = new RestapiCallNode();
+ rcn.sendRequest(p, ctx);
+ }
+
+
+ @Test
+ public void testDeleteNoneAsContentType() throws SvcLogicException {
+ SvcLogicContext ctx = new SvcLogicContext();
+
+ Map<String, String> p = new HashMap<>();
+ p.put("restapiUrl", "https://echo.getpostman.com/delete");
+ p.put("restapiUser", "user1");
+ p.put("restapiPassword", "pwd1");
+ p.put("httpMethod", "delete");
+ p.put("format", "none");
+ p.put("skipSending", "true");
+
+ RestapiCallNode rcn = new RestapiCallNode();
+ rcn.sendRequest(p, ctx);
+ }
+
+ @Test
+ public void testPostNoneAsContentType() throws SvcLogicException {
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute("prop.l3vpn.name", "10000000-0000-0000-0000-000000000001");
+ ctx.setAttribute("prop.l3vpn.topology", "point_to_point");
+
+ Map<String, String> p = new HashMap<>();
+ p.put("templateFileName", "src/test/resources/l3smvpntemplate.json");
+ p.put("restapiUrl", "http://ipwan:18002/restconf/data/huawei-ac-net-l3vpn-svc:l3vpn-svc-cfg/vpn-services");
+ p.put("restapiUser", "admin");
+ p.put("restapiPassword", "admin123");
+ p.put("format", "none");
+ p.put("httpMethod", "post");
+ p.put("responsePrefix", "restapi-result");
+ p.put("skipSending", "true");
+
+ RestapiCallNode rcn = new RestapiCallNode();
+ rcn.sendRequest(p, ctx);
+ }
+ /*
+ * {
+ "partnerOne": {
+ "url": "http://localhost:7001" 4 http://uebsb93kcdc.it.att.com:3904",
+ "test": "/metrics"
+ },
+ "partnerTwo": {
+ "url": "http://localhost:7002",
+ "user": "controller_user",
+ "password": "P@ssword",
+ "test": "/metrics"
+ },
+ "partnerThree": {
+ "url": "http://localhost:7003",
+ "user": "controller_admin"
+ }
+}
+ */
+ @Test
+ public void testPartners() throws Exception{
+ String partnerTwoKey = "partnerTwo";
+ String partnerTwoUsername = "controller_user";
+ String partnerTwoPassword = "P@ssword";
+
+ System.setProperty("SDNC_CONFIG_DIR", "src/test/resources");
+ RestapiCallNode rcn = new RestapiCallNode();
+ assertNull(rcn.partnerStore.get("partnerOne"));
+ PartnerDetails details = rcn.partnerStore.get(partnerTwoKey);
+ assertEquals(partnerTwoUsername,details.username);
+ assertEquals(partnerTwoPassword,details.password);
+ assertNull(rcn.partnerStore.get("partnerThree"));
+
+ //In this scenario the caller expects username, password and url to be picked up from the partners json
+ Map<String, String> paramMap = new HashMap<>();
+ paramMap.put("partner", partnerTwoKey);
+ rcn.handlePartner(paramMap );
+ assertEquals(partnerTwoUsername,paramMap.get(RestapiCallNode.restapiUserKey));
+ assertEquals(partnerTwoPassword,paramMap.get(RestapiCallNode.restapiPasswordKey));
+ assertEquals("http://localhost:7002",paramMap.get(RestapiCallNode.restapiUrlString));
+
+ //In this scenario the caller expects username, password and url to be picked up from the partners json
+ //the provided suffix will be appended to the default url from the partners json
+ paramMap = new HashMap<>();
+ paramMap.put("partner", partnerTwoKey);
+ paramMap.put("restapiUrlSuffix", "/networking/v1/instance/3");
+ rcn.handlePartner(paramMap);
+ Parameters p = new Parameters();
+ RestapiCallNode.getParameters(paramMap, p);
+ assertEquals(partnerTwoUsername,p.restapiUser);
+ assertEquals(partnerTwoPassword,p.restapiPassword);
+ assertEquals("http://localhost:7002/networking/v1/instance/3",p.restapiUrl);
+ }
+
+ @Test
+ public void retryPolicyBean() throws Exception {
+ Integer retries = 3;
+ String first = "http://localhost:7001";
+ String second = "http://localhost:7001";
+
+ RetryPolicy p = new RetryPolicy(new String[] {first,second}, retries);
+ assertEquals(retries,p.getMaximumRetries());
+ assertNotNull(p.getRetryMessage());
+ String next = p.getNextHostName();
+ assertEquals(second,next);
+ assertEquals(1,p.getRetryCount());
+ next = p.getNextHostName();
+ assertEquals(first,next);
+ assertEquals(2,p.getRetryCount());
+ }
+
+ @Test
+ public void testEmbeddedJsonTemplate() throws Exception {
+ SvcLogicContext ctx = new SvcLogicContext();
+ String complexObj = "{\"image_name\":\"Ubuntu 14.04\",\"service-instance-id\":\"1\",\"vnf-model-customization-uuid\":\"2f\",\"vnf-id\":\"3b\"}";
+ ctx.setAttribute("reqId", "1235");
+ ctx.setAttribute("subReqId", "054243");
+ ctx.setAttribute("actionName", "CREATE");
+ ctx.setAttribute("myPrefix", "2016-09-09 16:30:35.0");
+ ctx.setAttribute("complexObj", complexObj);
+ RestapiCallNode rcn = new RestapiCallNode();
+ String request = rcn.buildXmlJsonRequest(ctx, rcn.readFile("src/test/resources/testEmbeddedTemplate.json"), Format.JSON);
+ //This will throw a JSONException and fail the test case if rest api call node doesn't form valid JSON
+ assertNotNull(new JSONObject(request));
+ }
+
+ @Test
+ public void testMultiLineEmbeddedJsonTemplate() throws Exception {
+ SvcLogicContext ctx = new SvcLogicContext();
+ String complexObj = "{\n"
+ + " \"image_name\": \"Ubuntu 14.04\",\n"
+ + " \"service-instance-id\": \"1\",\n"
+ + " \"vnf-model-customization-uuid\": \"2f\",\n"
+ + " \"vnf-id\": \"3b\"\n"
+ + "}";
+ ctx.setAttribute("reqId", "1235");
+ ctx.setAttribute("subReqId", "054243");
+ ctx.setAttribute("actionName", "CREATE");
+ ctx.setAttribute("myPrefix", "2016-09-09 16:30:35.0");
+ ctx.setAttribute("complexObj", complexObj);
+ RestapiCallNode rcn = new RestapiCallNode();
+ String request = rcn.buildXmlJsonRequest(ctx, rcn.readFile("src/test/resources/testMultiLineEmbeddedTemplate.json"), Format.JSON);
+ //This will throw a JSONException and fail the test case if rest api call node doesn't form valid JSON
+ assertNotNull(new JSONObject(request));
+ }
+
+ @Test
+ public void testGetMultipleUrls() throws Exception{
+ String[] urls = RestapiCallNode.getMultipleUrls("http://localhost:8008/rest/restconf/data/abc:def/abc:action=Create,deviceType=Banana,https://localhost:8008/rest/restconf/data/abc:def/abc:action=Create,deviceType=Potato");
+ assertEquals("http://localhost:8008/rest/restconf/data/abc:def/abc:action=Create,deviceType=Banana",urls[0]);
+ assertEquals("https://localhost:8008/rest/restconf/data/abc:def/abc:action=Create,deviceType=Potato",urls[1]);
+
+ urls = RestapiCallNode.getMultipleUrls("https://wiki.onap.org/,http://localhost:7001/,http://wiki.onap.org/");
+ assertEquals("https://wiki.onap.org/",urls[0]);
+ assertEquals("http://localhost:7001/",urls[1]);
+ assertEquals("http://wiki.onap.org/",urls[2]);
+
+ urls = RestapiCallNode.getMultipleUrls("https://wiki.onap.org/test=4,5,6,http://localhost:7001/test=1,2,3,http://wiki.onap.org/test=7,8,9,10");
+ assertEquals("https://wiki.onap.org/test=4,5,6",urls[0]);
+ assertEquals("http://localhost:7001/test=1,2,3",urls[1]);
+ assertEquals("http://wiki.onap.org/test=7,8,9,10",urls[2]);
+
+ urls = RestapiCallNode.getMultipleUrls("https://wiki.onap.org/,https://readthedocs.org/projects/onap/");
+ assertEquals("https://wiki.onap.org/",urls[0]);
+ assertEquals("https://readthedocs.org/projects/onap/",urls[1]);
+ }
+
+ @Test
+ public void testContainsMultipleUrls() throws Exception{
+ assertFalse(RestapiCallNode.containsMultipleUrls("https://wiki.onap.org/"));
+ assertFalse(RestapiCallNode.containsMultipleUrls("http://wiki.onap.org/"));
+ assertFalse(RestapiCallNode.containsMultipleUrls("http://localhost:8008/rest/restconf/data/abc:def/abc:action=Create,deviceType=Banana"));
+ assertFalse(RestapiCallNode.containsMultipleUrls("https://localhost:8008/params=1,2,3,4,5,6"));
+
+ assertTrue(RestapiCallNode.containsMultipleUrls("https://wiki.onap.org/,https://readthedocs.org/projects/onap/"));
+ assertTrue(RestapiCallNode.containsMultipleUrls("http://localhost:7001/,http://localhost:7002"));
+ assertTrue(RestapiCallNode.containsMultipleUrls("http://localhost:8008/rest/restconf/data/abc:def/abc:action=Create,deviceType=Banana,https://localhost:8008/rest/restconf/data/abc:def/abc:action=Create,deviceType=Potato"));
+ assertTrue(RestapiCallNode.containsMultipleUrls("https://wiki.onap.org/,http://localhost:7001/,http://wiki.onap.org/"));
+ assertTrue(RestapiCallNode.containsMultipleUrls("https://wiki.onap.org/test=4,5,6,http://localhost:7001/test=1,2,3,http://wiki.onap.org/test=7,8,9,10"));
+ }
+
+}
diff --git a/plugins/restapi-call-node/provider/src/test/java/org/onap/ccsdk/sli/plugins/restapicall/TestXmlJsonUtil.java b/plugins/restapi-call-node/provider/src/test/java/org/onap/ccsdk/sli/plugins/restapicall/TestXmlJsonUtil.java
new file mode 100644
index 000000000..ac6d3b78b
--- /dev/null
+++ b/plugins/restapi-call-node/provider/src/test/java/org/onap/ccsdk/sli/plugins/restapicall/TestXmlJsonUtil.java
@@ -0,0 +1,321 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.restapicall;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.onap.ccsdk.sli.plugins.restapicall.XmlJsonUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+public class TestXmlJsonUtil {
+
+ private static final Logger log = LoggerFactory.getLogger(TestXmlJsonUtil.class);
+
+ @Test
+ public void test() {
+ Map<String, String> mm = new HashMap<>();
+ mm.put("service-data.vnf-config-parameters-list.vnf-config-parameters[0].vnf-type", "N-SBG");
+ mm.put("service-data.service-information.service-instance-id", "someinstance001");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].dns-server-ip-address", "10.11.12.13");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].escf-domain-name", "hclab.atttest.com");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].snmp-target-v3_length", "2");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].snmp-target-v3[0].snmp-target-v3-id", "1");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].snmp-target-v3[0].snmp-target-ip-address", "127.0.0.1");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].snmp-target-v3[0].snmp-security-level", "NO_AUTH_NO_PRIV");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].snmp-target-v3[1].snmp-target-v3-id", "2");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].snmp-target-v3[1].snmp-target-ip-address", "192.168.1.8");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].snmp-target-v3[1].snmp-security-level", "NO_AUTH_NO_PRIV");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].dns-ip-address-1", "2001:1890:1001:2224::1");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].dns-ip-address-2", "2001:1890:1001:2424::1");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].diameter-rf-realm-name", "uvp.els-an.att.net");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].diameter-rf-peer-ip-address", "192.168.1.66");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].bgf-controller-ip-address", "192.168.1.186");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].bgf-control-link-name", "mg3/69@192.168.1.226");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].rf-interface-nexthop-ip-address", "10.111.108.150");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].rf-mated-pair-ip-address", "10.111.108.146");
+
+ mm.put("service-data.vnf-config-parameters-list.vnf-config-parameters[0].access-net-pcscf_length", "4");
+
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].access-net-pcscf[0].network-name", "UvpbUgnAccess1");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].access-net-pcscf[0].sip-pa-termination-ip-address", "10.111.108.146");
+
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].access-net-pcscf[1].network-name", "MIS");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].access-net-pcscf[1].proactive-transcoding-profile",
+ "trinity-transcodingProfile");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].access-net-pcscf[1].next-hop-ip-address", "10.111.108.158");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].access-net-pcscf[1].subnet-mask-length", "10.111.108.154");
+
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].access-net-pcscf[2].network-name", "AVPN1");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].access-net-pcscf[2].proactive-transcoding-profile",
+ "trinity-transcodingProfile");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].access-net-pcscf[2].next-hop-ip-address", "10.111.108.166");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].access-net-pcscf[2].subnet-mask-length", "10.111.108.162");
+
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].access-net-pcscf[3].network-name", "AVPN1");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].access-net-pcscf[3].proactive-transcoding-profile",
+ "trinity-transcodingProfile");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].access-net-pcscf[3].next-hop-ip-address", "10.129.108.166");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].access-net-pcscf[3].subnet-mask-length", "10.129.108.162");
+
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].core-net-pcscf_length", "1");
+
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].core-net-pcscf[0].network-name", "Core");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].core-net-pcscf[0].next-hop-ip-address", "10.111.108.142");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].core-net-pcscf[0].sip-pa-termination-ip-address", "10.111.108.138");
+
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].mated-pair-fully-qualified-domain-name",
+ "mt1nj01sbg01pyl-mt1nj01sbg02pyl.ar1ga.uvp.els-an.att.net");
+
+ mm.put("service-data.appc-request-header.svc-request-id", "SOMESERVICEREQUEST123451000");
+ mm.put("service-data.vnf-config-information.vnf-host-ip-address", "192.168.13.151");
+ mm.put("service-data.vnf-config-information.vendor", "Netconf");
+
+ mm.put("service-data.vnf-config-information.escape-test",
+ "blah blah \"xxx&nnn<>\\'\"there>blah<&''\"\"123\\\\\\'''blah blah &");
+
+ String ss = XmlJsonUtil.getXml(mm, "service-data.vnf-config-parameters-list");
+ log.info(ss);
+
+ ss = XmlJsonUtil.getXml(mm, "service-data.vnf-config-information");
+ log.info(ss);
+
+ ss = XmlJsonUtil.getJson(mm, "service-data.vnf-config-parameters-list.vnf-config-parameters");
+ log.info(ss);
+
+ ss = XmlJsonUtil.getJson(mm, "service-data.vnf-config-information");
+ log.info(ss);
+
+ ss = XmlJsonUtil.getJson(mm, "service-data.vnf-config-information.vnf-host-ip-address");
+ log.info(ss);
+
+ ss = XmlJsonUtil.getJson(mm, "\"service-data.vnf-config-information.vnf-host-ip-address");
+ log.info(ss);
+ }
+
+ public void testRemoveEmptyStructJson1() {
+ String xmlin = "{\n" +
+ " \"policyName\" : \"default-domain.ECOM_Tenant_DND.ECOM_Tenant_DND_mtn6_HngwOamNetVto." +
+ "HNGWOAMNETVTO.OAM_landing-network-role_policy_05\",\n" +
+ " \"policyConfigType\": \"MicroService\",\n" +
+ " \"ecompName\": \"SDNC\",\n" +
+ " \"configBody\": \"{\\\"service\\\": \\\"NetworkPolicy\\\"," +
+ "\\\"location\\\": \\\"Search\\\",\\\"uuid\\\": \\\"Search\\\"," +
+ "\\\"policyName\\\": \\\"default-domain.ECOM_Tenant_DND.ECOM_Tenant_DND_mtn6_HngwOamNetVto." +
+ "HNGWOAMNETVTO.OAM_landing-network-role_policy_05\\\"," +
+ "\\\"description\\\": \\\"default-domain.ECOM_Tenant_DND.ECOM_Tenant_DND_mtn6_HngwOamNetVto." +
+ "HNGWOAMNETVTO.OAM_landing-network-role_policy_05\\\",\\\"configName\\\": \\\"Search\\\"," +
+ "\\\"templateVersion\\\": \\\"1607\\\",\\\"version\\\": \\\"1.3.0.1\\\"," +
+ "\\\"priority\\\": \\\"2\\\",\\\"policyScope\\\": \\\"SDNC\\\",\\\"riskType\\\": \\\"low\\\"," +
+ "\\\"riskLevel\\\": \\\"2\\\",\\\"guard\\\": \\\"True\\\",\\\"content\\\":{ " +
+ "\\\"network-policy\\\": { \\\"display_name\\\": \\\"default-domain.ECOM_Tenant_DND." +
+ "ECOM_Tenant_DND_mtn6_HngwOamNetVto.HNGWOAMNETVTO.OAM_landing-network-role_policy_05\\\", " +
+ "\\\"fq_name\\\": [ \\\"default-domain\\\", " +
+ "\\\"ECOM_Tenant_DND\\\", \\\"default-domain." +
+ "ECOM_Tenant_DND.ECOM_Tenant_DND_mtn6_HngwOamNetVto." +
+ "HNGWOAMNETVTO.OAM_landing-network-role_policy_05\\\" ], " +
+ "\\\"id_perms\\\": { \\\"user_visible\\\": true }, " +
+ "\\\"parent_type\\\": \\\"project\\\", \\\"network_policy_entries\\\": { " +
+ "\\\"policy_rule\\\": [ { " +
+ "\\\"action_list\\\": { \\\"apply_service\\\": [ " +
+ "\\\"testfqdn\\\" ], " +
+ "\\\"gateway_name\\\": null, \\\"qos_action\\\": null, " +
+ "\\\"log\\\": false , \\\"mirror_to\\\": null, " +
+ "\\\"simple_action\\\": null }, " +
+ "\\\"ethertype\\\": null, \\\"application\\\": [], " +
+ "\\\"direction\\\": \\\"<>\\\", \\\"dst_addresses\\\": [ " +
+ "{ \\\"network_policy\\\": null, " +
+ "\\\"security_group\\\": null, " +
+ "\\\"subnet\\\": null, \\\"virtual_network\\\": " +
+ "\\\"default-domain:ECOM_Tenant_DND:ECOM_Tenant_DND_int_HngwOamNetVto." +
+ "HNGWOAMNETVTO.OAM_net_10\\\" } ], " +
+ "\\\"dst_ports\\\": [ { " +
+ "\\\"end_port\\\": -1, \\\"start_port\\\": -1 " +
+ "} ], \\\"protocol\\\": \\\"any\\\", " +
+ "\\\"src_addresses\\\": [ { " +
+ "\\\"network_policy\\\": null, " +
+ "\\\"security_group\\\": null, " +
+ "\\\"subnet\\\": null, \\\"virtual_network\\\": " +
+ "\\\"default-domain:ECOM_Tenant_DND:ECOM_Tenant_DND_int_HngwOamNetVto." +
+ "HNGWOAMNETVTO.OAM_net_9\\\" } ], " +
+ "\\\"src_ports\\\": [ { " +
+ "\\\"end_port\\\": -1, " +
+ "\\\"start_port\\\": -1 } ] } " +
+ "] } }}}\"\n" +
+ "}";
+
+ String xmloutexpected = xmlin;
+
+ String xmlout = XmlJsonUtil.removeEmptyStructJson(null, xmlin);
+ log.info(xmlout);
+
+ Assert.assertEquals(xmloutexpected, xmlout);
+ }
+
+ @Test
+ public void testRemoveEmptyStructXml() {
+ String xmlin = "" +
+ "<T1>\n" +
+ " <T2>\n" +
+ " <T3>\n" +
+ " <T4></T4>\n" +
+ " <T5> </T5>\n" +
+ " <T6>\n" +
+ " </T6>\n" +
+ " </T3>\n" +
+ " <T7>blah</T7>\n" +
+ " </T2>\n" +
+ " <T8>\n" +
+ " <T9>\n" +
+ " <T10></T10>\n" +
+ " <T11> </T11>\n" +
+ " <T12>\n" +
+ " </T12>\n" +
+ " </T9>\n" +
+ " <T13>\n" +
+ " <T14></T14>\n" +
+ " <T15> </T15>\n" +
+ " <T16>\n" +
+ " <T17></T17>\n" +
+ " </T16>\n" +
+ " </T13>\n" +
+ " <T17>\n" +
+ " </T17>\n" +
+ " </T8>\n" +
+ " <T18>blah blah</T18>\n" +
+ "</T1>\n";
+
+ String xmloutexpected = "" +
+ "<T1>\n" +
+ " <T2>\n" +
+ " <T7>blah</T7>\n" +
+ " </T2>\n" +
+ " <T18>blah blah</T18>\n" +
+ "</T1>\n";
+
+ String xmlout = XmlJsonUtil.removeEmptyStructXml(xmlin);
+ log.info(xmlout);
+
+ Assert.assertEquals(xmloutexpected, xmlout);
+ }
+
+ @Test
+ public void testRemoveEmptyStructJson() {
+ String xmlin = "{\r\n" +
+ " \"T1\":{\r\n" +
+ " \"T2\":{\r\n" +
+ " \"T3\":[\r\n" +
+ " \r\n" +
+ " ],\r\n" +
+ " \"T4\":{\r\n" +
+ " \"T12\":[\r\n" +
+ " \r\n" +
+ " ],\r\n" +
+ " \"T13\":[ ],\r\n" +
+ " \"T14\":{\r\n" +
+ " \"T15\":{\r\n" +
+ " \r\n" +
+ " },\r\n" +
+ " \"T16\":{\r\n" +
+ " \r\n" +
+ " }\r\n" +
+ " }\r\n" +
+ " },\r\n" +
+ " \"T5\":{\r\n" +
+ " \"T6\":[\r\n" +
+ " \r\n" +
+ " ],\r\n" +
+ " \"T7\":[\r\n" +
+ " \"T8\":{\r\n" +
+ " \r\n" +
+ " },\r\n" +
+ " \"T9\":{ },\r\n" +
+ " \"T10\":\"blah\",\r\n" +
+ " \"T11\":[\r\n" +
+ " \r\n" +
+ " ]\r\n" +
+ " ]\r\n" +
+ " }\r\n" +
+ " }\r\n" +
+ " }\r\n" +
+ "}\r\n" +
+ "";
+
+ String xmloutexpected = "{\r\n" +
+ " \"T1\":{\r\n" +
+ " \"T2\":{\r\n" +
+ " \"T5\":{\r\n" +
+ " \"T7\":[\r\n" +
+ " \"T10\":\"blah\",\r\n" +
+ " ]\r\n" +
+ " }\r\n" +
+ " }\r\n" +
+ " }\r\n" +
+ "}\r\n" +
+ "";
+
+ String xmlout = XmlJsonUtil.removeEmptyStructJson(null, xmlin);
+ log.info(xmlout);
+
+ Assert.assertEquals(xmloutexpected, xmlout);
+ }
+}
diff --git a/plugins/restapi-call-node/provider/src/test/java/org/onap/ccsdk/sli/plugins/restapicall/TestXmlParser.java b/plugins/restapi-call-node/provider/src/test/java/org/onap/ccsdk/sli/plugins/restapicall/TestXmlParser.java
new file mode 100644
index 000000000..76f86abc0
--- /dev/null
+++ b/plugins/restapi-call-node/provider/src/test/java/org/onap/ccsdk/sli/plugins/restapicall/TestXmlParser.java
@@ -0,0 +1,121 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.restapicall;
+
+import static org.junit.Assert.assertEquals;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import org.junit.Test;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+
+public class TestXmlParser {
+
+ @Test
+ public void test() throws Exception {
+ String path = "src/test/resources/test3.xml";
+ String content = new String(Files.readAllBytes(Paths.get(path)));
+ Set<String> listNameList = new HashSet<String>();
+ listNameList.add("project.dependencies.dependency");
+ listNameList.add("project.build.plugins.plugin");
+ listNameList.add("project.build.plugins.plugin.executions.execution");
+ listNameList.add("project.build.pluginManagement.plugins.plugin");
+ listNameList.add("project.build.pluginManagement." +
+ "plugins.plugin.configuration.lifecycleMappingMetadata.pluginExecutions.pluginExecution");
+
+ Map<String, String> mm = XmlParser.convertToProperties(content, listNameList);
+ assertEquals("811182", mm.get("ApplyGroupResponse.ApplyGroupResponseData.VrfDetails.VpnId"));
+ assertEquals("v6", mm.get("ApplyGroupResponse.ApplyGroupResponseData.RoutingApplyGroups.Family"));
+ assertEquals("SET6_BVOIP_IN", mm.get("ApplyGroupResponse.ApplyGroupResponseData.VrfDetails.VrfImport"));
+ assertEquals("AG_MAX_MCASTROUTES",
+ mm.get("ApplyGroupResponse.ApplyGroupResponseData.VrfDetails.ApplyGroup.ApplyGroup"));
+ assertEquals("ICOREPVC-81114561", mm.get("ApplyGroupResponse.ApplyGroupResponseData.ServiceInstanceId"));
+ assertEquals("SET_RESET_LP", mm.get("ApplyGroupResponse.ApplyGroupResponseData.VrfDetails.VrfExport"));
+ assertEquals("21302:811182", mm.get("ApplyGroupResponse.ApplyGroupResponseData.VrfDetails.VrfName"));
+ assertEquals("BGP4_PROTOCOL",
+ mm.get("ApplyGroupResponse.ApplyGroupResponseData.RoutingApplyGroups.RoutingProtocol"));
+ assertEquals("AG6_MAX_PREFIX",
+ mm.get("ApplyGroupResponse.ApplyGroupResponseData.RoutingApplyGroups.ApplyGroupPeer.ApplyGroup"));
+ assertEquals("VPNL811182", mm.get("ApplyGroupResponse.ApplyGroupResponseData.VrfDetails.End2EndVpnKey"));
+ assertEquals("AG6_BFD_BGP_3000",
+ mm.get("ApplyGroupResponse.ApplyGroupResponseData.RoutingApplyGroups.ApplyGroupNeighbour.ApplyGroup"));
+ assertEquals("200", mm.get("ApplyGroupResponse.response-code"));
+ assertEquals("gp6_21302:811182",
+ mm.get("ApplyGroupResponse.ApplyGroupResponseData.RoutingApplyGroups.PeerGroupName"));
+ assertEquals("Y", mm.get("ApplyGroupResponse.ack-final-indicator"));
+ assertEquals("Success", mm.get("ApplyGroupResponse.response-message"));
+ }
+
+ @Test
+ public void testValidLength() throws Exception {
+ String path = "src/test/resources/test3.xml";
+ String content = new String(Files.readAllBytes(Paths.get(path)));
+ Set<String> listNameList = new HashSet<String>();
+ listNameList.add("ApplyGroupResponse.ApplyGroupResponseData.VrfDetails.VrfImport");
+ listNameList.add("ApplyGroupResponse.ApplyGroupResponseData.VrfDetails.VrfExport");
+
+ Map<String, String> mm = XmlParser.convertToProperties(content, listNameList);
+ assertEquals("AG6_BFD_BGP_3000",
+ mm.get("ApplyGroupResponse.ApplyGroupResponseData.RoutingApplyGroups.ApplyGroupNeighbour.ApplyGroup"));
+ assertEquals("AG6_MAX_PREFIX",
+ mm.get("ApplyGroupResponse.ApplyGroupResponseData.RoutingApplyGroups.ApplyGroupPeer.ApplyGroup"));
+ assertEquals("v6", mm.get("ApplyGroupResponse.ApplyGroupResponseData.RoutingApplyGroups.Family"));
+ assertEquals("gp6_21302:811182",
+ mm.get("ApplyGroupResponse.ApplyGroupResponseData.RoutingApplyGroups.PeerGroupName"));
+ assertEquals("BGP4_PROTOCOL",
+ mm.get("ApplyGroupResponse.ApplyGroupResponseData.RoutingApplyGroups.RoutingProtocol"));
+ assertEquals("ICOREPVC-81114561", mm.get("ApplyGroupResponse.ApplyGroupResponseData.ServiceInstanceId"));
+ assertEquals("AG_MAX_MCASTROUTES",
+ mm.get("ApplyGroupResponse.ApplyGroupResponseData.VrfDetails.ApplyGroup.ApplyGroup"));
+ assertEquals("VPNL811182", mm.get("ApplyGroupResponse.ApplyGroupResponseData.VrfDetails.End2EndVpnKey"));
+ assertEquals("811182", mm.get("ApplyGroupResponse.ApplyGroupResponseData.VrfDetails.VpnId"));
+ assertEquals("SET6_DSU", mm.get("ApplyGroupResponse.ApplyGroupResponseData.VrfDetails.VrfExport[0]"));
+ assertEquals("SET_DSU", mm.get("ApplyGroupResponse.ApplyGroupResponseData.VrfDetails.VrfExport[1]"));
+ assertEquals("SET6_MANAGED", mm.get("ApplyGroupResponse.ApplyGroupResponseData.VrfDetails.VrfExport[2]"));
+ assertEquals("SET_MANAGED", mm.get("ApplyGroupResponse.ApplyGroupResponseData.VrfDetails.VrfExport[3]"));
+ assertEquals("SET_LOVRF_COMMUNITY",
+ mm.get("ApplyGroupResponse.ApplyGroupResponseData.VrfDetails.VrfExport[4]"));
+ assertEquals("SET_RESET_LP", mm.get("ApplyGroupResponse.ApplyGroupResponseData.VrfDetails.VrfExport[5]"));
+ assertEquals("6", mm.get("ApplyGroupResponse.ApplyGroupResponseData.VrfDetails.VrfExport_length"));
+ assertEquals("SET_BVOIP_IN", mm.get("ApplyGroupResponse.ApplyGroupResponseData.VrfDetails.VrfImport[0]"));
+ assertEquals("SET6_BVOIP_IN", mm.get("ApplyGroupResponse.ApplyGroupResponseData.VrfDetails.VrfImport[1]"));
+ assertEquals("2", mm.get("ApplyGroupResponse.ApplyGroupResponseData.VrfDetails.VrfImport_length"));
+ assertEquals("21302:811182", mm.get("ApplyGroupResponse.ApplyGroupResponseData.VrfDetails.VrfName"));
+ assertEquals("Y", mm.get("ApplyGroupResponse.ack-final-indicator"));
+ assertEquals("200", mm.get("ApplyGroupResponse.response-code"));
+ assertEquals("Success", mm.get("ApplyGroupResponse.response-message"));
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void testInvalidLength() throws Exception {
+ String path = "src/test/resources/invalidlength.xml";
+ String content = new String(Files.readAllBytes(Paths.get(path)));
+ Set<String> listNameList = new HashSet<String>();
+ listNameList.add("ApplyGroupResponse.ApplyGroupResponseData.VrfDetails.VrfImport");
+ listNameList.add("ApplyGroupResponse.ApplyGroupResponseData.VrfDetails.VrfExport");
+ XmlParser.convertToProperties(content, listNameList); // throws an exception because the length in the xml is
+ // not a valid number
+ }
+
+}
diff --git a/plugins/restapi-call-node/provider/src/test/org/onap/ccsdk/sli/plugins/restapicall/TestRestapiCallNode.java b/plugins/restapi-call-node/provider/src/test/org/onap/ccsdk/sli/plugins/restapicall/TestRestapiCallNode.java
new file mode 100755
index 000000000..a130d4390
--- /dev/null
+++ b/plugins/restapi-call-node/provider/src/test/org/onap/ccsdk/sli/plugins/restapicall/TestRestapiCallNode.java
@@ -0,0 +1,531 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.restapicall;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import java.util.HashMap;
+import java.util.Map;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.contrib.java.lang.system.EnvironmentVariables;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.plugins.restapicall.RestapiCallNode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class TestRestapiCallNode {
+
+ @SuppressWarnings("unused")
+ private static final Logger log = LoggerFactory.getLogger(TestRestapiCallNode.class);
+ @Rule
+ public EnvironmentVariables environmentVariables = new EnvironmentVariables();
+
+
+
+ @Test
+ public void testDelete() throws SvcLogicException {
+ SvcLogicContext ctx = new SvcLogicContext();
+
+ Map<String, String> p = new HashMap<>();
+ p.put("restapiUrl", "https://echo.getpostman.com/delete");
+ p.put("restapiUser", "user1");
+ p.put("restapiPassword", "pwd1");
+ p.put("httpMethod", "delete");
+ p.put("skipSending", "true");
+
+ RestapiCallNode rcn = new RestapiCallNode();
+ rcn.sendRequest(p, ctx);
+ }
+
+ @Test
+ public void testDeleteWithPayload() throws SvcLogicException {
+ SvcLogicContext ctx = new SvcLogicContext();
+
+ ctx.setAttribute("prop.name", "site1");
+
+ Map<String, String> p = new HashMap<>();
+ p.put("templateFileName", "src/test/resources/sdwan-site.json");
+ p.put("restapiUrl", "https://echo.getpostman.com/delete");
+ p.put("restapiUser", "user1");
+ p.put("restapiPassword", "pwd1");
+ p.put("httpMethod", "delete");
+ p.put("skipSending", "true");
+
+ RestapiCallNode rcn = new RestapiCallNode();
+ rcn.sendRequest(p, ctx);
+ }
+
+ @Test
+ public void testJsonTemplate() throws SvcLogicException {
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute("tmp.sdn-circuit-req-row_length", "3");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[0].source-uid", "APIDOC-123");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[0].action", "delete");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[0].request-timestamp", "2016-09-09 16:30:35.0");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[0].request-status", "New");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[0].processing-status", "New");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[0].service-clfi", "testClfi1");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[0].clci", "clci");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[1].source-uid", "APIDOC-123");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[1].action", "delete");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[1].request-timestamp", "2016-09-09 16:30:35.0");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[1].request-status", "New");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[1].processing-status", "New");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[1].service-clfi", "testClfi1");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[1].clci", "clci");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[2].source-uid", "APIDOC-123");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[2].action", "delete");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[2].request-timestamp", "2016-09-09 16:30:35.0");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[2].request-status", "New");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[2].processing-status", "New");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[2].service-clfi", "testClfi1");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[2].clci", "clci");
+
+ Map<String, String> p = new HashMap<>();
+ p.put("templateFileName", "src/test/resources/test-template.json");
+ p.put("restapiUrl", "http://echo.getpostman.com");
+ p.put("restapiUser", "user1");
+ p.put("restapiPassword", "abc123");
+ p.put("format", "json");
+ p.put("httpMethod", "post");
+ p.put("responsePrefix", "response");
+ p.put("skipSending", "true");
+
+ RestapiCallNode rcn = new RestapiCallNode();
+ rcn.sendRequest(p, ctx);
+ }
+
+ @Test
+ public void testInvalidRepeatTimes() throws SvcLogicException {
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute("tmp.sdn-circuit-req-row_length", "a");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[0].source-uid", "APIDOC-123");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[0].action", "delete");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[0].request-timestamp", "2016-09-09 16:30:35.0");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[0].request-status", "New");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[0].processing-status", "New");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[0].service-clfi", "testClfi1");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[0].clci", "clci");
+
+ Map<String, String> p = new HashMap<>();
+ p.put("templateFileName", "src/test/resources/test-template.json");
+ p.put("restapiUrl", "http://echo.getpostman.com");
+ p.put("restapiUser", "user1");
+ p.put("restapiPassword", "abc123");
+ p.put("format", "json");
+ p.put("httpMethod", "post");
+ p.put("responsePrefix", "response");
+ p.put("skipSending", "true");
+
+ RestapiCallNode rcn = new RestapiCallNode();
+ rcn.sendRequest(p, ctx);
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void testInvalidTemplatePath() throws SvcLogicException {
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute("tmp.sdn-circuit-req-row_length", "1");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[0].source-uid", "APIDOC-123");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[0].action", "delete");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[0].request-timestamp", "2016-09-09 16:30:35.0");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[0].request-status", "New");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[0].processing-status", "New");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[0].service-clfi", "testClfi1");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[0].clci", "clci");
+
+ Map<String, String> p = new HashMap<>();
+ p.put("templateFileName", "src/test/resourcess/test-template.json");
+ p.put("restapiUrl", "http://echo.getpostman.com");
+ p.put("restapiUser", "user1");
+ p.put("restapiPassword", "abc123");
+ p.put("format", "json");
+ p.put("httpMethod", "post");
+ p.put("responsePrefix", "response");
+ p.put("skipSending", "true");
+
+ RestapiCallNode rcn = new RestapiCallNode();
+ rcn.sendRequest(p, ctx);
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void testWithoutSkipSending() throws SvcLogicException {
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute("tmp.sdn-circuit-req-row_length", "1");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[0].source-uid", "APIDOC-123");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[0].action", "delete");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[0].request-timestamp", "2016-09-09 16:30:35.0");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[0].request-status", "New");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[0].processing-status", "New");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[0].service-clfi", "testClfi1");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[0].clci", "clci");
+
+ Map<String, String> p = new HashMap<>();
+ p.put("templateFileName", "src/test/resources/test-template.json");
+ p.put("restapiUrl", "http://echo.getpostman.com");
+ p.put("restapiUser", "user1");
+ p.put("restapiPassword", "abc123");
+ p.put("format", "json");
+ p.put("httpMethod", "post");
+ p.put("responsePrefix", "response");
+ p.put("skipSending", "false");
+
+ RestapiCallNode rcn = new RestapiCallNode();
+ rcn.sendRequest(p, ctx);
+ }
+
+
+ @Test(expected = SvcLogicException.class)
+ public void testWithInvalidURI() throws SvcLogicException {
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute("tmp.sdn-circuit-req-row_length", "1");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[0].source-uid", "APIDOC-123");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[0].action", "delete");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[0].request-timestamp", "2016-09-09 16:30:35.0");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[0].request-status", "New");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[0].processing-status", "New");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[0].service-clfi", "testClfi1");
+ ctx.setAttribute("tmp.sdn-circuit-req-row[0].clci", "clci");
+
+ Map<String, String> p = new HashMap<>();
+ p.put("templateFileName", "src/test/resources/test-template.json");
+ p.put("restapiUrl", "http://echo. getpostman.com");
+ p.put("restapiUser", "user1");
+ p.put("restapiPassword", "abc123");
+ p.put("format", "json");
+ p.put("httpMethod", "post");
+ p.put("responsePrefix", "response");
+ p.put("skipSending", "false");
+
+ RestapiCallNode rcn = new RestapiCallNode();
+ rcn.sendRequest(p, ctx);
+ }
+
+ @Test
+ public void testVpnJsonTemplate() throws SvcLogicException {
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute("prop.l3vpn.name", "10000000-0000-0000-0000-000000000001");
+ ctx.setAttribute("prop.l3vpn.topology", "point_to_point");
+
+ Map<String, String> p = new HashMap<>();
+ p.put("templateFileName", "src/test/resources/l3smvpntemplate.json");
+ p.put("restapiUrl", "http://ipwan:18002/restconf/data/huawei-ac-net-l3vpn-svc:l3vpn-svc-cfg/vpn-services");
+ p.put("restapiUser", "admin");
+ p.put("restapiPassword", "admin123");
+ p.put("format", "json");
+ p.put("httpMethod", "post");
+ p.put("responsePrefix", "restapi-result");
+ p.put("skipSending", "true");
+
+ RestapiCallNode rcn = new RestapiCallNode();
+ rcn.sendRequest(p, ctx);
+ }
+
+ @Test
+ public void testSiteJsonTemplate() throws SvcLogicException {
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute("prop.l3vpn.name", "10000000-0000-0000-0000-000000000001");
+ ctx.setAttribute("prop.l3vpn.topology", "point_to_point");
+
+ ctx.setAttribute("prop.l3vpn.site1_name", "10000000-0000-0000-0000-000000000002");
+ ctx.setAttribute("prop.l3vpn.vpn-policy1-id", "10000000-0000-0000-0000-000000000003");
+ ctx.setAttribute("prop.l3vpn.entry1-id", "1");
+ ctx.setAttribute("prop.l3vpn.sna1_name", "10000000-0000-0000-0000-000000000004");
+ ctx.setAttribute("prop.l3vpn.pe1_id", "a8098c1a-f86e-11da-bd1a-00112444be1e");
+ ctx.setAttribute("prop.l3vpn.ac1_id", "a8098c1a-f86e-11da-bd1a-00112444be1b");
+ ctx.setAttribute("prop.l3vpn.ac1-peer-ip", "192.168.1.1");
+ ctx.setAttribute("prop.l3vpn.ac1-ip", "192.168.1.2");
+ ctx.setAttribute("prop.l3vpn.sna1_svlan", "100");
+ ctx.setAttribute("prop.l3vpn.ac1_protocol", "static");
+ ctx.setAttribute("prop.l3vpn.sna1-route.ip-prefix", "192.168.1.1/24");
+ ctx.setAttribute("prop.l3vpn.sna1-route.next-hop", "192.168.1.4");
+
+ ctx.setAttribute("prop.l3vpn.site2_name", "10000000-0000-0000-0000-000000000005");
+ ctx.setAttribute("prop.l3vpn.vpn-policy2-id", "10000000-0000-0000-0000-000000000006");
+ ctx.setAttribute("prop.l3vpn.entry2-id", "1");
+ ctx.setAttribute("prop.l3vpn.sna2_name", "10000000-0000-0000-0000-000000000007");
+ ctx.setAttribute("prop.l3vpn.pe2_id", "a8098c1a-f86e-11da-bd1a-00112444be1a");
+ ctx.setAttribute("prop.l3vpn.ac2_id", "a8098c1a-f86e-11da-bd1a-00112444be1c");
+ ctx.setAttribute("prop.l3vpn.ac2-peer-ip", "192.168.1.6");
+ ctx.setAttribute("prop.l3vpn.ac2-ip", "192.168.1.5");
+ ctx.setAttribute("prop.l3vpn.sna2_svlan", "200");
+ ctx.setAttribute("prop.l3vpn.ac2_protocol", "bgp");
+ ctx.setAttribute("prop.l3vpn.peer2-ip", "192.168.1.7");
+ ctx.setAttribute("prop.l3vpn.ac2_protocol_bgp_as", "200");
+
+ Map<String, String> p = new HashMap<>();
+ p.put("templateFileName", "src/test/resources/l3smsitetemplate.json");
+ p.put("restapiUrl", "http://ipwan:18002/restconf/data/huawei-ac-net-l3vpn-svc:l3vpn-svc-cfg/sites");
+ p.put("restapiUser", "admin");
+ p.put("restapiPassword", "admin123");
+ p.put("format", "json");
+ p.put("httpMethod", "post");
+ p.put("responsePrefix", "restapi-result");
+ p.put("skipSending", "true");
+
+ RestapiCallNode rcn = new RestapiCallNode();
+ rcn.sendRequest(p, ctx);
+ }
+
+ @Test
+ public void testVrfJsonTemplate() throws SvcLogicException {
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute("prop.l3vpn.vrf1-id", "10000000-0000-0000-0000-000000000007");
+ ctx.setAttribute("prop.l3vpn.vpn-policy1-id", "10000000-0000-0000-0000-000000000003");
+ ctx.setAttribute("prop.l3vpn.pe1_id", "a8098c1a-f86e-11da-bd1a-00112444be1e");
+ ctx.setAttribute("prop.l3vpn.vrf2-id", "10000000-0000-0000-0000-000000000009");
+ ctx.setAttribute("prop.l3vpn.vpn-policy2-id", "10000000-0000-0000-0000-000000000006");
+ ctx.setAttribute("prop.l3vpn.pe2_id", "a8098c1a-f86e-11da-bd1a-00112444be1a");
+
+ Map<String, String> p = new HashMap<>();
+ p.put("templateFileName", "src/test/resources/l3smvrftemplate.json");
+ p.put("restapiUrl", "http://ipwan:18002/restconf/data/huawei-ac-net-l3vpn-svc:l3vpn-svc-cfg/vrf-attributes");
+ p.put("restapiUser", "admin");
+ p.put("restapiPassword", "admin123");
+ p.put("format", "json");
+ p.put("httpMethod", "post");
+ p.put("responsePrefix", "restapi-result");
+ p.put("skipSending", "true");
+
+ RestapiCallNode rcn = new RestapiCallNode();
+ rcn.sendRequest(p, ctx);
+ }
+
+ @Test
+ public void testDeleteVpnJsonTemplate() throws SvcLogicException {
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute("prop.l3vpn.name", "10000000-0000-0000-0000-000000000001");
+ ctx.setAttribute("prop.l3vpn.topology", "point_to_point");
+
+ Map<String, String> p = new HashMap<>();
+ //p.put("templateFileName", "src/test/resources/l3smvpntemplate.json");
+ p.put("restapiUrl", "http://ipwan:18002/restconf/data/huawei-ac-net-l3vpn-svc:l3vpn-svc-cfg/vpn-services"
+ + "/vpnservice=10000000-0000-0000-0000-000000000001");
+ p.put("restapiUser", "admin");
+ p.put("restapiPassword", "admin123");
+ p.put("format", "json");
+ p.put("httpMethod", "delete");
+ p.put("responsePrefix", "restapi-result");
+ p.put("skipSending", "true");
+
+ RestapiCallNode rcn = new RestapiCallNode();
+ rcn.sendRequest(p, ctx);
+ }
+
+ @Test
+ public void testL2DciTemplate() throws SvcLogicException {
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute("prop.dci-connects.id", "Id1");
+ ctx.setAttribute("prop.dci-connects.name", "Name1");
+ ctx.setAttribute("prop.dci-connects.local_networks[0]", "NetId1");
+ ctx.setAttribute("prop.dci-connects.local_networks[1]", "NetId2");
+ ctx.setAttribute("prop.dci-connects.evpn_irts[0]", "100:1");
+ ctx.setAttribute("prop.dci-connects.evpn_erts[0]", "100:2");
+ ctx.setAttribute("prop.dci-connects.evpn_irts[1]", "200:1");
+ ctx.setAttribute("prop.dci-connects.evpn_erts[1]", "200:2");
+ ctx.setAttribute("prop.dci-connects.vni", "1");
+
+ Map<String, String> p = new HashMap<>();
+ p.put("templateFileName", "src/test/resources/l2-dci-connects-template.json");
+ p.put("restapiUrl", "http://echo.getpostman.com");
+ p.put("restapiUser", "user1");
+ p.put("restapiPassword", "abc123");
+ p.put("format", "json");
+ p.put("httpMethod", "post");
+ p.put("responsePrefix", "response");
+ p.put("skipSending", "true");
+
+ RestapiCallNode rcn = new RestapiCallNode();
+ rcn.sendRequest(p, ctx);
+ }
+
+ @Test
+ public void testL3DciTemplate() throws SvcLogicException {
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute("prop.dci-connects.id", "Id1");
+ ctx.setAttribute("prop.dci-connects.name", "Name1");
+ ctx.setAttribute("prop.dci-connects.local_networks_length", "2");
+ ctx.setAttribute("prop.dci-connects.local_networks[0]", "NetId1");
+ ctx.setAttribute("prop.dci-connects.local_networks[1]", "NetId2");
+ ctx.setAttribute("prop.dci-connects.evpn_irts[0]", "100:1");
+ ctx.setAttribute("prop.dci-connects.evpn_erts[0]", "100:2");
+ ctx.setAttribute("prop.dci-connects.evpn_irts[1]", "200:1");
+ ctx.setAttribute("prop.dci-connects.evpn_erts[1]", "200:2");
+ ctx.setAttribute("prop.dci-connects.vni", "1");
+
+ Map<String, String> p = new HashMap<>();
+ p.put("templateFileName", "src/test/resources/l3-dci-connects-template.json");
+ p.put("restapiUrl", "http://echo.getpostman.com");
+ p.put("restapiUser", "user1");
+ p.put("restapiPassword", "abc123");
+ p.put("format", "json");
+ p.put("httpMethod", "post");
+ p.put("responsePrefix", "response");
+ p.put("skipSending", "true");
+
+ RestapiCallNode rcn = new RestapiCallNode();
+ rcn.sendRequest(p, ctx);
+
+ }
+
+ @Test
+ public void testControllerTokenTemplate() throws SvcLogicException {
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute("prop.sdncRestApi.thirdpartySdnc.user", "admin");
+ ctx.setAttribute("prop.sdncRestApi.thirdpartySdnc.password", "admin123");
+
+ Map<String, String> p = new HashMap<>();
+ p.put("templateFileName", "src/test/resources/actokentemplate.json");
+ p.put("restapiUrl", "https://ipwan:18002/controller/v2/tokens");
+ p.put("format", "json");
+ p.put("httpMethod", "post");
+ p.put("responsePrefix", "restapi-result");
+ p.put("skipSending", "true");
+
+ RestapiCallNode rcn = new RestapiCallNode();
+ rcn.sendRequest(p, ctx);
+ }
+
+
+ @Test
+ public void testDeleteNoneAsContentType() throws SvcLogicException {
+ SvcLogicContext ctx = new SvcLogicContext();
+
+ Map<String, String> p = new HashMap<>();
+ p.put("restapiUrl", "https://echo.getpostman.com/delete");
+ p.put("restapiUser", "user1");
+ p.put("restapiPassword", "pwd1");
+ p.put("httpMethod", "delete");
+ p.put("format", "none");
+ p.put("skipSending", "true");
+
+ RestapiCallNode rcn = new RestapiCallNode();
+ rcn.sendRequest(p, ctx);
+ }
+
+ @Test
+ public void testPostNoneAsContentType() throws SvcLogicException {
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute("prop.l3vpn.name", "10000000-0000-0000-0000-000000000001");
+ ctx.setAttribute("prop.l3vpn.topology", "point_to_point");
+
+ Map<String, String> p = new HashMap<>();
+ p.put("templateFileName", "src/test/resources/l3smvpntemplate.json");
+ p.put("restapiUrl", "http://ipwan:18002/restconf/data/huawei-ac-net-l3vpn-svc:l3vpn-svc-cfg/vpn-services");
+ p.put("restapiUser", "admin");
+ p.put("restapiPassword", "admin123");
+ p.put("format", "none");
+ p.put("httpMethod", "post");
+ p.put("responsePrefix", "restapi-result");
+ p.put("skipSending", "true");
+
+ RestapiCallNode rcn = new RestapiCallNode();
+ rcn.sendRequest(p, ctx);
+ }
+ /*
+ * {
+ "partnerOne": {
+ "url": "http://localhost:7001" 4 http://uebsb93kcdc.it.att.com:3904",
+ "test": "/metrics"
+ },
+ "partnerTwo": {
+ "url": "http://localhost:7002",
+ "user": "controller_user",
+ "password": "P@ssword",
+ "test": "/metrics"
+ },
+ "partnerThree": {
+ "url": "http://localhost:7003",
+ "user": "controller_admin"
+ }
+}
+ */
+ @Test
+ public void testPartners() throws Exception{
+
+ environmentVariables.set("deployer_pass", "sdncp-123");
+ assertEquals("sdncp-123", System.getenv("deployer_pass"));
+
+ String partnerTwoKey = "partnerTwo";
+ String partnerTwoUsername = "controller_user";
+ String partnerTwoPassword = "P@ssword";
+
+ System.setProperty("SDNC_CONFIG_DIR", "src/test/resources");
+ RestapiCallNode rcn = new RestapiCallNode();
+ assertNull(rcn.partnerStore.get("partnerOne"));
+ PartnerDetails details = rcn.partnerStore.get(partnerTwoKey);
+ assertEquals(partnerTwoUsername,details.username);
+ assertEquals(partnerTwoPassword,details.password);
+ assertNull(rcn.partnerStore.get("partnerThree"));
+
+ //In this scenario the caller expects username, password and url to be picked up from the partners json
+ Map<String, String> paramMap = new HashMap<String,String>();
+ paramMap.put("partner", partnerTwoKey);
+ rcn.handlePartner(paramMap );
+ assertEquals(partnerTwoUsername,paramMap.get(rcn.restapiUserKey));
+ assertEquals(partnerTwoPassword,paramMap.get(rcn.restapiPasswordKey));
+ assertEquals("http://localhost:7002",paramMap.get(rcn.restapiUrlString));
+
+ //In this scenario the caller expects username, password and url to be picked up from the partners json
+ //the provided suffix will be appended to the default url from the partners json
+ paramMap = new HashMap<String,String>();
+ paramMap.put("partner", partnerTwoKey);
+ paramMap.put("restapiUrlSuffix", "/networking/v1/instance/3");
+ rcn.handlePartner(paramMap);
+ p = new Parameters();
+ RestapiCallNode.getParameters(paramMap, p);
+ assertEquals(partnerTwoUsername,p.restapiUser);
+ assertEquals(partnerTwoPassword,p.restapiPassword);
+ assertEquals("http://localhost:7002/networking/v1/instance/3",p.restapiUrl);
+
+ paramMap = new HashMap<String, String>();
+ paramMap.put("partner","partnerFour" );
+ paramMap.put("httpMethod", "delete");
+ paramMap.put("skipSending", "true");
+ rcn.handlePartner(paramMap);
+ Parameters p = new Parameters();
+ RestapiCallNode.getParameters(paramMap, p);
+ assertEquals(p.restapiPassword, "sdncp-123");
+ assertEquals(p.restapiUser, "m30402@sdncp.att.com");
+ assertEquals(p.restapiUrl, "http://localhost:7004");
+ }
+
+ @Test
+ public void retryPolicyBean() throws Exception {
+ Integer retries = 3;
+ String first = "http://localhost:7001";
+ String second = "http://localhost:7001";
+
+ RetryPolicy p = new RetryPolicy(new String[] {first,second}, retries);
+ assertEquals(retries,p.getMaximumRetries());
+ assertNotNull(p.getRetryMessage());
+ String next = p.getNextHostName();
+ assertEquals(second,next);
+ assertEquals(1,p.getRetryCount());
+ next = p.getNextHostName();
+ assertEquals(first,next);
+ assertEquals(2,p.getRetryCount());
+ }
+}
diff --git a/plugins/restapi-call-node/provider/src/test/resources/1dArray.json b/plugins/restapi-call-node/provider/src/test/resources/1dArray.json
new file mode 100644
index 000000000..208fb70a6
--- /dev/null
+++ b/plugins/restapi-call-node/provider/src/test/resources/1dArray.json
@@ -0,0 +1,8 @@
+[
+ "apple",
+ "orange",
+ "banana",
+ "squash",
+ "broccoli",
+ "cauliflower"
+] \ No newline at end of file
diff --git a/plugins/restapi-call-node/provider/src/test/resources/2dArray.json b/plugins/restapi-call-node/provider/src/test/resources/2dArray.json
new file mode 100644
index 000000000..b473864d8
--- /dev/null
+++ b/plugins/restapi-call-node/provider/src/test/resources/2dArray.json
@@ -0,0 +1,4 @@
+[
+ ["apple", "orange", "banana"],
+ ["squash", "broccoli", "cauliflower"]
+] \ No newline at end of file
diff --git a/plugins/restapi-call-node/provider/src/test/resources/3dArray.json b/plugins/restapi-call-node/provider/src/test/resources/3dArray.json
new file mode 100644
index 000000000..3f3f4fab8
--- /dev/null
+++ b/plugins/restapi-call-node/provider/src/test/resources/3dArray.json
@@ -0,0 +1,5 @@
+[
+ [["x","y","z"]],
+ [["abc","def","xyz"], [123, 456, 789]],
+ [["a","b","c"], ["d","e","f"], ["1","2","3"]]
+] \ No newline at end of file
diff --git a/plugins/restapi-call-node/provider/src/test/resources/ArrayMenu.json b/plugins/restapi-call-node/provider/src/test/resources/ArrayMenu.json
new file mode 100644
index 000000000..b12f16315
--- /dev/null
+++ b/plugins/restapi-call-node/provider/src/test/resources/ArrayMenu.json
@@ -0,0 +1,41 @@
+[{
+ "id": "1",
+ "type": "pizza",
+ "name": "plain",
+ "calories": 1000,
+ "vegetarian": true
+ }, {
+ "id": "2",
+ "type": "pizza",
+ "name": "Tuesday Special",
+ "calories": 2000,
+ "vegetarian": false,
+ "topping":
+ [{
+ "id": "1",
+ "name": "onion"
+ }, {
+ "id": "2",
+ "name": "pepperoni"
+ }
+ ]
+ }, {
+ "id": "3",
+ "type": "pizza",
+ "name": "House Special",
+ "calories": 1500,
+ "vegetarian": true,
+ "topping":
+ [{
+ "id": "3",
+ "name": "basil"
+ }, {
+ "id": "4",
+ "name": "fresh mozzarella"
+ }, {
+ "id": "5",
+ "name": "tomato"
+ }
+ ]
+ }
+]
diff --git a/plugins/restapi-call-node/provider/src/test/resources/EmbeddedEscapedJson.json b/plugins/restapi-call-node/provider/src/test/resources/EmbeddedEscapedJson.json
new file mode 100644
index 000000000..dbb6d8d3a
--- /dev/null
+++ b/plugins/restapi-call-node/provider/src/test/resources/EmbeddedEscapedJson.json
@@ -0,0 +1,16 @@
+{
+ "input": {
+ "parameters":
+ [{
+ "name": "escapedJsonObject",
+ "value": "[{\"id\":\"0.2.0.0\/16\"},{\"id\":\"ge04::\/64\"}]"
+ }, {
+ "name": "password",
+ "value": "Hello\/World"
+ }, {
+ "name": "resourceName",
+ "value": "The\t\"Best\"\tName"
+ }
+ ]
+ }
+} \ No newline at end of file
diff --git a/plugins/restapi-call-node/provider/src/test/resources/EscapedJson.json b/plugins/restapi-call-node/provider/src/test/resources/EscapedJson.json
new file mode 100644
index 000000000..a7719e819
--- /dev/null
+++ b/plugins/restapi-call-node/provider/src/test/resources/EscapedJson.json
@@ -0,0 +1 @@
+{\"widget\":{\"debug\":false,\"window\":{\"title\":\"ONAP Widget\",\"name\":\"main_window\",\"width\":200,\"height\":300},\"image\":{\"src\":\"images\/moon.png\",\"name\":\"moon\",\"hOffset\":150,\"vOffset\":150,\"alignment\":\"center\"},\"text\":{\"data\":\"Click Me\",\"size\":21,\"style\":\"bold\",\"name\":\"text1\",\"hOffset\":350,\"vOffset\":200,\"alignment\":\"center\"}}} \ No newline at end of file
diff --git a/plugins/restapi-call-node/provider/src/test/resources/ObjectMenu.json b/plugins/restapi-call-node/provider/src/test/resources/ObjectMenu.json
new file mode 100644
index 000000000..56f842d48
--- /dev/null
+++ b/plugins/restapi-call-node/provider/src/test/resources/ObjectMenu.json
@@ -0,0 +1,43 @@
+{
+ "menu": [{
+ "id": "1",
+ "type": "pizza",
+ "name": "plain",
+ "calories": 1000,
+ "vegetarian": true
+ }, {
+ "id": "2",
+ "type": "pizza",
+ "name": "Tuesday Special",
+ "calories": 2000,
+ "vegetarian": false,
+ "topping":
+ [{
+ "id": "1",
+ "name": "onion"
+ }, {
+ "id": "2",
+ "name": "pepperoni"
+ }
+ ]
+ }, {
+ "id": "3",
+ "type": "pizza",
+ "name": "House Special",
+ "calories": 1500,
+ "vegetarian": true,
+ "topping":
+ [{
+ "id": "3",
+ "name": "basil"
+ }, {
+ "id": "4",
+ "name": "fresh mozzarella"
+ }, {
+ "id": "5",
+ "name": "tomato"
+ }
+ ]
+ }
+ ]
+}
diff --git a/plugins/restapi-call-node/provider/src/test/resources/Widget.json b/plugins/restapi-call-node/provider/src/test/resources/Widget.json
new file mode 100644
index 000000000..1e25282c2
--- /dev/null
+++ b/plugins/restapi-call-node/provider/src/test/resources/Widget.json
@@ -0,0 +1,27 @@
+{
+ "widget": {
+ "debug": false,
+ "window": {
+ "title": "ONAP Widget",
+ "name": "main_window",
+ "width": 200,
+ "height": 300
+ },
+ "image": {
+ "src": "images/moon.png",
+ "name": "moon",
+ "hOffset": 150,
+ "vOffset": 150,
+ "alignment": "center"
+ },
+ "text": {
+ "data": "Click Me",
+ "size": 21,
+ "style": "bold",
+ "name": "text1",
+ "hOffset": 350,
+ "vOffset": 200,
+ "alignment": "center"
+ }
+ }
+} \ No newline at end of file
diff --git a/plugins/restapi-call-node/provider/src/test/resources/actokentemplate.json b/plugins/restapi-call-node/provider/src/test/resources/actokentemplate.json
new file mode 100644
index 000000000..02e62400f
--- /dev/null
+++ b/plugins/restapi-call-node/provider/src/test/resources/actokentemplate.json
@@ -0,0 +1,4 @@
+{
+ "userName": ${prop.sdncRestApi.thirdpartySdnc.user},
+ "password": ${prop.sdncRestApi.thirdpartySdnc.password}
+}
diff --git a/plugins/restapi-call-node/provider/src/test/resources/invalidlength.xml b/plugins/restapi-call-node/provider/src/test/resources/invalidlength.xml
new file mode 100644
index 000000000..c086d564e
--- /dev/null
+++ b/plugins/restapi-call-node/provider/src/test/resources/invalidlength.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!--
+ ============LICENSE_START=======================================================
+ openECOMP : SDN-C
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property. All rights
+ reserved.
+ ================================================================================
+ 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.
+ ============LICENSE_END=========================================================
+ -->
+
+<ApplyGroupResponse xmlns="http://onap.org/vpn/schema/v1"
+ xmlns:ns2="http://onap.org/prov/vpn/schema/v2">
+ <ApplyGroupResponseData>
+ <ServiceInstanceId>ICOREPVC-81114561</ServiceInstanceId>
+ <VrfDetails>
+ <End2EndVpnKey>VPNL811182</End2EndVpnKey>
+ <VpnId>811182</VpnId>
+ <VrfName>21302:811182</VrfName>
+ <VrfImport>SET_BVOIP_IN</VrfImport>
+ <VrfImport>SET6_BVOIP_IN</VrfImport>
+ <VrfExport_length>a</VrfExport_length>
+ <VrfExport>SET6_DSU</VrfExport>
+ <VrfExport>SET_DSU</VrfExport>
+ <VrfExport>SET6_MANAGED</VrfExport>
+ <VrfExport>SET_MANAGED</VrfExport>
+ <VrfExport>SET_LOVRF_COMMUNITY</VrfExport>
+ <VrfExport>SET_RESET_LP</VrfExport>
+ <ApplyGroup>
+ <ns2:ApplyGroup>AG_MAX_MCASTROUTES</ns2:ApplyGroup>
+ </ApplyGroup>
+ </VrfDetails>
+ </ApplyGroupResponseData>
+ <response-code>200</response-code>
+ <response-message>Success</response-message>
+ <ack-final-indicator>Y</ack-final-indicator>
+</ApplyGroupResponse>
+
diff --git a/plugins/restapi-call-node/provider/src/test/resources/l2-dci-connects-template.json b/plugins/restapi-call-node/provider/src/test/resources/l2-dci-connects-template.json
new file mode 100644
index 000000000..e0896bbaa
--- /dev/null
+++ b/plugins/restapi-call-node/provider/src/test/resources/l2-dci-connects-template.json
@@ -0,0 +1,11 @@
+{
+ "l2-dci-connect": {
+ "id": ${prop.dci-connects.id},
+ "name": ${prop.dci-connects.name},
+ "description": ${prop.dci-connects.description},
+ "network_id": ${prop.dci-connects.local_networks[0]},
+ "evpn_irts": ${prop.dci-connects.evpn_irts},
+ "evpn_erts": ${prop.dci-connects.evpn_erts},
+ "vni": ${prop.dci-connects.vni}
+ }
+}
diff --git a/plugins/restapi-call-node/provider/src/test/resources/l3-dci-connects-template.json b/plugins/restapi-call-node/provider/src/test/resources/l3-dci-connects-template.json
new file mode 100644
index 000000000..41df794fd
--- /dev/null
+++ b/plugins/restapi-call-node/provider/src/test/resources/l3-dci-connects-template.json
@@ -0,0 +1,14 @@
+{
+ "l3-dci-connect": {
+ "id": ${prop.dci-connects.id},
+ "name": ${prop.dci-connects.name},
+ "description": ${prop.dci-connects.description},
+ "router_id": ${prop.dci-connects.router_id},
+ "firewall_enable": false,
+ "local_networks": ${prop.dci-connects.local_networks},
+ "local_network_all": false,
+ "evpn_irts": ${prop.dci-connects.evpn_irts},
+ "evpn_erts": ${prop.dci-connects.evpn_erts},
+ "l3_vni": ${prop.dci-connects.vni}
+ }
+}
diff --git a/plugins/restapi-call-node/provider/src/test/resources/l3smsitetemplate.json b/plugins/restapi-call-node/provider/src/test/resources/l3smsitetemplate.json
new file mode 100644
index 000000000..8f8156698
--- /dev/null
+++ b/plugins/restapi-call-node/provider/src/test/resources/l3smsitetemplate.json
@@ -0,0 +1,162 @@
+{
+ "site":[
+ {
+ "site-id": ${prop.l3vpn.site1_name},
+ "vpn-policies": {
+ "vpn-policy": [
+ {
+ "vpn-policy-id": ${prop.l3vpn.vpn-policy1-id},
+ "entries": [
+ {
+ "id": ${prop.l3vpn.entry1-id},
+ "vpn": {
+ "vpn-id": ${prop.l3vpn.name},
+ "site-role": "huawei-ac-net-l3vpn-svc:any-to-any-role"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ "site-network-accesses": {
+ "site-network-access": [
+ {
+ "site-network-access-id": ${prop.l3vpn.sna1_name},
+ "bearer": {
+ "appointed-access": {
+ "ne-id": ${prop.l3vpn.pe1_id},
+ "ltp-id": ${prop.l3vpn.ac1_id},
+ "vlan": {
+ "type": "huawei-ac-net-l3vpn-svc:vlan-dot1q",
+ "vlan-id": ${prop.l3vpn.sna1_svlan}
+ }
+ }
+ },
+ "ip-connection": {
+ "ipv4": {
+ "address-allocation-type": "huawei-ac-net-l3vpn-svc:static-address",
+ "addresses": {
+ "provider-address": ${prop.l3vpn.ac1-peer-ip},
+ "customer-address": ${prop.l3vpn.ac1-ip},
+ "mask": "24"
+ }
+ }
+ },
+ "service": {
+ "mtu": "1500"
+ },
+ "routing-protocols": {
+ "routing-protocol": [
+ {
+ "type": ${prop.l3vpn.ac1_protocol},
+ "static": {
+ "cascaded-lan-prefixes": [
+ {
+ "ipv4-lan-prefixes": [
+ {
+ "ip-prefix": ${prop.l3vpn.sna1-route.ip-prefix},
+ "next-hop": ${prop.l3vpn.sna1-route.next-hop}
+ }
+ ]
+ }
+ ]
+ }
+ "bgp": {
+ "peers": [
+ {
+ "peer-ip": ${prop.l3vpn.peer1-ip},
+ "remote-as": ${prop.l3vpn.ac1_protocol_bgp_as}
+ }
+ ]
+ }
+ }
+ }
+ ]
+ },
+ "vpn-attachment": {
+ "vpn-policy-id": ${prop.l3vpn.name}
+ }
+ }
+ ]
+ },
+ {
+ "site-id": ${prop.l3vpn.site2_name},
+ "vpn-policies": {
+ "vpn-policy": [
+ {
+ "vpn-policy-id": ${prop.l3vpn.vpn-policy2-id},
+ "entries": [
+ {
+ "id": ${prop.l3vpn.entry2-id},
+ "vpn": {
+ "vpn-id": ${prop.l3vpn.name},
+ "site-role": "huawei-ac-net-l3vpn-svc:any-to-any-role"
+ }
+ }
+ ]
+ }
+ ]
+ },
+ "site-network-accesses": {
+ "site-network-access": [
+ {
+ "site-network-access-id": ${prop.l3vpn.sna2_name},
+ "bearer": {
+ "appointed-access": {
+ "ne-id": ${prop.l3vpn.pe2_id},
+ "ltp-id": ${prop.l3vpn.ac2_id},
+ "vlan": {
+ "type": "huawei-ac-net-l3vpn-svc:vlan-dot1q",
+ "vlan-id": ${prop.l3vpn.sna2_svlan}
+ }
+ }
+ },
+ "ip-connection": {
+ "ipv4": {
+ "address-allocation-type": "huawei-ac-net-l3vpn-svc:static-address",
+ "addresses": {
+ "provider-address": ${prop.l3vpn.ac2-peer-ip},
+ "customer-address": ${prop.l3vpn.ac2-ip},
+ "mask": "24"
+ }
+ }
+ },
+ "service": {
+ "mtu": "1500"
+ },
+ "routing-protocols": {
+ "routing-protocol": [
+ {
+ "type": ${prop.l3vpn.ac2_protocol},
+ "static": {
+ "cascaded-lan-prefixes": [
+ {
+ "ipv4-lan-prefixes": [
+ {
+ "ip-prefix": ${prop.l3vpn.sna2-route.ip-prefix},
+ "next-hop": ${prop.l3vpn.sna2-route.next-hop}
+ }
+ ]
+ }
+ ]
+ }
+ "bgp": {
+ "peers": [
+ {
+ "peer-ip": ${prop.l3vpn.peer2-ip},
+ "remote-as": ${prop.l3vpn.ac2_protocol_bgp_as}
+ }
+ ]
+ }
+ }
+ ]
+ },
+ "vpn-attachment": {
+ "vpn-policy-id": ${prop.l3vpn.name}
+ }
+ }
+ ]
+ }
+ ]
+}
+
diff --git a/plugins/restapi-call-node/provider/src/test/resources/l3smvpntemplate.json b/plugins/restapi-call-node/provider/src/test/resources/l3smvpntemplate.json
new file mode 100644
index 000000000..30f30a24f
--- /dev/null
+++ b/plugins/restapi-call-node/provider/src/test/resources/l3smvpntemplate.json
@@ -0,0 +1,10 @@
+{
+ "vpn-service": [
+ {
+ "vpn-id": ${prop.l3vpn.name},
+ "customer-name": "huawei",
+ "vpn-service-topology": ${prop.l3vpn.topology},
+ "route-exchange-policy": "huawei-ac-net-l3vpn-svc:vpnv4-way"
+ }
+ ]
+}
diff --git a/plugins/restapi-call-node/provider/src/test/resources/l3smvrftemplate.json b/plugins/restapi-call-node/provider/src/test/resources/l3smvrftemplate.json
new file mode 100644
index 000000000..52359a7fd
--- /dev/null
+++ b/plugins/restapi-call-node/provider/src/test/resources/l3smvrftemplate.json
@@ -0,0 +1,14 @@
+{
+ "vrf-attribute": [
+ {
+ "vrf-attribute-id": ${prop.l3vpn.vrf1-id},
+ "ne-id": ${prop.l3vpn.pe1_id},
+ "vpn-policy-id": ${prop.l3vpn.vpn-policy1-id}
+ },
+ {
+ "vrf-attribute-id": ${prop.l3vpn.vrf2-id},
+ "ne-id": ${prop.l3vpn.pe2_id},
+ "vpn-policy-id": ${prop.l3vpn.vpn-policy2-id}
+ }
+ ]
+}
diff --git a/plugins/restapi-call-node/provider/src/test/resources/partners.json b/plugins/restapi-call-node/provider/src/test/resources/partners.json
new file mode 100755
index 000000000..2562d69c0
--- /dev/null
+++ b/plugins/restapi-call-node/provider/src/test/resources/partners.json
@@ -0,0 +1,22 @@
+{
+ "partnerOne": {
+ "url": "http://localhost:7001",
+ "test": "/metrics"
+ },
+ "partnerTwo": {
+ "url": "http://localhost:7002",
+ "user": "controller_user",
+ "password": "P@ssword",
+ "test": "/metrics"
+ },
+ "partnerThree": {
+ "url": "http://localhost:7003",
+ "user": "controller_admin"
+ },
+ "partnerFour": {
+ "url": "http://localhost:7004",
+ "user": "m30402@sdncp.att.com",
+ "password": "${deployer_pass}",
+ "test": "/metrics"
+ }
+}
diff --git a/plugins/restapi-call-node/provider/src/test/resources/sdwan-site.json b/plugins/restapi-call-node/provider/src/test/resources/sdwan-site.json
new file mode 100644
index 000000000..238ec7642
--- /dev/null
+++ b/plugins/restapi-call-node/provider/src/test/resources/sdwan-site.json
@@ -0,0 +1,10 @@
+{
+ "sites": [
+ {
+ "name": ${prop.name},
+ "controlPoints": []
+ }
+ ]
+}
+
+
diff --git a/plugins/restapi-call-node/provider/src/test/resources/sdwan-vpn-topology.json b/plugins/restapi-call-node/provider/src/test/resources/sdwan-vpn-topology.json
new file mode 100644
index 000000000..4260d2fc1
--- /dev/null
+++ b/plugins/restapi-call-node/provider/src/test/resources/sdwan-vpn-topology.json
@@ -0,0 +1,23 @@
+{
+ "vpnId": ${prop.vpn1Id},
+ "areas": [
+ {
+ "name": "area1",
+ "areaType": "leaf",
+ "topologyType": ${prop.topology},
+ "siteAttachements": [${repeat:prop.siteAttachement_length:
+ {
+ "siteId": ${prop.siteAttachement[${1}].siteId},
+ "role": [${repeat:prop.siteAttachement[${1}].roles_length:
+ ${prop.siteAttachement[${1}].roles[${2}]},
+ }
+ ],
+ "workMode": "with-interconnection",
+ "sitePriority": "active",
+ "borders": "null"
+ },
+ }
+ ]
+ }
+ ]
+} \ No newline at end of file
diff --git a/plugins/restapi-call-node/provider/src/test/resources/test-template.json b/plugins/restapi-call-node/provider/src/test/resources/test-template.json
new file mode 100644
index 000000000..ae519a731
--- /dev/null
+++ b/plugins/restapi-call-node/provider/src/test/resources/test-template.json
@@ -0,0 +1,37 @@
+{
+ "sdn-circuit-request": [
+ ${repeat:tmp.sdn-circuit-req-row_length:
+ {
+ "request-id": ${tmp.sdn-circuit-req-row[${1}].request-id},
+ "source-uid": ${tmp.sdn-circuit-req-row[${1}].source-uid},
+ "action": ${tmp.sdn-circuit-req-row[${1}].action},
+ "request-timestamp": ${tmp.sdn-circuit-req-row[${1}].request-timestamp},
+ "update-timestamp": ${tmp.sdn-circuit-req-row[${1}].update-timestamp},
+ "request-status": ${tmp.sdn-circuit-req-row[${1}].request-status},
+ "processing-status": ${tmp.sdn-circuit-req-row[${1}].processing-status},
+ "reason-code": ${tmp.sdn-circuit-req-row[${1}].reason-code},
+ "reason-message": ${tmp.sdn-circuit-req-row[${1}].reason-message},
+ "customer-code": ${tmp.sdn-circuit-req-row[${1}].customer-code},
+ "bundle-id": ${tmp.sdn-circuit-req-row[${1}].bundle-id},
+ "router-name-1": ${tmp.sdn-circuit-req-row[${1}].router-name-1},
+ "tail-clfi-1": ${tmp.sdn-circuit-req-row[${1}].tail-clfi-1},
+ "srg-1": ${tmp.sdn-circuit-req-row[${1}].srg-1},
+ "router-name-2": ${tmp.sdn-circuit-req-row[${1}].router-name-2},
+ "tail-clfi-2": ${tmp.sdn-circuit-req-row[${1}].tail-clfi-2},
+ "srg-2": ${tmp.sdn-circuit-req-row[${1}].srg-2},
+ "facility-speed": ${tmp.sdn-circuit-req-row[${1}].facility-speed},
+ "facility-speed-units": ${tmp.sdn-circuit-req-row[${1}].facility-speed-units},
+ "facility-type": ${tmp.sdn-circuit-req-row[${1}].facility-type},
+ "service-clfi": ${tmp.sdn-circuit-req-row[${1}].service-clfi},
+ "clci": ${tmp.sdn-circuit-req-row[${1}].clci},
+ "wavelength-purpose": ${tmp.sdn-circuit-req-row[${1}].wavelength-purpose},
+ "activate-setting": ${tmp.sdn-circuit-req-row[${1}].activate-setting},
+ "apply-date": ${tmp.sdn-circuit-req-row[${1}].apply-date},
+ "run-id": ${tmp.sdn-circuit-req-row[${1}].run-id},
+ "hostname": ${tmp.sdn-circuit-req-row[${1}].hostname},
+ "algo-request-reason": ${tmp.sdn-circuit-req-row[${1}].algo-request-reason}
+ "test-empty-value": ${tmp.sdn-circuit-req-row[${1}].test-empty-value}
+ },
+ }
+ ]
+}
diff --git a/plugins/restapi-call-node/provider/src/test/resources/test.json b/plugins/restapi-call-node/provider/src/test/resources/test.json
new file mode 100644
index 000000000..75155393c
--- /dev/null
+++ b/plugins/restapi-call-node/provider/src/test/resources/test.json
@@ -0,0 +1,30 @@
+{
+ "equipment-data": [
+ {
+ "server-count": "4",
+ "max-server-speed": "1600000",
+ "number-primary-servers": "2",
+ "equipment-id": "Server1",
+ "server-model": "Unknown",
+ "server-id": "Server1",
+ "test-node" : {
+ "test-inner-node" : "Test-Value"
+ }
+ }
+ ],
+ "resource-state": {
+ "threshold-value": "1600000",
+ "last-added": "1605000",
+ "used": "1605000",
+ "limit-value": "1920000"
+ },
+ "resource-rule": {
+ "endpoint-position": "VCE-Cust",
+ "soft-limit-expression": "0.6 * max-server-speed * number-primary-servers",
+ "resource-name": "Bandwidth",
+ "service-model": "DUMMY",
+ "hard-limit-expression": "max-server-speed * number-primary-servers",
+ "equipment-level": "Server"
+ },
+ "message": "The provisioned access bandwidth is at or exceeds 50% of the total server capacity."
+}
diff --git a/plugins/restapi-call-node/provider/src/test/resources/test.xml b/plugins/restapi-call-node/provider/src/test/resources/test.xml
new file mode 100644
index 000000000..1974f688e
--- /dev/null
+++ b/plugins/restapi-call-node/provider/src/test/resources/test.xml
@@ -0,0 +1,182 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ============LICENSE_START=======================================================
+ openECOMP : SDN-C
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property. All rights
+ reserved.
+ ================================================================================
+ 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.
+ ============LICENSE_END=========================================================
+ -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.onap.ccsdk.sli.plugins</groupId>
+ <artifactId>restapi-call-node</artifactId>
+ <version>6.0.0-SNAPSHOT</version>
+ </parent>
+ <artifactId>restapi-call-node-provider</artifactId>
+ <packaging>bundle</packaging>
+ <name>RESTAPI Call Node - Provider</name>
+ <url>http://maven.apache.org</url>
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-test</artifactId>
+ <version>3.1.4.RELEASE</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli</groupId>
+ <artifactId>sli-common</artifactId>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli</groupId>
+ <artifactId>sli-provider</artifactId>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ <version>${slf4j.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>jcl-over-slf4j</artifactId>
+ <version>${slf4j.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-beans</artifactId>
+ <version>3.1.4.RELEASE</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-context</artifactId>
+ <version>3.1.4.RELEASE</version>
+ </dependency>
+ <dependency>
+ <groupId>xerces</groupId>
+ <artifactId>xerces</artifactId>
+ <version>2.4.0</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.sun.jersey</groupId>
+ <artifactId>jersey-client</artifactId>
+ <version>1.17</version>
+ </dependency>
+ <dependency>
+ <groupId>com.sun.jersey.contribs.jersey-oauth</groupId>
+ <artifactId>oauth-signature</artifactId>
+ <version>1.17</version>
+ </dependency>
+ <dependency>
+ <groupId>com.sun.jersey.contribs.jersey-oauth</groupId>
+ <artifactId>oauth-client</artifactId>
+ <version>1.17</version>
+ </dependency>
+ <dependency>
+ <groupId>commons-codec</groupId>
+ <artifactId>commons-codec</artifactId>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>com.brocade.developer</groupId>
+ <artifactId>providermodule-plugin</artifactId>
+ <configuration>
+ <packageId>org.onap.ccsdk.sli.plugins</packageId>
+ <appName>restapi-call-node</appName>
+ </configuration>
+ <executions>
+ <execution>
+ <phase>process-sources</phase>
+ <goals>
+ <goal>process</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+
+
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Bundle-SymbolicName>org.onap.ccsdk.sli.plugins.restapicall</Bundle-SymbolicName>
+ <Export-Package>org.onap.ccsdk.sli.plugins.restapicall</Export-Package>
+ <Import-Package>*</Import-Package>
+ </instructions>
+
+ <manifestLocation>${project.basedir}/src/main/resources/META-INF</manifestLocation>
+
+ </configuration>
+
+ </plugin>
+
+
+ </plugins>
+ <pluginManagement>
+ <plugins>
+ <!--This plugin's configuration is used to store Eclipse m2e settings
+ only. It has no influence on the Maven build itself. -->
+ <plugin>
+ <groupId>org.eclipse.m2e</groupId>
+ <artifactId>lifecycle-mapping</artifactId>
+ <version>1.0.0</version>
+ <configuration>
+ <lifecycleMappingMetadata>
+ <pluginExecutions>
+ <pluginExecution>
+ <pluginExecutionFilter>
+ <groupId>
+ com.brocade.developer
+ </groupId>
+ <artifactId>
+ providermodule-plugin
+ </artifactId>
+ <versionRange>
+ [1.2.0.100-SNAPSHOT,)
+ </versionRange>
+ <goals>
+ <goal>process</goal>
+ </goals>
+ </pluginExecutionFilter>
+ <action>
+ <ignore />
+ </action>
+ </pluginExecution>
+ </pluginExecutions>
+ </lifecycleMappingMetadata>
+ </configuration>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+</project>
diff --git a/plugins/restapi-call-node/provider/src/test/resources/test3.xml b/plugins/restapi-call-node/provider/src/test/resources/test3.xml
new file mode 100644
index 000000000..ade412681
--- /dev/null
+++ b/plugins/restapi-call-node/provider/src/test/resources/test3.xml
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!--
+ ============LICENSE_START=======================================================
+ openECOMP : SDN-C
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property. All rights
+ reserved.
+ ================================================================================
+ 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.
+ ============LICENSE_END=========================================================
+ -->
+
+<ApplyGroupResponse xmlns="http://onap.org/vpn/schema/v1"
+ xmlns:ns2="http://onap.org/prov/vpn/schema/v2">
+ <ApplyGroupResponseData>
+ <ServiceInstanceId>ICOREPVC-81114561</ServiceInstanceId>
+ <VrfDetails>
+ <End2EndVpnKey>VPNL811182</End2EndVpnKey>
+ <VpnId>811182</VpnId>
+ <VrfName>21302:811182</VrfName>
+ <VrfImport>SET_BVOIP_IN</VrfImport>
+ <VrfImport>SET6_BVOIP_IN</VrfImport>
+ <VrfExport>SET6_DSU</VrfExport>
+ <VrfExport>SET_DSU</VrfExport>
+ <VrfExport>SET6_MANAGED</VrfExport>
+ <VrfExport>SET_MANAGED</VrfExport>
+ <VrfExport>SET_LOVRF_COMMUNITY</VrfExport>
+ <VrfExport>SET_RESET_LP</VrfExport>
+ <ApplyGroup>
+ <ns2:ApplyGroup>AG_MAX_MCASTROUTES</ns2:ApplyGroup>
+ </ApplyGroup>
+ </VrfDetails>
+ <RoutingApplyGroups>
+ <RoutingProtocol>BGP4_PROTOCOL</RoutingProtocol>
+ <Family>v4</Family>
+ <PeerGroupName>gp_21302:811182</PeerGroupName>
+ <ApplyGroupPeer>
+ <ns2:ApplyGroup>AG_L3VPN_EBGP</ns2:ApplyGroup>
+ </ApplyGroupPeer>
+ <ApplyGroupPeer>
+ <ns2:ApplyGroup>AG_MAX_PREFIX</ns2:ApplyGroup>
+ </ApplyGroupPeer>
+ <ApplyGroupNeighbour>
+ <ns2:ApplyGroup>AG_BGP_UNMANAGED</ns2:ApplyGroup>
+ </ApplyGroupNeighbour>
+ <ApplyGroupNeighbour>
+ <ns2:ApplyGroup>AG_BFD_BGP_3000</ns2:ApplyGroup>
+ </ApplyGroupNeighbour>
+ </RoutingApplyGroups>
+ <RoutingApplyGroups>
+ <RoutingProtocol>BGP4_PROTOCOL</RoutingProtocol>
+ <Family>v6</Family>
+ <PeerGroupName>gp6_21302:811182</PeerGroupName>
+ <ApplyGroupPeer>
+ <ns2:ApplyGroup>AG6_L3VPN_EBGP</ns2:ApplyGroup>
+ </ApplyGroupPeer>
+ <ApplyGroupPeer>
+ <ns2:ApplyGroup>AG6_MAX_PREFIX</ns2:ApplyGroup>
+ </ApplyGroupPeer>
+ <ApplyGroupNeighbour>
+ <ns2:ApplyGroup>AG6_BGP_UNMANAGED</ns2:ApplyGroup>
+ </ApplyGroupNeighbour>
+ <ApplyGroupNeighbour>
+ <ns2:ApplyGroup>AG6_BFD_BGP_3000</ns2:ApplyGroup>
+ </ApplyGroupNeighbour>
+ </RoutingApplyGroups>
+ </ApplyGroupResponseData>
+ <response-code>200</response-code>
+ <response-message>Success</response-message>
+ <ack-final-indicator>Y</ack-final-indicator>
+</ApplyGroupResponse>
+
diff --git a/plugins/restapi-call-node/provider/src/test/resources/testEmbeddedTemplate.json b/plugins/restapi-call-node/provider/src/test/resources/testEmbeddedTemplate.json
new file mode 100644
index 000000000..7f2377813
--- /dev/null
+++ b/plugins/restapi-call-node/provider/src/test/resources/testEmbeddedTemplate.json
@@ -0,0 +1,20 @@
+{
+ "commonHeader": {
+ "origin": "earth",
+ "requestId": ${reqId},
+ "subRequestId": ${subReqId}
+ },
+ "actions": {
+ "actionName": ${actionName},
+ "mode": "sync"
+ },
+ "payload": {
+ "assignment-request": {
+ "prefix": [
+ ${myPrefix}
+ ],
+ "assignment-properties": ${'"complexObj}
+ }
+ }
+}
+
diff --git a/plugins/restapi-call-node/provider/src/test/resources/testMultiLineEmbeddedTemplate.json b/plugins/restapi-call-node/provider/src/test/resources/testMultiLineEmbeddedTemplate.json
new file mode 100644
index 000000000..84ae3a492
--- /dev/null
+++ b/plugins/restapi-call-node/provider/src/test/resources/testMultiLineEmbeddedTemplate.json
@@ -0,0 +1,20 @@
+{
+ "commonHeader": {
+ "origin": "earth",
+ "requestId": ${reqId},
+ "subRequestId": ${subReqId}
+ },
+ "actions": {
+ "actionName": ${actionName},
+ "mode": "sync"
+ },
+ "payload": {
+ "assignment-request": {
+ "prefix": [
+ ${myPrefix}
+ ],
+ "assignment-properties": ${complexObj}
+ }
+ }
+}
+
diff --git a/plugins/restapi-call-node/provider/src/test/resources/test_file.txt b/plugins/restapi-call-node/provider/src/test/resources/test_file.txt
new file mode 100644
index 000000000..038d757dc
--- /dev/null
+++ b/plugins/restapi-call-node/provider/src/test/resources/test_file.txt
@@ -0,0 +1,5 @@
+“You think your pain and your heartbreak are unprecedented in the history of the world, but then you read. It was books that taught me that the things that tormented me most were the very things that connected me with all the people who were alive, who had ever been alive.” – James Baldwin
+“When I have a little money, I buy books; and if I have any left, I buy food and clothes.” – Erasmus
+“If you only read the books that everyone else is reading, you can only think what everyone else is thinking.” – Haruki Murakami
+“You don’t have to burn books to destroy a culture. Just get people to stop reading them.” – Ray Bradbury
+“A reader lives a thousand lives before he dies, said Jojen. The man who never reads lives only one.” – George R.R. Martin
diff --git a/plugins/restapi-call-node/provider/src/test/resources/ueb.properties b/plugins/restapi-call-node/provider/src/test/resources/ueb.properties
new file mode 100644
index 000000000..96657ee1a
--- /dev/null
+++ b/plugins/restapi-call-node/provider/src/test/resources/ueb.properties
@@ -0,0 +1,6 @@
+#for other servers see http://sa2020.it.att.com:8888/sw/cambria/installs
+
+#to check connectivity http://hostname:3904/metrics
+
+servers=http://uebsb91kcdc.it.att.com:3904 http://uebsb92kcdc.it.att.com:3904 http://uebsb93kcdc.it.att.com:3904
+
diff --git a/plugins/restconf-client/.gitignore b/plugins/restconf-client/.gitignore
new file mode 100755
index 000000000..b73caf31e
--- /dev/null
+++ b/plugins/restconf-client/.gitignore
@@ -0,0 +1,34 @@
+#####standard .git ignore entries#####
+
+## IDE Specific Files ##
+org.eclipse.core.resources.prefs
+.classpath
+.project
+.settings
+.idea
+.externalToolBuilders
+maven-eclipse.xml
+workspace
+
+## Compilation Files ##
+*.class
+**/target
+target
+target-ide
+MANIFEST.MF
+
+## Misc Ignores (OS specific etc) ##
+bin/
+dist
+*~
+*.ipr
+*.iml
+*.iws
+classes
+out/
+.DS_STORE
+.metadata
+
+## Folders which contain auto generated source code ##
+yang-gen-config
+yang-gen-sal
diff --git a/plugins/restconf-client/installer/pom.xml b/plugins/restconf-client/installer/pom.xml
new file mode 100755
index 000000000..9114c7a22
--- /dev/null
+++ b/plugins/restconf-client/installer/pom.xml
@@ -0,0 +1,127 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>odlparent-lite</artifactId>
+ <version>2.1.0</version>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.plugins</groupId>
+ <artifactId>restconf-client-installer</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>pom</packaging>
+
+ <name>ccsdk-sli-plugins :: restconf-client :: ${project.artifactId}</name>
+
+ <properties>
+ <application.name>ccsdk-restconf-client</application.name>
+ <features.boot>${application.name}</features.boot>
+ <features.repositories>mvn:org.onap.ccsdk.sli.plugins/${features.boot}/${project.version}/xml/features
+ </features.repositories>
+ <include.transitive.dependencies>false</include.transitive.dependencies>
+ </properties>
+
+ <dependencies>
+
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.plugins</groupId>
+ <artifactId>restconf-client-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <version>2.6</version>
+ <executions>
+ <execution>
+ <id>maven-repo-zip</id>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ <phase>package</phase>
+ <configuration>
+ <attach>true</attach>
+ <finalName>stage/${application.name}-${project.version}</finalName>
+ <descriptors>
+ <descriptor>src/assembly/assemble_mvnrepo_zip.xml</descriptor>
+ </descriptors>
+ <appendAssemblyId>true</appendAssemblyId>
+ </configuration>
+ </execution>
+ <execution>
+ <id>installer-zip</id>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ <phase>package</phase>
+ <configuration>
+ <attach>true</attach>
+ <finalName>${application.name}-${project.version}-installer</finalName>
+ <descriptors>
+ <descriptor>src/assembly/assemble_installer_zip.xml</descriptor>
+ </descriptors>
+ <appendAssemblyId>false</appendAssemblyId>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>copy-dependencies</id>
+ <goals>
+ <goal>copy-dependencies</goal>
+ </goals>
+ <phase>prepare-package</phase>
+ <configuration>
+ <transitive>false</transitive>
+ <outputDirectory>${project.build.directory}/assembly/system</outputDirectory>
+ <overWriteReleases>false</overWriteReleases>
+ <overWriteSnapshots>true</overWriteSnapshots>
+ <overWriteIfNewer>true</overWriteIfNewer>
+ <useRepositoryLayout>true</useRepositoryLayout>
+ <addParentPoms>false</addParentPoms>
+ <copyPom>false</copyPom>
+ <includeGroupIds>org.onap.ccsdk.sli.plugins</includeGroupIds>
+ <scope>provided</scope>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <artifactId>maven-resources-plugin</artifactId>
+ <version>2.6</version>
+ <executions>
+ <execution>
+ <id>copy-version</id>
+ <goals>
+ <goal>copy-resources</goal>
+ </goals><!-- here the phase you need -->
+ <phase>validate</phase>
+ <configuration>
+ <outputDirectory>${basedir}/target/stage</outputDirectory>
+ <resources>
+ <resource>
+ <directory>src/main/resources/scripts</directory>
+ <includes>
+ <include>install-feature.sh</include>
+ </includes>
+ <filtering>true</filtering>
+ </resource>
+ </resources>
+ </configuration>
+ </execution>
+
+ </executions>
+ </plugin>
+
+ </plugins>
+ </build>
+</project>
diff --git a/plugins/restconf-client/installer/src/assembly/assemble_installer_zip.xml b/plugins/restconf-client/installer/src/assembly/assemble_installer_zip.xml
new file mode 100644
index 000000000..8ffcb88a1
--- /dev/null
+++ b/plugins/restconf-client/installer/src/assembly/assemble_installer_zip.xml
@@ -0,0 +1,58 @@
+<!--
+ * ============LICENSE_START=======================================================
+ * ONAP - CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Huawei Technologies Co., Ltd. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ -->
+
+<!-- Defines how we build the .zip file which is our distribution. -->
+
+<assembly
+ xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
+ <id>installer_zip</id>
+ <formats>
+ <format>zip</format>
+ </formats>
+
+ <!-- we want "system" and related files right at the root level
+ as this file is suppose to be unzip on top of a karaf
+ distro. -->
+ <includeBaseDirectory>false</includeBaseDirectory>
+
+ <fileSets>
+ <fileSet>
+ <directory>target/stage/</directory>
+ <outputDirectory>${application.name}</outputDirectory>
+ <fileMode>755</fileMode>
+ <includes>
+ <include>*.sh</include>
+ </includes>
+ </fileSet>
+ <fileSet>
+ <directory>target/stage/</directory>
+ <outputDirectory>${application.name}</outputDirectory>
+ <fileMode>644</fileMode>
+ <excludes>
+ <exclude>*.sh</exclude>
+ </excludes>
+ </fileSet>
+ </fileSets>
+
+
+
+</assembly>
diff --git a/plugins/restconf-client/installer/src/assembly/assemble_mvnrepo_zip.xml b/plugins/restconf-client/installer/src/assembly/assemble_mvnrepo_zip.xml
new file mode 100644
index 000000000..252c39d3c
--- /dev/null
+++ b/plugins/restconf-client/installer/src/assembly/assemble_mvnrepo_zip.xml
@@ -0,0 +1,48 @@
+<!--
+ * ============LICENSE_START=======================================================
+ * ONAP - CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Huawei Technologies Co., Ltd. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ -->
+
+<!-- Defines how we build the .zip file which is our distribution. -->
+
+<assembly
+ xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
+ <id>repo</id>
+ <formats>
+ <format>zip</format>
+ </formats>
+
+ <!-- we want "system" and related files right at the root level
+ as this file is suppose to be unzip on top of a karaf
+ distro. -->
+ <includeBaseDirectory>false</includeBaseDirectory>
+
+ <fileSets>
+ <fileSet>
+ <directory>target/assembly/</directory>
+ <outputDirectory>.</outputDirectory>
+ <excludes>
+ </excludes>
+ </fileSet>
+ </fileSets>
+
+
+
+</assembly>
diff --git a/plugins/restconf-client/installer/src/main/resources/scripts/install-feature.sh b/plugins/restconf-client/installer/src/main/resources/scripts/install-feature.sh
new file mode 100644
index 000000000..8e9195d57
--- /dev/null
+++ b/plugins/restconf-client/installer/src/main/resources/scripts/install-feature.sh
@@ -0,0 +1,38 @@
+#!/bin/bash
+
+###
+# ============LICENSE_START=======================================================
+# ONAP : CCSDK
+# ================================================================================
+# Copyright (C) 2018 Huawei Technologies Co., Ltd. All rights reserved.
+# ================================================================================
+# 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.
+# ============LICENSE_END=========================================================
+###
+
+ODL_HOME=${ODL_HOME:-/opt/opendaylight/current}
+ODL_KARAF_CLIENT=${ODL_KARAF_CLIENT:-${ODL_HOME}/bin/client}
+INSTALLERDIR=$(dirname $0)
+
+REPOZIP=${INSTALLERDIR}/${features.boot}-${project.version}.zip
+
+if [ -f ${REPOZIP} ]
+then
+ unzip -nd ${ODL_HOME} ${REPOZIP}
+else
+ echo "ERROR : repo zip ($REPOZIP) not found"
+ exit 1
+fi
+
+${ODL_KARAF_CLIENT} feature:repo-add ${features.repositories}
+${ODL_KARAF_CLIENT} feature:install ${features.boot}
diff --git a/plugins/restconf-client/pom.xml b/plugins/restconf-client/pom.xml
new file mode 100755
index 000000000..ee2d0423c
--- /dev/null
+++ b/plugins/restconf-client/pom.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>odlparent-lite</artifactId>
+ <version>2.1.0</version>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.plugins</groupId>
+ <artifactId>restconf-client</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>pom</packaging>
+
+ <name>ccsdk-sli-plugins :: restconf-client</name>
+ <description>This is an implementation of DG Execute Node that makes a call to an external RESTCONF API</description>
+
+ <modules>
+ <module>provider</module>
+ <module>installer</module>
+ </modules>
+</project>
diff --git a/plugins/restconf-client/provider/pom.xml b/plugins/restconf-client/provider/pom.xml
new file mode 100755
index 000000000..ab57af017
--- /dev/null
+++ b/plugins/restconf-client/provider/pom.xml
@@ -0,0 +1,132 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>binding-parent</artifactId>
+ <version>2.1.0</version>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.plugins</groupId>
+ <artifactId>restconf-client-provider</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>bundle</packaging>
+
+ <name>ccsdk-sli-plugins :: restconf-client :: ${project.artifactId}</name>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sli-core-artifacts</artifactId>
+ <version>${ccsdk.sli.core.version}</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.glassfish.jersey.media</groupId>
+ <artifactId>jersey-media-sse</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>javax.ws.rs</groupId>
+ <artifactId>javax.ws.rs-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sli-common</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sli-provider</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.plugins</groupId>
+ <artifactId>properties-node-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-data-impl</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-databind</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.dom4j</groupId>
+ <artifactId>dom4j</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.google.code.gson</groupId>
+ <artifactId>gson</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.plugins</groupId>
+ <artifactId>restapi-call-node-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.netconf</groupId>
+ <artifactId>restconf-nb-rfc8040</artifactId>
+ <scope>provided</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>javax.xml</groupId>
+ <artifactId>jsr173</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-parser-impl</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.core</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ <!-- For test -->
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-servlet</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.containers</groupId>
+ <artifactId>jersey-container-grizzly2-http</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.hamcrest</groupId>
+ <artifactId>hamcrest-library</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.opendaylight.yangtools</groupId>
+ <artifactId>yang-test-util</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.glassfish.jersey.core</groupId>
+ <artifactId>jersey-client</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/restconfapicall/RestconfApiCallNode.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/restconfapicall/RestconfApiCallNode.java
new file mode 100644
index 000000000..620df282f
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/restconfapicall/RestconfApiCallNode.java
@@ -0,0 +1,484 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Huawei Technologies Co., Ltd. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.restconfapicall;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import com.google.gson.stream.JsonWriter;
+
+import javax.ws.rs.core.UriBuilder;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.net.SocketException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.dom4j.Document;
+import org.dom4j.DocumentException;
+import org.dom4j.DocumentHelper;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.core.sli.SvcLogicJavaPlugin;
+import org.onap.ccsdk.sli.plugins.restapicall.Format;
+import org.onap.ccsdk.sli.plugins.restapicall.HttpResponse;
+import org.onap.ccsdk.sli.plugins.restapicall.RestapiCallNode;
+import org.onap.ccsdk.sli.plugins.restapicall.XmlParser;
+import org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DataFormatSerializer;
+import org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DataFormatSerializerContext;
+import org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DfSerializerFactory;
+import org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.Listener;
+import org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.MdsalSerializerHelper;
+import org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.SerializerHelper;
+import org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.YangParameters;
+import org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeSerializer;
+import org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.Namespace;
+import org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.PropertiesNodeSerializer;
+import org.opendaylight.restconf.common.context.InstanceIdentifierContext;
+import org.opendaylight.restconf.nb.rfc8040.utils.parser.ParserIdentifier;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaNode;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static com.google.common.base.Strings.repeat;
+import static java.lang.String.format;
+import static java.lang.String.valueOf;
+import static org.apache.commons.lang3.StringUtils.join;
+import static org.onap.ccsdk.sli.plugins.restapicall.HttpMethod.DELETE;
+import static org.onap.ccsdk.sli.plugins.restapicall.HttpMethod.GET;
+import static org.onap.ccsdk.sli.plugins.restapicall.HttpMethod.PATCH;
+import static org.onap.ccsdk.sli.plugins.restapicall.HttpMethod.PUT;
+import static org.onap.ccsdk.sli.plugins.restapicall.RestapiCallNode.parseParam;
+import static org.onap.ccsdk.sli.plugins.restconfapicall.RestconfApiUtils.ATTEMPTS_MSG;
+import static org.onap.ccsdk.sli.plugins.restconfapicall.RestconfApiUtils.COLON;
+import static org.onap.ccsdk.sli.plugins.restconfapicall.RestconfApiUtils.COMMA;
+import static org.onap.ccsdk.sli.plugins.restconfapicall.RestconfApiUtils.COMM_FAIL;
+import static org.onap.ccsdk.sli.plugins.restconfapicall.RestconfApiUtils.HEADER;
+import static org.onap.ccsdk.sli.plugins.restconfapicall.RestconfApiUtils.HTTP_REQ;
+import static org.onap.ccsdk.sli.plugins.restconfapicall.RestconfApiUtils.HTTP_RES;
+import static org.onap.ccsdk.sli.plugins.restconfapicall.RestconfApiUtils.MAX_RETRY_ERR;
+import static org.onap.ccsdk.sli.plugins.restconfapicall.RestconfApiUtils.NO_MORE_RETRY;
+import static org.onap.ccsdk.sli.plugins.restconfapicall.RestconfApiUtils.REQ_ERR;
+import static org.onap.ccsdk.sli.plugins.restconfapicall.RestconfApiUtils.REST_API_URL;
+import static org.onap.ccsdk.sli.plugins.restconfapicall.RestconfApiUtils.RES_CODE;
+import static org.onap.ccsdk.sli.plugins.restconfapicall.RestconfApiUtils.RES_MSG;
+import static org.onap.ccsdk.sli.plugins.restconfapicall.RestconfApiUtils.RES_PRE;
+import static org.onap.ccsdk.sli.plugins.restconfapicall.RestconfApiUtils.RETRY_COUNT;
+import static org.onap.ccsdk.sli.plugins.restconfapicall.RestconfApiUtils.RETRY_FAIL;
+import static org.onap.ccsdk.sli.plugins.restconfapicall.RestconfApiUtils.UPDATED_URL;
+import static org.onap.ccsdk.sli.plugins.restconfapicall.RestconfApiUtils.getSchemaCtxFromDir;
+import static org.onap.ccsdk.sli.plugins.restconfapicall.RestconfApiUtils.getUpdatedXmlReq;
+import static org.onap.ccsdk.sli.plugins.restconfapicall.RestconfApiUtils.getYangParameters;
+import static org.onap.ccsdk.sli.plugins.restconfapicall.RestconfApiUtils.parseUrl;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DfListenerFactory.instance;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DfSerializerUtil.FORMAT_ERR;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DfSerializerUtil.UTF_HEADER;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DfSerializerUtil.XML_TREE_ERR;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DfSerializerUtil.getXmlWriter;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.getModuleNamespace;
+import static org.osgi.framework.FrameworkUtil.getBundle;
+
+/**
+ * Representation of a plugin to enable RESTCONF based CRUD operations from DG.
+ */
+public class RestconfApiCallNode implements SvcLogicJavaPlugin {
+
+ /**
+ * Logger for the restconf api call node class.
+ */
+ private static final Logger log = LoggerFactory.getLogger(
+ RestconfApiCallNode.class);
+
+ /**
+ * Rest api call node service instance
+ */
+ private RestapiCallNode restapiCallNode;
+
+ /**
+ * Creates an instance of restconf api call node with restapi call node.
+ *
+ * @param r restapi call node
+ */
+ public RestconfApiCallNode(RestapiCallNode r) {
+ this.restapiCallNode = r;
+ }
+
+ /**
+ * Returns the restapi call node instance.
+ * @return
+ */
+ public RestapiCallNode getRestapiCallNode() {
+ return restapiCallNode;
+ }
+
+ /**
+ * Sends the restconf request using the parameters map and the memory
+ * context. And this method allows the directed graphs to interact with
+ * the restconf api call node
+ *
+ * @param paramMap parameters map
+ * @param ctx service logic context
+ * @throws SvcLogicException when svc logic exception occurs
+ */
+ public void sendRequest(Map<String, String> paramMap, SvcLogicContext ctx)
+ throws SvcLogicException {
+ sendRequest(paramMap, ctx, 0);
+ }
+
+ /**
+ * Sends the restconf request using the parameters map and the memory
+ * context along with the retry count.
+ *
+ * @param paramMap parameters map
+ * @param ctx service logic context
+ * @param retryCount number of retry counts
+ * @throws SvcLogicException when svc logic exception occurs
+ */
+ public void sendRequest(Map<String, String> paramMap, SvcLogicContext ctx,
+ Integer retryCount) throws SvcLogicException {
+ RestapiCallNode rest = getRestapiCallNode();
+ HttpResponse r = new HttpResponse();
+ try {
+ YangParameters p = getYangParameters(paramMap);
+
+ String pp = p.responsePrefix != null ? p.responsePrefix + '.' : "";
+ Map<String, String> props = new HashMap<>((Map)ctx.toProperties());
+ String uri = parseUrl(p.restapiUrl, p.httpMethod);
+ InstanceIdentifierContext<?> insIdCtx = getInsIdCtx(p, uri);
+
+ String req = null;
+ if (p.httpMethod != GET && p.httpMethod != DELETE) {
+ req = serializeRequest(props, p, uri, insIdCtx);
+ if (p.httpMethod == PUT || p.httpMethod == PATCH) {
+ updateReq(req, p, insIdCtx);
+ }
+ }
+ if (req == null && p.requestBody != null) {
+ req = p.requestBody;
+ }
+
+ r = rest.sendHttpRequest(req, p);
+ if (p.returnRequestPayload && req != null) {
+ ctx.setAttribute(pp + HTTP_REQ, req);
+ }
+
+ String response = getResponse(ctx, p, pp, r);
+ if (response != null) {
+ try {
+ Map<String, String> resProp = serializeResponse(
+ p, uri, response, insIdCtx);
+ for (Map.Entry<String, String> pro : resProp.entrySet()) {
+ ctx.setAttribute(pro.getKey(), pro.getValue());
+ }
+ } catch (SvcLogicException e) {
+ convertToNormalRes(ctx, p, pp, response);
+ }
+ }
+ } catch (SvcLogicException e) {
+ boolean shouldRetry = false;
+ if (e.getCause().getCause() instanceof SocketException) {
+ shouldRetry = true;
+ }
+
+ log.error(REQ_ERR + e.getMessage(), e);
+ String prefix = parseParam(paramMap, RES_PRE, false, null);
+ setFailureResponseStatus(ctx, prefix, e.getMessage());
+ }
+
+ if (r != null && r.code >= 300) {
+ throw new SvcLogicException(valueOf(r.code) +
+ COLON + " " + r.message);
+ }
+ }
+
+ private void convertToNormalRes(SvcLogicContext ctx ,
+ YangParameters p, String pp, String body)
+ throws SvcLogicException {
+ if (p.convertResponse) {
+ Map<String, String> mm = null;
+ if (p.format == Format.XML) {
+ mm = XmlParser.convertToProperties(body, p.listNameList);
+ } else if (p.format == Format.JSON) {
+ mm = org.onap.ccsdk.sli.plugins.restapicall.JsonParser
+ .convertToProperties(body);
+ }
+
+ if (mm != null) {
+ for (Map.Entry<String, String> entry : mm.entrySet()) {
+ ctx.setAttribute(pp + entry.getKey(),
+ entry.getValue());
+ }
+ }
+ }
+ }
+
+ /**
+ * Serializes the request message to JSON or XML from the properties.
+ *
+ * @param properties properties
+ * @param params YANG parameters
+ * @param uri URI
+ * @param insIdCtx instance identifier context
+ * @return JSON or XML message to be sent
+ * @throws SvcLogicException when serializing the request fails
+ */
+ public String serializeRequest(Map<String, String> properties,
+ YangParameters params, String uri,
+ InstanceIdentifierContext insIdCtx)
+ throws SvcLogicException {
+ PropertiesNodeSerializer propSer = new MdsalPropertiesNodeSerializer(
+ insIdCtx.getSchemaNode(), insIdCtx.getSchemaContext(), uri);
+ DataFormatSerializerContext serCtx = new DataFormatSerializerContext(
+ null, uri, null, propSer);
+ DataFormatSerializer ser = DfSerializerFactory.instance()
+ .getSerializer(serCtx, params);
+ //TODO: Handling of XML annotations
+ return ser.encode(properties, null);
+ }
+
+ /**
+ * Serializes the response message from JSON or XML to the properties.
+ *
+ * @param params YANG parameters
+ * @param uri URI
+ * @param response response message
+ * @param insIdCtx instance identifier context
+ * @return response message as properties
+ * @throws SvcLogicException when serializing the response fails
+ */
+ public Map<String, String> serializeResponse(YangParameters params,
+ String uri, String response,
+ InstanceIdentifierContext insIdCtx)
+ throws SvcLogicException {
+ PropertiesNodeSerializer propSer = new MdsalPropertiesNodeSerializer(
+ insIdCtx.getSchemaNode(), insIdCtx.getSchemaContext(), uri);
+ SerializerHelper helper = new MdsalSerializerHelper(
+ insIdCtx.getSchemaNode(), insIdCtx.getSchemaContext(), uri);
+ Listener listener = instance().getListener(helper, params);
+ DataFormatSerializerContext serCtx = new DataFormatSerializerContext(
+ listener, uri, null, propSer);
+ DataFormatSerializer ser = DfSerializerFactory.instance()
+ .getSerializer(serCtx, params);
+ return ser.decode(response);
+ }
+
+ /**
+ * Returns instance identifier context for a uri using the schema context.
+ *
+ * @param params YANG parameters
+ * @param uri URI
+ * @return instance identifier context
+ * @throws SvcLogicException when getting schema context fails
+ */
+ private InstanceIdentifierContext<?> getInsIdCtx(YangParameters params,
+ String uri)
+ throws SvcLogicException {
+ SchemaContext context = getSchemaContext(params);
+ return ParserIdentifier.toInstanceIdentifier(uri, context, null);
+ }
+
+ /**
+ * Returns the global schema context or schema context of particular YANG
+ * files present in a directory path.
+ *
+ * @param params YANG parameters
+ * @return schema context
+ * @throws SvcLogicException when schema context fetching fails
+ */
+ private SchemaContext getSchemaContext(YangParameters params)
+ throws SvcLogicException {
+ if (params.dirPath != null) {
+ return getSchemaCtxFromDir(params.dirPath);
+ }
+ BundleContext bc = getBundle(SchemaContext.class).getBundleContext();
+ SchemaContext schemaContext = null;
+ if (bc != null) {
+ ServiceReference reference = bc.getServiceReference(
+ SchemaContext.class);
+ if (reference != null) {
+ schemaContext = (SchemaContext) bc.getService(reference);
+ }
+ }
+ return schemaContext;
+ }
+
+ /**
+ * Returns the response message body of a http response message.
+ *
+ * @param ctx svc logic context
+ * @param params parameters
+ * @param pre prefix to be appended
+ * @param res http response
+ * @return response message body
+ */
+ public String getResponse(SvcLogicContext ctx, YangParameters params,
+ String pre, HttpResponse res) {
+ ctx.setAttribute(pre + RES_CODE, valueOf(res.code));
+ ctx.setAttribute(pre + RES_MSG, res.message);
+
+ if (params.dumpHeaders && res.headers != null) {
+ for (Map.Entry<String, List<String>> a : res.headers.entrySet()) {
+ ctx.setAttribute(pre + HEADER + a.getKey(),
+ join(a.getValue(), COMMA));
+ }
+ }
+
+ if (res.body != null && res.body.trim().length() > 0) {
+ ctx.setAttribute(pre + HTTP_RES, res.body);
+ return res.body;
+ }
+ return null;
+ }
+
+ /**
+ * Sets the failure response status in the context memory.
+ *
+ * @param ctx service logic context
+ * @param prefix prefix to be added
+ * @param errMsg error message
+ */
+ private void setFailureResponseStatus(SvcLogicContext ctx, String prefix,
+ String errMsg) {
+ HttpResponse res = new HttpResponse();
+ res.code = 500;
+ res.message = errMsg;
+ ctx.setAttribute(prefix + RES_CODE, valueOf(res.code));
+ ctx.setAttribute(prefix + RES_MSG, res.message);
+ }
+
+ /**
+ * Updates request message for JSON and XML data format, when the HTTP
+ * method points it as PUT or PATCH.
+ *
+ * @param req current request message
+ * @param p YANG parameters
+ * @param insIdCtx instance identifier context
+ * @return update request message
+ * @throws SvcLogicException when the data format type is wrong
+ */
+ public String updateReq(String req, YangParameters p,
+ InstanceIdentifierContext<?> insIdCtx)
+ throws SvcLogicException {
+
+ SchemaNode schemaNode = insIdCtx.getSchemaNode();
+ Namespace modNs = getModuleNamespace(schemaNode.getQName(),
+ insIdCtx.getSchemaContext());
+ String nodeName = schemaNode.getQName().getLocalName();
+
+ switch (p.format) {
+ case JSON:
+ return getUpdatedJsonReq(req, nodeName, modNs.moduleName());
+
+ case XML:
+ return getXmlReqForPutOp(req, nodeName, modNs.moduleNs());
+
+ default:
+ throw new SvcLogicException(format(FORMAT_ERR, p.format));
+ }
+ }
+
+ /**
+ * Returns the updated JSON request message, when the HTTP method
+ * points to PUT or PATCH.
+ *
+ * @param req current JSON request message
+ * @param nodeName root node name
+ * @param modName module name of the root node
+ * @return update JSON request message
+ */
+ private String getUpdatedJsonReq(String req, String nodeName,
+ String modName) {
+ Writer writer = new StringWriter();
+ JsonWriter jsonWriter = new JsonWriter(writer);
+ jsonWriter.setIndent(repeat(" ", 4));
+
+ JsonParser jsonParser = new JsonParser();
+ JsonObject oldJson = (JsonObject)jsonParser.parse(req);
+ oldJson = remChildModName(oldJson, modName);
+ JsonObject newJson = new JsonObject();
+ newJson.add(modName + COLON + nodeName, oldJson.deepCopy());
+
+ Gson gson= new Gson();
+ gson.toJson(newJson, jsonWriter);
+ return writer.toString();
+ }
+
+ /**
+ * Removes module name from all the updated first level child node, if it
+ * is same as the root node added.
+ *
+ * @param oldJson JSON object for old request
+ * @param modName module name of root node
+ * @return JSON object for old request with updated child module name
+ */
+ private JsonObject remChildModName(JsonObject oldJson, String modName) {
+ Iterator<Map.Entry<String, JsonElement>> it = oldJson.entrySet().iterator();
+ Map<String, JsonElement> m = new HashMap<>();
+ while (it.hasNext()) {
+ Map.Entry<String, JsonElement> jNode = it.next();
+ if (jNode.getKey().contains(COLON)) {
+ String[] modArr = jNode.getKey().split(COLON);
+ if (modArr[0].equals(modName)) {
+ it.remove();
+ m.put(modArr[1], jNode.getValue());
+ }
+ }
+ }
+ if (!m.isEmpty()) {
+ for (Map.Entry<String, JsonElement> element : m.entrySet()) {
+ oldJson.add(element.getKey(), element.getValue());
+ }
+ }
+ return oldJson;
+ }
+
+ /**
+ * Returns the updated XML request message, when the HTTP method points
+ * to PUT or PATCH.
+ *
+ * @param req current JSON request message
+ * @param nodeName root node name
+ * @param modNs module namespace of the root node
+ * @return update JSON request message
+ * @throws SvcLogicException when XML parsing fails
+ */
+ private String getXmlReqForPutOp(String req, String nodeName,
+ URI modNs) throws SvcLogicException {
+ req = getUpdatedXmlReq(req, nodeName, modNs.toString());
+ Document oldDoc;
+ try {
+ oldDoc = DocumentHelper.parseText(req);
+ } catch (DocumentException e) {
+ throw new SvcLogicException(XML_TREE_ERR, e);
+ }
+ Writer writer = getXmlWriter(
+ UTF_HEADER + oldDoc.getRootElement().asXML(), "4");
+ return writer.toString();
+ }
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/restconfapicall/RestconfApiUtils.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/restconfapicall/RestconfApiUtils.java
new file mode 100644
index 000000000..1309102b3
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/restconfapicall/RestconfApiUtils.java
@@ -0,0 +1,265 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Huawei Technologies Co., Ltd. All rights reserved.
+ *
+ * Modifications Copyright © 2018 IBM.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.restconfapicall;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.plugins.restapicall.HttpMethod;
+import org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.YangParameters;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.parser.api.YangSyntaxErrorException;
+import org.opendaylight.yangtools.yang.parser.rfc7950.repo.YangStatementStreamSource;
+import org.opendaylight.yangtools.yang.parser.spi.meta.ReactorException;
+import org.opendaylight.yangtools.yang.parser.stmt.reactor.CrossSourceStatementReactor;
+
+import static org.onap.ccsdk.sli.plugins.restapicall.RestapiCallNode.getParameters;
+import static org.onap.ccsdk.sli.plugins.restapicall.RestapiCallNode.parseParam;
+import static org.opendaylight.yangtools.yang.model.repo.api.StatementParserMode.DEFAULT_MODE;
+import static org.opendaylight.yangtools.yang.model.repo.api.YangTextSchemaSource.forFile;
+import static org.opendaylight.yangtools.yang.parser.rfc7950.reactor.RFC7950Reactors.defaultReactor;
+import static org.opendaylight.yangtools.yang.parser.rfc7950.repo.YangStatementStreamSource.create;
+
+/**
+ * Utilities for restconf api call node.
+ */
+public final class RestconfApiUtils {
+
+ static final String RES_CODE = "response-code";
+
+ static final String HTTP_REQ ="httpRequest";
+
+ static final String RES_PRE = "responsePrefix";
+
+ static final String RES_MSG = "response-message";
+
+ static final String HEADER = "header.";
+
+ static final String COMMA = ",";
+
+ static final String COLON = ":";
+
+ static final String HTTP_RES = "httpResponse";
+
+ static final String REST_API_URL = "restapiUrl";
+
+ static final String UPDATED_URL = "URL was set to";
+
+ static final String COMM_FAIL = "Failed to communicate with host %s." +
+ "Request will be re-attempted using the host %s.";
+
+ static final String RETRY_COUNT = "This is retry attempt %d out of %d";
+
+ static final String RETRY_FAIL = "Retry attempt has failed. No further " +
+ "retry shall be attempted, calling setFailureResponseStatus";
+
+ static final String NO_MORE_RETRY = "Could not attempt retry";
+
+ static final String MAX_RETRY_ERR = "Maximum retries reached, calling " +
+ "setFailureResponseStatus";
+
+ static final String ATTEMPTS_MSG = "%d attempts were made out of %d " +
+ "maximum retries";
+
+ static final String REQ_ERR = "Error sending the request: ";
+
+ private static final String SLASH = "/";
+
+ private static final String DIR_PATH = "dirPath";
+
+ private static final String URL_SYNTAX = "The following URL cannot be " +
+ "parsed into URI : ";
+
+ private static final String YANG = ".yang";
+
+ private static final String YANG_FILE_ERR = "Unable to parse the YANG " +
+ "file provided";
+
+ //No instantiation.
+ private RestconfApiUtils() {
+ }
+
+ /**
+ * Returns the YANG parameters after parsing it from the map.
+ *
+ * @param paramMap parameters map
+ * @return YANG parameters
+ * @throws SvcLogicException when parsing of parameters map fail
+ */
+ static YangParameters getYangParameters(Map<String, String> paramMap)
+ throws SvcLogicException {
+ YangParameters param = (YangParameters) getParameters(
+ paramMap, new YangParameters());
+ param.dirPath = parseParam(paramMap, DIR_PATH, false, null);
+ return param;
+ }
+
+ /**
+ * Parses the restconf URL and gives the YANG path from it, which can be
+ * used to get schema node. If it is a PUT operation, then a node must be
+ * reduced from the url to make it always point to the parent.
+ *
+ * @param url restconf URL
+ * @param method HTTP operation
+ * @return YANG path pointing to parent
+ * @throws SvcLogicException when parsing the URL fails
+ */
+ public static String parseUrl(String url, HttpMethod method)
+ throws SvcLogicException {
+ URI uri;
+ try {
+ uri = new URI(url);
+ } catch (URISyntaxException e) {
+ throw new SvcLogicException(URL_SYNTAX + url, e);
+ }
+
+ String path = uri.getPath();
+ path = getParsedPath(path);
+ return path;
+ }
+
+ /**
+ * Returns the path which contains only the schema nodes.
+ *
+ * @param path path
+ * @return path representing schema
+ */
+ private static String getParsedPath(String path) {
+ String firstHalf;
+ String secondHalf;
+ if (path.contains(COLON)) {
+ String[] p = path.split(COLON);
+ if (p[0].contains(SLASH)) {
+ int slash = p[0].lastIndexOf(SLASH);
+ firstHalf = p[0].substring(slash + 1);
+ } else {
+ firstHalf = p[0];
+ }
+ secondHalf = path.substring(p[0].length() + 1);
+ return firstHalf + COLON + secondHalf;
+ } else if (path.contains(SLASH)) {
+ String[] p = path.split(SLASH);
+ if (p.length > 4) {
+ String actual = p[3] + COLON + p[4];
+ if (p.length > 5) {
+ secondHalf = path.substring(
+ p[1].length() + p[2].length() + actual.length() + 3);
+ path = actual + secondHalf;
+ } else {
+ path = actual;
+ }
+ }
+ }
+ return path;
+ }
+
+ /**
+ * Returns the schema context of the YANG files present in a directory.
+ *
+ * @param di directory path
+ * @return YANG schema context
+ * @throws SvcLogicException when YANG file reading fails
+ */
+ static SchemaContext getSchemaCtxFromDir(String di)
+ throws SvcLogicException {
+ Path d = Paths.get(di);
+ File dir = d.toFile();
+ List<File> yangFiles = new LinkedList<>();
+ getYangFiles(dir, yangFiles);
+ final Collection<YangStatementStreamSource> sources =
+ new ArrayList<>(yangFiles.size());
+ for (File file : yangFiles) {
+ try {
+ sources.add(create(forFile(file)));
+ } catch (IOException | YangSyntaxErrorException e) {
+ throw new SvcLogicException(YANG_FILE_ERR + e.getMessage(), e);
+ }
+ }
+
+ final CrossSourceStatementReactor.BuildAction reactor = defaultReactor()
+ .newBuild(DEFAULT_MODE).addSources(sources);
+ try {
+ return reactor.buildEffective();
+ } catch (ReactorException e) {
+ throw new SvcLogicException(YANG_FILE_ERR + e.getMessage(), e);
+ }
+ }
+
+ /**
+ * Returns all the YANG files present in a directory recursively.
+ *
+ * @param dir path of the directory
+ * @param yangFiles list of YANG files
+ */
+ private static void getYangFiles(File dir, List<File> yangFiles) {
+ if (dir.exists()) {
+ File[] files = dir.listFiles();
+ if (files != null) {
+ processFiles(files, yangFiles);
+ }
+ }
+ }
+
+ /**
+ * Processes all the obtained files by isolating all the YANG files from
+ * all the directory of the given path recursively.
+ *
+ * @param files files in the given path
+ * @param yangFiles YANG files list
+ */
+ private static void processFiles(File[] files, List<File> yangFiles) {
+ for (File file : files) {
+ if (file.isFile() && file.getName().endsWith(YANG)) {
+ yangFiles.add(file);
+ } else if (file.isDirectory()) {
+ getYangFiles(file, yangFiles);
+ }
+ }
+ }
+
+ /**
+ * Returns the updated XML request message by adding root node to it.
+ *
+ * @param req XML request
+ * @param nodeName root node name
+ * @param modNs module namespace of the root node
+ * @return updated XML request message
+ */
+ static String getUpdatedXmlReq(String req, String nodeName, String modNs) {
+ String rootNode = "\n<" + nodeName + " xmlns=\"" + modNs +
+ "\">\n";
+ req = req.replaceFirst("\n", rootNode);
+ req = req + "</" + nodeName + ">";
+ return req.replaceAll(">\\s+<", "><");
+ }
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/restconfdiscovery/AdditionalHeaderWebTarget.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/restconfdiscovery/AdditionalHeaderWebTarget.java
new file mode 100644
index 000000000..3213cae15
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/restconfdiscovery/AdditionalHeaderWebTarget.java
@@ -0,0 +1,166 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Huawei Technologies Co., Ltd. All rights reserved.
+ *
+ * Modifications Copyright © 2018 IBM
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.restconfdiscovery;
+
+import javax.ws.rs.client.Invocation;
+import javax.ws.rs.client.WebTarget;
+import javax.ws.rs.core.Configuration;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.UriBuilder;
+import java.net.URI;
+import java.util.Map;
+
+/**
+ * Adds additional headers for SSE request.
+ */
+class AdditionalHeaderWebTarget implements WebTarget {
+ private WebTarget base;
+ private String token;
+
+ private String accessToken = "X-ACCESS-TOKEN";
+
+ public AdditionalHeaderWebTarget(WebTarget target, String token) {
+ base = target;
+ this.token = token;
+ }
+
+ @Override
+ public Invocation.Builder request() {
+ return base.request().header(accessToken, token);
+ }
+
+ @Override
+ public Invocation.Builder request(String... acceptedResponseTypes) {
+ return base.request().header(accessToken, token);
+ }
+
+ @Override
+ public Invocation.Builder request(MediaType... acceptedResponseTypes) {
+ return base.request().header(accessToken, token);
+ }
+
+ @Override
+ public Configuration getConfiguration() {
+ return base.getConfiguration();
+ }
+
+ @Override
+ public URI getUri() {
+ return base.getUri();
+ }
+
+ @Override
+ public UriBuilder getUriBuilder() {
+ return base.getUriBuilder();
+ }
+
+ @Override
+ public WebTarget path(String path) {
+ return base.path(path);
+ }
+
+ @Override
+ public WebTarget resolveTemplate(String name, Object value) {
+ return base.resolveTemplate(name, value);
+ }
+
+ @Override
+ public WebTarget resolveTemplate(String name, Object value, boolean encodeSlashInPath) {
+ return base.resolveTemplate(name, value, encodeSlashInPath);
+ }
+
+ @Override
+ public WebTarget resolveTemplateFromEncoded(String name, Object value) {
+ return base.resolveTemplateFromEncoded(name, value);
+ }
+
+ @Override
+ public WebTarget resolveTemplates(Map<String, Object> templateValues) {
+ return base.resolveTemplates(templateValues);
+ }
+
+ @Override
+ public WebTarget resolveTemplates(Map<String, Object> templateValues, boolean encodeSlashInPath) {
+ return base.resolveTemplates(templateValues, encodeSlashInPath);
+ }
+
+ @Override
+ public WebTarget resolveTemplatesFromEncoded(Map<String, Object> templateValues) {
+ return base.resolveTemplatesFromEncoded(templateValues);
+ }
+
+ @Override
+ public WebTarget matrixParam(String name, Object... values) {
+ return base.matrixParam(name, values);
+ }
+
+ @Override
+ public WebTarget queryParam(String name, Object... values) {
+ return base.queryParam(name, values);
+ }
+
+ @Override
+ public WebTarget property(String name, Object value) {
+ return base.property(name, value);
+ }
+
+ @Override
+ public WebTarget register(Class<?> componentClass) {
+ return base.register(componentClass);
+ }
+
+ @Override
+ public WebTarget register(Class<?> componentClass, int priority) {
+ return base.register(componentClass, priority);
+ }
+
+ @Override
+ public WebTarget register(Class<?> componentClass, Class<?>... contracts) {
+ return base.register(componentClass, contracts);
+ }
+
+ @Override
+ public WebTarget register(Class<?> componentClass, Map<Class<?>, Integer> contracts) {
+ return base.register(componentClass, contracts);
+ }
+
+ @Override
+ public WebTarget register(Object component) {
+ return base.register(component);
+ }
+
+ @Override
+ public WebTarget register(Object component, int priority) {
+ return base.register(component, priority);
+ }
+
+ @Override
+ public WebTarget register(Object component, Class<?>... contracts) {
+ return base.register(component, contracts);
+ }
+
+ @Override
+ public WebTarget register(Object component, Map<Class<?>, Integer> contracts) {
+ return base.register(component, contracts);
+ }
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/restconfdiscovery/EventHandler.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/restconfdiscovery/EventHandler.java
new file mode 100644
index 000000000..a76554d5a
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/restconfdiscovery/EventHandler.java
@@ -0,0 +1,46 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Huawei Technologies Co., Ltd. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.restconfdiscovery;
+
+import org.glassfish.jersey.media.sse.InboundEvent;
+import org.glassfish.jersey.media.sse.EventListener;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Listener that can be registered to listen for notifications.
+ */
+class EventHandler implements EventListener {
+ private static final Logger log = LoggerFactory.getLogger(EventListener.class);
+ private RestconfDiscoveryNode node;
+
+ public EventHandler(RestconfDiscoveryNode node) {
+ this.node = node;
+ }
+
+ @Override
+ public void onEvent(InboundEvent event) {
+ String payload = event.readData();
+ if (!node.eventQueue().offer(payload)) {
+ log.error("Unable to process event {} as processing queue is full", payload);
+ }
+ }
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/restconfdiscovery/EventProcessor.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/restconfdiscovery/EventProcessor.java
new file mode 100644
index 000000000..4f28072d3
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/restconfdiscovery/EventProcessor.java
@@ -0,0 +1,76 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Huawei Technologies Co., Ltd. All rights reserved.
+ *
+ * Modifications Copyright © 2018 IBM
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.restconfdiscovery;
+
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.slf4j.Logger;
+
+import java.util.Map;
+
+import static org.onap.ccsdk.sli.plugins.restapicall.JsonParser.convertToProperties;
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Processes the events from event queue and executes callback DG.
+ */
+class EventProcessor implements Runnable {
+
+ private static final Logger log = getLogger(EventProcessor.class);
+ private RestconfDiscoveryNode node;
+
+ private static final String EVENT_SUBSCRIPTION_ID = "notification." +
+ "push-change-update.subscription-id";
+
+ public EventProcessor(RestconfDiscoveryNode node) {
+ this.node = node;
+ }
+
+ @Override
+ public void run() {
+ while(true) {
+ try {
+ String payload = node.eventQueue().take();
+ Map<String, String> param = convertToProperties(payload);
+ String id = param.get(EVENT_SUBSCRIPTION_ID);
+ SubscriptionInfo info = node.subscriptionInfoMap().get(id);
+ if (info != null) {
+ SvcLogicContext ctx = setContext(param);
+ SvcLogicGraphInfo callbackDG = info.callBackDG();
+ callbackDG.executeGraph(ctx);
+ }
+ } catch (InterruptedException | SvcLogicException e) {
+ log.error("Interrupted!", e);
+ Thread.currentThread().interrupt();
+ }
+ }
+ }
+
+ private SvcLogicContext setContext(Map<String, String> param) {
+ SvcLogicContext ctx = new SvcLogicContext();
+ for (Map.Entry<String, String> entry : param.entrySet()) {
+ ctx.setAttribute(entry.getKey(), entry.getValue());
+ }
+ return ctx;
+ }
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/restconfdiscovery/RestconfDiscoveryNode.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/restconfdiscovery/RestconfDiscoveryNode.java
new file mode 100644
index 000000000..cf69d7a3c
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/restconfdiscovery/RestconfDiscoveryNode.java
@@ -0,0 +1,310 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Huawei Technologies Co., Ltd. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.restconfdiscovery;
+
+import org.glassfish.jersey.media.sse.EventSource;
+import org.glassfish.jersey.media.sse.SseFeature;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.plugins.restapicall.Parameters;
+import org.onap.ccsdk.sli.plugins.restapicall.RestapiCallNode;
+import org.onap.ccsdk.sli.plugins.restconfapicall.RestconfApiCallNode;
+import org.slf4j.Logger;
+
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
+import javax.ws.rs.client.Client;
+import javax.ws.rs.client.ClientBuilder;
+import javax.ws.rs.client.WebTarget;
+import java.security.KeyManagementException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.LinkedBlockingQueue;
+
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Representation of a plugin to subscribe for notification and then
+ * to handle the received notifications.
+ */
+public class RestconfDiscoveryNode implements SvcLogicDiscoveryPlugin {
+
+ private static final Logger log = getLogger(RestconfDiscoveryNode.class);
+
+ private ExecutorService executor = Executors.newCachedThreadPool();
+ private Map<String, PersistentConnection> runnableInfo = new ConcurrentHashMap<>();
+ private RestconfApiCallNode restconfApiCallNode;
+
+ private volatile Map<String, SubscriptionInfo> subscriptionInfoMap = new ConcurrentHashMap<>();
+ private volatile LinkedBlockingQueue<String> eventQueue = new LinkedBlockingQueue<>();
+
+ private static final String SUBSCRIBER_ID = "subscriberId";
+ private static final String RESPONSE_CODE = "response-code";
+ private static final String RESPONSE_PREFIX = "responsePrefix";
+ private static final String OUTPUT_IDENTIFIER = "ietf-subscribed-notif" +
+ "ications:establish-subscription.output.identifier";
+ private static final String RESPONSE_CODE_200 = "200";
+ private static final String SSE_URL = "sseConnectURL";
+
+ /**
+ * Creates an instance of RestconfDiscoveryNode and starts processing of
+ * event.
+ *
+ * @param r restconf api call node
+ */
+ public RestconfDiscoveryNode(RestconfApiCallNode r) {
+ this.restconfApiCallNode = r;
+ ExecutorService e = Executors.newFixedThreadPool(20);
+ EventProcessor p = new EventProcessor(this);
+ for (int i = 0; i < 20; ++i) {
+ e.execute(p);
+ }
+ }
+
+ @Override
+ public void establishSubscription(Map<String, String> paramMap,
+ SvcLogicContext ctx) throws SvcLogicException {
+ String subscriberId = paramMap.get(SUBSCRIBER_ID);
+ if (subscriberId == null) {
+ throw new SvcLogicException("Subscriber Id is null");
+ }
+
+ restconfApiCallNode.sendRequest(paramMap, ctx);
+
+ if (getResponseCode(paramMap.get(RESPONSE_PREFIX), ctx).equals(RESPONSE_CODE_200)) {
+ // TODO: save subscription id and subscriber in MYSQL
+
+ establishPersistentConnection(paramMap, ctx, subscriberId);
+ } else {
+ log.info("Failed to subscribe {}", subscriberId);
+ throw new SvcLogicException(ctx.getAttribute(RESPONSE_CODE));
+ }
+ }
+
+ @Override
+ public void modifySubscription(Map<String, String> paramMap, SvcLogicContext ctx) {
+ // TODO: to be implemented
+ }
+
+ @Override
+ public void deleteSubscription(Map<String, String> paramMap, SvcLogicContext ctx) {
+ String id = getSubscriptionId(paramMap.get(SUBSCRIBER_ID));
+ if (id != null) {
+ PersistentConnection conn = runnableInfo.get(id);
+ conn.terminate();
+ runnableInfo.remove(id);
+ subscriptionInfoMap.remove(id);
+ }
+ }
+
+ class PersistentConnection implements Runnable {
+ private String url;
+ private volatile boolean running = true;
+ private Map<String, String> paramMap;
+
+ PersistentConnection(String url, Map<String, String> paramMap) {
+ this.url = url;
+ this.paramMap = paramMap;
+ }
+
+ private void terminate() {
+ running = false;
+ }
+
+ @Override
+ public void run() {
+ Parameters p;
+ WebTarget target = null;
+ try {
+ RestapiCallNode restapi = restconfApiCallNode.getRestapiCallNode();
+ p = RestapiCallNode.getParameters(paramMap, new Parameters());
+ Client client = ignoreSslClient().register(SseFeature.class);
+ target = restapi.addAuthType(client, p).target(url);
+ } catch (SvcLogicException e) {
+ log.error("Exception occured!", e);
+ Thread.currentThread().interrupt();
+ }
+
+ target = addToken(target, paramMap.get("customHttpHeaders"));
+ EventSource eventSource = EventSource.target(target).build();
+ eventSource.register(new EventHandler(RestconfDiscoveryNode.this));
+ eventSource.open();
+ log.info("Connected to SSE source");
+ while (running) {
+ try {
+ log.info("SSE state " + eventSource.isOpen());
+ Thread.sleep(5000);
+ } catch (InterruptedException e) {
+ log.error("Interrupted!", e);
+ Thread.currentThread().interrupt();
+ }
+ }
+ eventSource.close();
+ log.info("Closed connection to SSE source");
+ }
+
+ private Client ignoreSslClient() {
+ SSLContext sslcontext = null;
+
+ try {
+ sslcontext = SSLContext.getInstance("TLS");
+ sslcontext.init(null, new TrustManager[]{new X509TrustManager() {
+ @Override
+ public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
+ }
+
+ @Override
+ public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
+ }
+
+ @Override
+ public X509Certificate[] getAcceptedIssuers() {
+ return new X509Certificate[0];
+ }
+ } }, new java.security.SecureRandom());
+ } catch (NoSuchAlgorithmException | KeyManagementException e) {
+ throw new IllegalStateException(e);
+ }
+
+ return ClientBuilder.newBuilder().sslContext(sslcontext).hostnameVerifier((s1, s2) -> true).build();
+ }
+ }
+
+ protected String getTokenId(String customHttpHeaders) {
+ if (customHttpHeaders.contains("=")) {
+ String[] s = customHttpHeaders.split("=");
+ return s[1];
+ }
+ return customHttpHeaders;
+ }
+
+ protected WebTarget addToken(WebTarget target, String customHttpHeaders) {
+ if (customHttpHeaders == null) {
+ return target;
+ }
+
+ return new AdditionalHeaderWebTarget(
+ target, getTokenId(customHttpHeaders));
+ }
+
+ /**
+ * Establishes a persistent between the client and server.
+ *
+ * @param paramMap input paramter map
+ * @param ctx service logic context
+ * @param subscriberId subscriber identifier
+ */
+ void establishPersistentConnection(Map<String, String> paramMap, SvcLogicContext ctx,
+ String subscriberId) {
+ String id = getOutputIdentifier(paramMap.get(RESPONSE_PREFIX), ctx);
+ SvcLogicGraphInfo callbackDG = new SvcLogicGraphInfo(paramMap.get("module"),
+ paramMap.get("rpc"),
+ paramMap.get("version"),
+ paramMap.get("mode"));
+ SubscriptionInfo info = new SubscriptionInfo();
+ info.callBackDG(callbackDG);
+ info.subscriptionId(id);
+ info.subscriberId(subscriberId);
+ subscriptionInfoMap.put(id, info);
+
+ String url = paramMap.get(SSE_URL);
+ PersistentConnection connection = new PersistentConnection(url, paramMap);
+ runnableInfo.put(id, connection);
+ executor.execute(connection);
+ }
+
+ /**
+ * Returns response code.
+ *
+ * @param prefix prefix given in input parameter
+ * @param ctx service logic context
+ * @return response code
+ */
+ String getResponseCode(String prefix, SvcLogicContext ctx) {
+ return ctx.getAttribute(getPrefix(prefix) + RESPONSE_CODE);
+ }
+
+ /**
+ * Returns subscription id from event.
+ *
+ * @param prefix prefix given in input parameter
+ * @param ctx service logic context
+ * @return subscription id from event
+ */
+ String getOutputIdentifier(String prefix, SvcLogicContext ctx) {
+ return ctx.getAttribute(getPrefix(prefix) + OUTPUT_IDENTIFIER);
+ }
+
+ private String getPrefix(String prefix) {
+ return prefix != null ? prefix + "." : "";
+ }
+
+ private String getSubscriptionId(String subscriberId) {
+ for (Map.Entry<String,SubscriptionInfo> entry
+ : subscriptionInfoMap.entrySet()) {
+ if (entry.getValue().subscriberId()
+ .equals(subscriberId)) {
+ return entry.getKey();
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Returns restconfApiCallNode.
+ *
+ * @return restconfApiCallNode
+ */
+ protected RestconfApiCallNode restconfapiCallNode() {
+ return restconfApiCallNode;
+ }
+
+ /**
+ * Sets restconfApiCallNode.
+ *
+ * @param node restconfApiCallNode
+ */
+ void restconfapiCallNode(RestconfApiCallNode node) {
+ restconfApiCallNode = node;
+ }
+
+ Map<String, SubscriptionInfo> subscriptionInfoMap() {
+ return subscriptionInfoMap;
+ }
+
+ void subscriptionInfoMap(Map<String, SubscriptionInfo> subscriptionInfoMap) {
+ this.subscriptionInfoMap = subscriptionInfoMap;
+ }
+
+ LinkedBlockingQueue<String> eventQueue() {
+ return eventQueue;
+ }
+
+ void eventQueue(LinkedBlockingQueue<String> eventQueue) {
+ this.eventQueue = eventQueue;
+ }
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/restconfdiscovery/SubscriptionInfo.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/restconfdiscovery/SubscriptionInfo.java
new file mode 100644
index 000000000..4ed3660ca
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/restconfdiscovery/SubscriptionInfo.java
@@ -0,0 +1,122 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Huawei Technologies Co., Ltd. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.restconfdiscovery;
+
+/**
+ * Holder to store information of subscription.
+ */
+public class SubscriptionInfo {
+ private String subscriptionId;
+ private String subscriberId;
+ private SvcLogicGraphInfo callbackDG;
+ private String yangFilePath;
+ private String filterUrl;
+
+ /**
+ * Returns callback DG.
+ *
+ * @return callback DG
+ */
+ public SvcLogicGraphInfo callBackDG() {
+ return callbackDG;
+ }
+
+ /**
+ * Sets callback DG.
+ *
+ * @param callbackDg callback DG
+ */
+ public void callBackDG(SvcLogicGraphInfo callbackDg) {
+ this.callbackDG = callbackDg;
+ }
+
+ /**
+ * Returns YANG file path.
+ *
+ * @return YANG file path
+ */
+ public String yangFilePath() {
+ return yangFilePath;
+ }
+
+ /**
+ * Sets YANG file path.
+ *
+ * @param yangFilePath yang file path
+ */
+ public void yangFilePath(String yangFilePath) {
+ this.yangFilePath = yangFilePath;
+ }
+
+ /**
+ * Returns filter URL.
+ *
+ * @return filter URL
+ */
+ public String filterUrl() {
+ return filterUrl;
+ }
+
+ /**
+ * Sets filter URL.
+ *
+ * @param filterUrl filter URL
+ */
+ public void filterUrl(String filterUrl) {
+ this.filterUrl = filterUrl;
+ }
+
+ /**
+ * Returns subscription Id.
+ *
+ * @return subscription Id
+ */
+ public String subscriptionId() {
+ return subscriptionId;
+ }
+
+ /**
+ * Sets subscription id.
+ *
+ * @param subscriptionId subscription id
+ */
+ public void subscriptionId(String subscriptionId) {
+ this.subscriptionId = subscriptionId;
+ }
+
+ /**
+ * Returns subscription Id.
+ *
+ * @return subscription Id
+ */
+ public String subscriberId() {
+ return subscriberId;
+ }
+
+ /**
+ * Sets subscriber id.
+ *
+ * @param subscriberId subscriber id
+ */
+ public void subscriberId(String subscriberId) {
+ this.subscriberId = subscriberId;
+ }
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/restconfdiscovery/SvcLogicDiscoveryPlugin.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/restconfdiscovery/SvcLogicDiscoveryPlugin.java
new file mode 100644
index 000000000..dfe8cd5b7
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/restconfdiscovery/SvcLogicDiscoveryPlugin.java
@@ -0,0 +1,110 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Huawei Technologies Co., Ltd. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.restconfdiscovery;
+
+import java.util.Map;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.core.sli.SvcLogicJavaPlugin;
+
+/**
+ * Abstraction of a plugin to enable discovery from DG.
+ */
+public interface SvcLogicDiscoveryPlugin extends SvcLogicJavaPlugin {
+
+ /**
+ * Allows directed graphs to establish a discovery subscription for a given subscriber.
+ * @param paramMap HashMap<String,String> of parameters passed by the DG to this function
+ * <table border="1">
+ * <thead><th>parameter</th><th>Mandatory/Optional</th><th>description</th><th>example values</th></thead>
+ * <tbody>
+ * <tr><td>templateDirName</td><td>Optional</td><td>full path to YANG directory that can be used to build a request</td><td>/sdncopt/bvc/resconfapi/test</td></tr>
+ * <tr><td>establishSubscriptionURL</td><td>Mandatory</td><td>url to establish connection with server</td><td>https://127.0.0.1:8181/restconf/operations/ietf-subscribed-notifications:establish-subscription</td></tr>
+ * <tr><td>sseConnectURL</td><td>Mandatory</td><td>url to setup SSE connection with server</td><td>https://127.0.0.1:8181/restconf/streams/yang-push-json</td></tr>
+ * <tr><td>callbackDG</td><td>Mandatory</td><td>callback DG to process the received notification</td><td>Resource-Discovery:handleSOTNTopology</td></tr>
+ * <tr><td>filterURL</td><td>Optional</td><td>url which needs to be subscribed, if null subscribe to all</td><td>http://example.com/sample-data/1.0</td></tr>
+ * <tr><td>subscriptionType</td><td>Optional</td><td>type of subscription, periodic or onDataChange</td><td>onDataChange</td></tr>
+ * <tr><td>updateFrequency</td><td>Optional</td><td>update frequency in milli seconds when subscription type is periodic</td><td>1000</td></tr>
+ * <tr><td>restapiUser</td><td>Optional</td><td>user name to use for http basic authentication</td><td>sdnc_ws</td></tr>
+ * <tr><td>restapiPassword</td><td>Optional</td><td>unencrypted password to use for http basic authentication</td><td>plain_password</td></tr>
+ * <tr><td>contentType</td><td>Optional</td><td>http content type to set in the http header</td><td>usually application/json or application/xml</td></tr>
+ * <tr><td>format</td><td>Optional</td><td>should match request body format</td><td>json or xml</td></tr>
+ * <tr><td>responsePrefix</td><td>Optional</td><td>location the notification response will be written to in context memory</td><td>tmp.restconfdiscovery.result</td></tr>
+ * <tr><td>skipSending</td><td>Optional</td><td></td><td>true or false</td></tr>
+ * <tr><td>convertResponse </td><td>Optional</td><td>whether the response should be converted</td><td>true or false</td></tr>
+ * <tr><td>customHttpHeaders</td><td>Optional</td><td>a list additional http headers to be passed in, follow the format in the example</td><td>X-CSI-MessageId=messageId,headerFieldName=headerFieldValue</td></tr>
+ * <tr><td>dumpHeaders</td><td>Optional</td><td>when true writes http header content to context memory</td><td>true or false</td></tr>
+ * </tbody>
+ * </table>
+ * @param ctx Reference to context memory
+ * @throws SvcLogicException
+ * @since 11.0.2
+ * @see String#split(String, int)
+ */
+ void establishSubscription(Map<String, String> paramMap, SvcLogicContext ctx) throws SvcLogicException;
+
+ /**
+ * Allows directed graphs to modify a discovery subscription for a given subscriber.
+ * @param paramMap HashMap<String,String> of parameters passed by the DG to this function
+ * <table border="1">
+ * <thead><th>parameter</th><th>Mandatory/Optional</th><th>description</th><th>example values</th></thead>
+ * <tbody>
+ * <tr><td>subscriberId</td><td>Mandatory</td><td>subscription subscriber's identifier</td><td>topologyId/1111</td></tr>
+ * <tr><td>templateDirName</td><td>Optional</td><td>full path to YANG directory that can be used to build a request</td><td>/sdncopt/bvc/resconfapi/test</td></tr>
+ * <tr><td>establishSubscriptionURL</td><td>Mandatory</td><td>url to establish connection with server</td><td>https://127.0.0.1:8181/restconf/operations/ietf-subscribed-notifications:establish-subscription</td></tr>
+ * <tr><td>sseConnectURL</td><td>Mandatory</td><td>url to setup SSE connection with server</td><td>https://127.0.0.1:8181/restconf/streams/yang-push-json</td></tr>
+ * <tr><td>callbackDG</td><td>Mandatory</td><td>callback DG to process the received notification</td><td>Resource-Discovery:handleSOTNTopology</td></tr>
+ * <tr><td>filterURL</td><td>Optional</td><td>url filter list which needs to be subscribed, if null subscribe to all</td><td>http://example.com/sample-data/1.0</td></tr>
+ * <tr><td>subscriptionType</td><td>Optional</td><td>type of subscription, periodic or onDataChange</td><td>onDataChange</td></tr>
+ * <tr><td>updateFrequency</td><td>Optional</td><td>update frequency in milli seconds when subscription type is periodic</td><td>1000</td></tr>
+ * <tr><td>restapiUser</td><td>Optional</td><td>user name to use for http basic authentication</td><td>sdnc_ws</td></tr>
+ * <tr><td>restapiPassword</td><td>Optional</td><td>unencrypted password to use for http basic authentication</td><td>plain_password</td></tr>
+ * <tr><td>contentType</td><td>Optional</td><td>http content type to set in the http header</td><td>usually application/json or application/xml</td></tr>
+ * <tr><td>format</td><td>Optional</td><td>should match request body format</td><td>json or xml</td></tr>
+ * <tr><td>responsePrefix</td><td>Optional</td><td>location the notification response will be written to in context memory</td><td>tmp.restconfdiscovery.result</td></tr>
+ * <tr><td>skipSending</td><td>Optional</td><td></td><td>true or false</td></tr>
+ * <tr><td>convertResponse </td><td>Optional</td><td>whether the response should be converted</td><td>true or false</td></tr>
+ * <tr><td>customHttpHeaders</td><td>Optional</td><td>a list additional http headers to be passed in, follow the format in the example</td><td>X-CSI-MessageId=messageId,headerFieldName=headerFieldValue</td></tr>
+ * <tr><td>dumpHeaders</td><td>Optional</td><td>when true writes http header content to context memory</td><td>true or false</td></tr>
+ * </tbody>
+ * </table>
+ * @param ctx Reference to context memory
+ * @throws SvcLogicException
+ * @since 11.0.2
+ * @see String#split(String, int)
+ */
+ void modifySubscription(Map<String, String> paramMap, SvcLogicContext ctx);
+
+ /**
+ * Allows directed graphs to delete the discovery subscription for a given subscriber.
+ * @param paramMap HashMap<String,String> of parameters passed by the DG to this function
+ * <table border="1">
+ * <thead><th>parameter</th><th>Mandatory/Optional</th><th>description</th><th>example values</th></thead>
+ * <tbody>
+ * <tr><td>subscriberId</td><td>Mandatory</td><td>subscription subscriber's identifier</td><td>topologyId/1111</td></tr>
+ * </tbody>
+ * </table>
+ * @param ctx Reference to context memory
+ * @throws SvcLogicException
+ */
+ void deleteSubscription(Map<String, String> paramMap, SvcLogicContext ctx);
+
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/restconfdiscovery/SvcLogicGraphInfo.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/restconfdiscovery/SvcLogicGraphInfo.java
new file mode 100644
index 000000000..1cc6261ab
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/restconfdiscovery/SvcLogicGraphInfo.java
@@ -0,0 +1,178 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Huawei Technologies Co., Ltd. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.restconfdiscovery;
+
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.core.sli.SvcLogicGraph;
+import org.onap.ccsdk.sli.core.sli.SvcLogicStore;
+import org.onap.ccsdk.sli.core.sli.provider.SvcLogicService;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.ServiceReference;
+
+/**
+ * Holder to store callback directed graph info.
+ */
+class SvcLogicGraphInfo {
+ private String module;
+ private String rpc;
+ private String mode;
+ private String version;
+
+ /**
+ * Creates an instance of SvcLogicGraphInfo.
+ *
+ * @param module module name of callback DG
+ * @param rpc rpc name of callback DG
+ * @param mode mode of callback DG
+ * @param version version of callback DG
+ */
+ public SvcLogicGraphInfo(String module, String rpc, String mode, String version) {
+ this.module = module;
+ this.rpc = rpc;
+ this.mode = mode;
+ this.version = version;
+ }
+
+ public SvcLogicGraphInfo() {}
+
+ /**
+ * Returns module name of callback DG.
+ *
+ * @return module name of callback DG
+ */
+ public String module() {
+ return module;
+ }
+
+ /**
+ * Sets module of callback DG.
+ *
+ * @param module module name of the DG
+ */
+ public void module(String module) {
+ this.module = module;
+ }
+
+ /**
+ * Returns rpc of callback DG.
+ *
+ * @return rpc of callback DG
+ */
+ public String rpc() {
+ return rpc;
+ }
+
+ /**
+ * Sets rpc of callback DG.
+ *
+ * @param rpc rpc attribute of the DG
+ */
+ public void rpc(String rpc) {
+ this.rpc = rpc;
+ }
+
+ /**
+ * Returns mode of callback DG.
+ *
+ * @return mode of callback DG
+ */
+ public String mode() {
+ return mode;
+ }
+
+ /**
+ * Sets mode of DG.
+ *
+ * @param mode mode of the DG
+ */
+ public void mode(String mode) {
+ this.mode = mode;
+ }
+
+ /**
+ * Returns version of callback DG.
+ *
+ * @return version of callback DG
+ */
+ public String version() {
+ return version;
+ }
+
+ /**
+ * Sets version of DG.
+ *
+ * @param version version of the DG
+ */
+ public void version(String version) {
+ this.version = version;
+ }
+
+ /**
+ * Executes call back DG.
+ *
+ * @param ctx service logic context
+ * @throws SvcLogicException service logic error
+ */
+ public void executeGraph(SvcLogicContext ctx) throws SvcLogicException {
+ SvcLogicService service = findSvcLogicService();
+ if (service == null) {
+ throw new SvcLogicException("\"Could not get SvcLogicService reference\"");
+ }
+
+ SvcLogicStore store = service.getStore();
+ if (store != null) {
+ SvcLogicGraph subGraph = store.fetch(module, rpc, mode, version);
+ if (subGraph != null) {
+ ctx.setAttribute("subGraph", subGraph.toString());
+ service.execute(subGraph, ctx);
+ } else {
+ throw new SvcLogicException("Failed to call child [" + module +
+ "," + rpc + "," + version +
+ "," + mode + "] because" +
+ " the" + " graph could" +
+ " not be found");
+ }
+ } else {
+ throw new SvcLogicException("\"Could not get SvcLogicStore reference\"");
+ }
+ }
+
+ private static SvcLogicService findSvcLogicService() throws SvcLogicException {
+ Bundle bundle = FrameworkUtil.getBundle(SvcLogicService.class);
+ if (bundle == null) {
+ throw new SvcLogicException("Cannot find bundle reference for "
+ + SvcLogicService.NAME);
+ }
+
+ BundleContext bctx = bundle.getBundleContext();
+ ServiceReference<SvcLogicService> sref = bctx.getServiceReference(
+ SvcLogicService.class);
+ if (sref != null) {
+ return bctx.getService(sref);
+ } else {
+ throw new SvcLogicException("Cannot find service reference for "
+ + SvcLogicService.NAME);
+ }
+ }
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/Annotation.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/Annotation.java
new file mode 100644
index 000000000..185f70ba0
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/Annotation.java
@@ -0,0 +1,66 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Huawei Technologies Co., Ltd. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.yangserializers.dfserializer;
+
+/**
+ * Representation of an entity that represents annotated attribute.
+ */
+public class Annotation {
+
+ /**
+ * Name of the annotation.
+ */
+ private String name;
+
+ /**
+ * Value of the annotation.
+ */
+ private String value;
+
+ /**
+ * Creates an instance of annotation.
+ *
+ * @param n annotation name
+ * @param v annotation value
+ */
+ public Annotation(String n, String v) {
+ name = n;
+ value = v;
+ }
+
+ /**
+ * Returns name of annotation.
+ *
+ * @return name of annotation
+ */
+ public String name() {
+ return name;
+ }
+
+ /**
+ * Returns value of annotation.
+ *
+ * @return value of annotation
+ */
+ public String value() {
+ return value;
+ }
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DataFormat.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DataFormat.java
new file mode 100644
index 000000000..c692f1dd2
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DataFormat.java
@@ -0,0 +1,37 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Huawei Technologies Co., Ltd. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.yangserializers.dfserializer;
+
+/**
+ * Representation of data format.
+ */
+public enum DataFormat {
+
+ /**
+ * XML data format.
+ */
+ XML,
+
+ /**
+ * JSON data format.
+ */
+ JSON
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DataFormatSerializer.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DataFormatSerializer.java
new file mode 100644
index 000000000..cab64391a
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DataFormatSerializer.java
@@ -0,0 +1,94 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Huawei Technologies Co., Ltd. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.yangserializers.dfserializer;
+
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Abstraction of serializer to encode/decode context memory parameters
+ * to/from specified data format.
+ */
+public abstract class DataFormatSerializer {
+
+ /**
+ * Data format type of the serializer.
+ */
+ private DataFormat dataFormat;
+
+ /**
+ * Data format serializer context.
+ */
+ private DataFormatSerializerContext serializerContext;
+
+ /**
+ * Creates an instance of data format serializer.
+ *
+ * @param d type of data format
+ * @param s data format serializer context
+ */
+ protected DataFormatSerializer(DataFormat d,
+ DataFormatSerializerContext s) {
+ this.dataFormat = d;
+ this.serializerContext = s;
+ }
+
+ /**
+ * Encodes context memory parameters to data format.
+ *
+ * @param param context memory parameter
+ * @param annotations annotations
+ * @return data format body
+ * @throws SvcLogicException when serialization fails
+ */
+ public abstract String encode(Map<String, String> param,
+ Map<String, List<Annotation>> annotations) throws SvcLogicException;
+
+ /**
+ * Decodes data format body to context memory parameters.
+ *
+ * @param dataFormatBody abstract node
+ * @return context memory parameters
+ * @throws SvcLogicException when serialization fails
+ */
+ public abstract Map<String, String> decode(String dataFormatBody)
+ throws SvcLogicException;
+
+ /**
+ * Returns data format serializer context.
+ *
+ * @return data format serializer context
+ */
+ public DataFormatSerializerContext serializerContext() {
+ return serializerContext;
+ }
+
+ /**
+ * Returns supported data format.
+ *
+ * @return supported data format
+ */
+ public DataFormat dataFormat() {
+ return dataFormat;
+ }
+} \ No newline at end of file
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DataFormatSerializerContext.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DataFormatSerializerContext.java
new file mode 100644
index 000000000..919e82af3
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DataFormatSerializerContext.java
@@ -0,0 +1,104 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Huawei Technologies Co., Ltd. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.yangserializers.dfserializer;
+
+import org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.PropertiesNodeSerializer;
+
+import java.util.Map;
+
+/**
+ * Abstraction of data format serializer context.
+ */
+public class DataFormatSerializerContext {
+
+ /**
+ * Data format listener.
+ */
+ private Listener listener;
+
+ /**
+ * URI corresponding to the instance identifier.
+ */
+ private String uri;
+
+ /**
+ * Protocol annotation.
+ */
+ private Map<String, String> protocolAnnotation;
+
+ /**
+ * Properties node serializer.
+ */
+ private PropertiesNodeSerializer propNodeSerializer;
+
+ /**
+ * Creates an instance of data format serializer context.
+ *
+ * @param l data format listener
+ * @param u URI corresponding to instance identifier
+ * @param p protocol annotations
+ * @param s properties node serializer
+ */
+ public DataFormatSerializerContext(Listener l, String u,
+ Map<String, String> p,
+ PropertiesNodeSerializer s) {
+ listener = l;
+ uri = u;
+ protocolAnnotation = p;
+ propNodeSerializer = s;
+ }
+
+ /**
+ * Returns the data format listener.
+ *
+ * @return data format listener
+ */
+ public Listener listener() {
+ return listener;
+ }
+
+ /**
+ * Returns the URI.
+ *
+ * @return URI
+ */
+ public String uri() {
+ return uri;
+ }
+
+ /**
+ * Returns the protocol annotations.
+ *
+ * @return protocol annotations
+ */
+ public Map<String, String> getProtocolAnnotation() {
+ return protocolAnnotation;
+ }
+
+ /**
+ * Returns the properties node serializer.
+ *
+ * @return properties node serializer
+ */
+ public PropertiesNodeSerializer getPropNodeSerializer() {
+ return propNodeSerializer;
+ }
+} \ No newline at end of file
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DefaultJsonListener.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DefaultJsonListener.java
new file mode 100644
index 000000000..45317522a
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DefaultJsonListener.java
@@ -0,0 +1,145 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Huawei Technologies Co., Ltd. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.yangserializers.dfserializer;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.NodeType;
+
+import static java.lang.String.format;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DfSerializerUtil.NODE_TYPE_ERR;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.NodeType.MULTI_INSTANCE_LEAF_NODE;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.NodeType.MULTI_INSTANCE_NODE;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.NodeType.SINGLE_INSTANCE_LEAF_NODE;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.NodeType.SINGLE_INSTANCE_NODE;
+
+
+/**
+ * Representation of default implementation of JSON listener.
+ */
+public class DefaultJsonListener implements JsonListener {
+
+ /**
+ * Serializer helper to convert to properties node.
+ */
+ private SerializerHelper serializerHelper;
+
+ /**
+ * Name of the current JSON node.
+ */
+ private String name;
+
+ /**
+ * Module name of the current JSON node.
+ */
+ private String modName;
+
+ /**
+ * Value of the current JSON node.
+ */
+ private String value;
+
+ /**
+ * Value namespace of the current JSON node.
+ */
+ private String valueNs;
+
+ /**
+ * Creates an instance of default json listener with its serializer helper.
+ *
+ * @param serializerHelper serializer helper
+ */
+ public DefaultJsonListener(SerializerHelper serializerHelper) {
+ this.serializerHelper = serializerHelper;
+ }
+
+ @Override
+ public void enterJsonNode(String nodeName, JsonNode node,
+ NodeType nodeType) throws SvcLogicException {
+ getNodeName(nodeName, false);
+
+ switch (nodeType) {
+ case SINGLE_INSTANCE_LEAF_NODE:
+ getNodeName(node.asText(), true);
+ serializerHelper.addNode(name, modName, value, valueNs,
+ SINGLE_INSTANCE_LEAF_NODE);
+ break;
+
+ case MULTI_INSTANCE_LEAF_NODE:
+ getNodeName(node.asText(), true);
+ serializerHelper.addNode(name, modName, value, valueNs,
+ MULTI_INSTANCE_LEAF_NODE);
+ break;
+
+ case SINGLE_INSTANCE_NODE:
+ serializerHelper.addNode(name, modName, null, null,
+ SINGLE_INSTANCE_NODE);
+ break;
+
+ case MULTI_INSTANCE_NODE:
+ serializerHelper.addNode(name, modName, null, null,
+ MULTI_INSTANCE_NODE);
+ break;
+
+ default:
+ throw new SvcLogicException(format(NODE_TYPE_ERR,
+ nodeType.toString()));
+ }
+ }
+
+ @Override
+ public void exitJsonNode(JsonNode node) throws SvcLogicException {
+ serializerHelper.exitNode();
+ }
+
+ @Override
+ public SerializerHelper serializerHelper() {
+ return serializerHelper;
+ }
+
+ /**
+ * Parses the abstract JSON name and fills the node name and node
+ * namespace or value and value namespace of the current JSON node .
+ *
+ * @param abstractName full name value
+ * @param isVal if it is for value parsing
+ */
+ private void getNodeName(String abstractName, boolean isVal) {
+ String[] val = abstractName.split(":");
+ if (val.length == 2) {
+ if (isVal) {
+ valueNs = val[0];
+ value = val[1];
+ } else {
+ modName = val[0];
+ name = val[1];
+ }
+ } else {
+ if (isVal) {
+ value = val[0];
+ valueNs = null;
+ } else {
+ name = val[0];
+ modName = null;
+ }
+ }
+ }
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DefaultJsonWalker.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DefaultJsonWalker.java
new file mode 100644
index 000000000..47cb8b292
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DefaultJsonWalker.java
@@ -0,0 +1,141 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Huawei Technologies Co., Ltd. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.yangserializers.dfserializer;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.JsonNodeType;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.NodeType;
+
+import java.util.Iterator;
+import java.util.Map;
+
+import static com.fasterxml.jackson.databind.node.JsonNodeType.NUMBER;
+import static com.fasterxml.jackson.databind.node.JsonNodeType.STRING;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.NodeType.MULTI_INSTANCE_LEAF_NODE;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.NodeType.MULTI_INSTANCE_NODE;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.NodeType.SINGLE_INSTANCE_LEAF_NODE;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.NodeType.SINGLE_INSTANCE_NODE;
+
+/**
+ * Implementation of JSON walker to walk through the nodes and process it.
+ */
+public class DefaultJsonWalker implements JsonWalker {
+
+ @Override
+ public void walk(JsonListener listener, JsonNode jsonNode) throws
+ SvcLogicException {
+ Iterator<Map.Entry<String, JsonNode>> children = jsonNode.fields();
+ while (children.hasNext()) {
+ Map.Entry<String, JsonNode> child = children.next();
+ JsonNode value = child.getValue();
+ String key = child.getKey();
+ if (value.isArray()) {
+ processMultiNodes(key, value, listener);
+ } else {
+ processSingleNode(key, value, listener);
+ }
+ }
+ }
+
+ /**
+ * Processes single instance node or leaf, by adding the node to from
+ * JSON and walking through all its children recursively.
+ *
+ * @param key JSON name
+ * @param value JSON node
+ * @param listener JSON listener
+ * @throws SvcLogicException when processing the node fails
+ */
+ private void processSingleNode(String key, JsonNode value,
+ JsonListener listener)
+ throws SvcLogicException {
+ NodeType nodeType;
+ if (!value.isContainerNode()) {
+ nodeType = SINGLE_INSTANCE_LEAF_NODE;
+ } else {
+ nodeType = SINGLE_INSTANCE_NODE;
+ }
+ processNode(key, value, nodeType, listener);
+ }
+
+ /**
+ * Processes multi instance node or leaf, by adding the node to from JSON
+ * and walking through all its instance recursively.
+ *
+ * @param key JSON name
+ * @param value JSON node
+ * @param listener JSON listener
+ * @throws SvcLogicException when processing a single instance fails
+ */
+ private void processMultiNodes(String key, JsonNode value,
+ JsonListener listener)
+ throws SvcLogicException {
+ NodeType nodeType;
+ Iterator<JsonNode> multiNodes = value.elements();
+ while (multiNodes.hasNext()) {
+ if (isLeafListNode((ArrayNode) value)) {
+ nodeType = MULTI_INSTANCE_LEAF_NODE;
+ } else {
+ nodeType = MULTI_INSTANCE_NODE;
+ }
+ JsonNode multiNode = multiNodes.next();
+ processNode(key, multiNode, nodeType, listener);
+ }
+ }
+
+ /**
+ * Processes each node by first entering the JSON node through JSON
+ * listener, second a call back to walking the rest of the tree of the
+ * node and finally exiting the node.
+ *
+ * @param key JSON name
+ * @param node JSON node
+ * @param nodeType JSON node type
+ * @param listener JSON listener
+ * @throws SvcLogicException when entering a JSON node fails
+ */
+ private void processNode(String key, JsonNode node, NodeType nodeType,
+ JsonListener listener) throws SvcLogicException {
+ listener.enterJsonNode(key, node, nodeType);
+ walk(listener, node);
+ listener.exitJsonNode(node);
+ }
+
+ /**
+ * Returns true if the node corresponds to a leaf-list node; false
+ * otherwise.
+ *
+ * @param node JSON node
+ * @return true if node corresponds to leaf-list node; false otherwise
+ */
+ private boolean isLeafListNode(ArrayNode node) {
+ Iterator<JsonNode> children = node.elements();
+ while (children.hasNext()) {
+ JsonNodeType type = children.next().getNodeType();
+ if (type != STRING && type != NUMBER) {
+ return false;
+ }
+ }
+ return true;
+ }
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DefaultXmlListener.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DefaultXmlListener.java
new file mode 100644
index 000000000..03abf44fd
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DefaultXmlListener.java
@@ -0,0 +1,120 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Huawei Technologies Co., Ltd. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.yangserializers.dfserializer;
+
+import org.dom4j.Element;
+import org.dom4j.Namespace;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+
+import java.util.List;
+
+import static java.lang.String.format;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DfSerializerUtil.NODE_TYPE_ERR;
+
+/**
+ * Representation of default implementation of XML listener.
+ */
+public class DefaultXmlListener implements XmlListener {
+
+ /**
+ * Serializer helper to convert to properties node.
+ */
+ private SerializerHelper serializerHelper;
+
+ /**
+ * Creates an instance of default XML listener with its serializer helper.
+ *
+ * @param serializerHelper serializer helper
+ */
+ public DefaultXmlListener(SerializerHelper serializerHelper) {
+ this.serializerHelper = serializerHelper;
+ }
+
+ @Override
+ public void enterXmlElement(Element element, XmlNodeType nodeType)
+ throws SvcLogicException {
+ switch (nodeType) {
+ case TEXT_NODE:
+ serializerHelper.addNode(element.getName(),
+ element.getNamespace().getURI(),
+ element.getText(), null, null);
+ break;
+
+ case OBJECT_NODE:
+ List cont = element.content();
+ if (cont != null && cont.size() == 2 &&
+ isValueNsForLeaf(cont, element)) {
+ return;
+ }
+ serializerHelper.addNode(element.getName(),
+ element.getNamespace().getURI(),
+ null, null, null);
+ break;
+
+ default:
+ throw new SvcLogicException(format(NODE_TYPE_ERR,
+ nodeType.toString()));
+ }
+ }
+
+ /**
+ * Returns true if element has value namespace and adds the node to
+ * property tree; false otherwise.
+ *
+ * @param cont content of the element
+ * @param element element
+ * @return true if element has value namespace; false otherwise
+ * @throws SvcLogicException
+ */
+ private boolean isValueNsForLeaf(List cont, Element element)
+ throws SvcLogicException {
+ for (Object c : cont) {
+ if (c instanceof Namespace) {
+ String value = element.getText();
+ if (value != null) {
+ String[] val = value.split(":");
+ String valPrefix = val[0];
+ String actVal = val[1];
+ if (valPrefix != null && actVal != null &&
+ valPrefix.equals(((Namespace) c).getPrefix())) {
+ serializerHelper.addNode(
+ element.getName(),
+ element.getNamespace().getURI(),
+ actVal,
+ ((Namespace) c).getURI(), null);
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+
+ @Override
+ public void exitXmlElement(Element element) throws SvcLogicException {
+ serializerHelper.exitNode();
+ }
+
+ @Override
+ public SerializerHelper serializerHelper() {
+ return serializerHelper;
+ }
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DefaultXmlWalker.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DefaultXmlWalker.java
new file mode 100644
index 000000000..cdc713f31
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DefaultXmlWalker.java
@@ -0,0 +1,48 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Huawei Technologies Co., Ltd. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.yangserializers.dfserializer;
+
+import org.dom4j.Element;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+
+import java.util.Iterator;
+
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DfSerializerUtil.getXmlNodeType;
+
+/**
+ * Implementation of XML walker to walk through the nodes and process it.
+ */
+public class DefaultXmlWalker implements XmlWalker {
+
+ @Override
+ public void walk(XmlListener listener, Element xmlElement) throws
+ SvcLogicException {
+ listener.enterXmlElement(xmlElement, getXmlNodeType(xmlElement));
+ if (xmlElement.hasContent() && !xmlElement.isTextOnly()) {
+ Iterator i = xmlElement.elementIterator();
+ while (i.hasNext()) {
+ Element childElement = (Element) i.next();
+ walk(listener, childElement);
+ }
+ }
+ listener.exitXmlElement(xmlElement);
+ }
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DfListenerFactory.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DfListenerFactory.java
new file mode 100644
index 000000000..06a811e15
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DfListenerFactory.java
@@ -0,0 +1,87 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Huawei Technologies Co., Ltd. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.yangserializers.dfserializer;
+
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+
+import static java.lang.String.format;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DfSerializerUtil.FORMAT_ERR;
+
+/**
+ * Represents the data format listener factory which will return JSON or XML
+ * listener according to the serializer helper.
+ */
+public final class DfListenerFactory {
+
+ /**
+ * Creates a new DfListenerFactory.
+ */
+ private DfListenerFactory() {
+ }
+
+ /**
+ * Returns the instance of the data format listener factory.
+ *
+ * @return instance of the data format listener factory
+ */
+ public static DfListenerFactory instance() {
+ return DfListenerFactory.LazyHolder.INSTANCE;
+ }
+
+ /**
+ * Bill pugh singleton pattern. Instance will not be instantiated until
+ * the lazy holder class is loaded via a call to the instance of method
+ * below.
+ */
+ private static class LazyHolder {
+ private static final DfListenerFactory INSTANCE =
+ new DfListenerFactory();
+ }
+
+ /**
+ * Returns the data format listener by deciding it based on the format of
+ * the parameter.
+ *
+ * @param serHelper serializer helper
+ * @param params parameters
+ * @return data format listener
+ * @throws SvcLogicException when the data format type is wrong
+ */
+ public Listener getListener(SerializerHelper serHelper,
+ YangParameters params)
+ throws SvcLogicException {
+ Listener listener;
+ switch (params.format) {
+ case JSON:
+ listener = new DefaultJsonListener(serHelper);
+ break;
+
+ case XML:
+ listener = new DefaultXmlListener(serHelper);
+ break;
+
+ default:
+ throw new SvcLogicException(format(FORMAT_ERR,
+ params.format));
+ }
+ return listener;
+ }
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DfSerializerFactory.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DfSerializerFactory.java
new file mode 100644
index 000000000..4d95235e5
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DfSerializerFactory.java
@@ -0,0 +1,87 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Huawei Technologies Co., Ltd. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.yangserializers.dfserializer;
+
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+
+import static java.lang.String.format;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DfSerializerUtil.FORMAT_ERR;
+
+/**
+ * Represents the data format serializer factory which will return JSON or XML
+ * serializer according to the serializer context.
+ */
+public final class DfSerializerFactory {
+
+ /**
+ * Creates a new DfSerializerFactory.
+ */
+ private DfSerializerFactory() {
+ }
+
+ /**
+ * Returns the instance of the data format serializer factory.
+ *
+ * @return instance of the data format serializer factory
+ */
+ public static DfSerializerFactory instance() {
+ return DfSerializerFactory.LazyHolder.INSTANCE;
+ }
+
+ /**
+ * Bill pugh singleton pattern. Instance will not be instantiated until
+ * the lazy holder class is loaded via a call to the instance of method
+ * below.
+ */
+ private static class LazyHolder {
+ private static final DfSerializerFactory INSTANCE =
+ new DfSerializerFactory();
+ }
+
+ /**
+ * Returns the data format serializer by deciding it based on the format of
+ * the parameter.
+ *
+ * @param serCtx serializer context
+ * @param params parameters
+ * @return data format serializer
+ * @throws SvcLogicException when the data format type is wrong
+ */
+ public DataFormatSerializer getSerializer(DataFormatSerializerContext serCtx,
+ YangParameters params)
+ throws SvcLogicException {
+ DataFormatSerializer serializer;
+ switch (params.format) {
+ case JSON:
+ serializer = new JsonSerializer(serCtx);
+ break;
+
+ case XML:
+ serializer = new XmlSerializer(serCtx);
+ break;
+
+ default:
+ throw new SvcLogicException(format(FORMAT_ERR,
+ params.format));
+ }
+ return serializer;
+ }
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DfSerializerUtil.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DfSerializerUtil.java
new file mode 100644
index 000000000..707c29444
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DfSerializerUtil.java
@@ -0,0 +1,231 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Huawei Technologies Co., Ltd. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.yangserializers.dfserializer;
+
+import org.dom4j.Element;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.Namespace;
+import org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.PropertiesNode;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+import org.w3c.dom.Document;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+import java.io.IOException;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.Iterator;
+
+import static javax.xml.transform.OutputKeys.INDENT;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.XmlNodeType.OBJECT_NODE;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.XmlNodeType.TEXT_NODE;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.getRevision;
+
+/**
+ * Utilities for data format serializer.
+ */
+public final class DfSerializerUtil {
+
+ static final String JSON_WRITE_ERR = "Unable to write to JSON from " +
+ "properties.";
+
+ static final String NODE_TYPE_ERR = "The node type %s is not supported.";
+
+ static final String JSON_LIS_ERR = "The JSON serializer doesn't have " +
+ "JSON listener";
+
+ static final String XML_LIS_ERR = "The XML serializer doesn't have XML " +
+ "listener";
+
+ static final String PROP_NODE_ERR = "The property node doesn't have " +
+ "schema node bound to it.";
+
+ static final String DF_ERR = "Type mismatch for the node %s. The schema " +
+ "node does not match with the data format node type %s.";
+
+ static final String XML_PREFIX = "yangid";
+
+ private static final String YES = "yes";
+
+ private static final String INDENT_XMLNS = "{http://xml.apache" +
+ ".org/xslt}indent-amount";
+
+ private static final String XML_PARSE_ERR = "Unable to parse the xml to " +
+ "document : \n";
+
+ private static final String URI_ERR = "Unable to parse the URI";
+
+ /**
+ * Data format error message for unsupported types.
+ */
+ public static final String FORMAT_ERR = "Only JSON and XML formats are " +
+ "supported. %s is not supported";
+
+ /**
+ * UTF header message for XML data format message.
+ */
+ public static final String UTF_HEADER = "<?xml version=\"1.0\" " +
+ "encoding=\"UTF-8\"?>";
+
+ /**
+ * Error message when a JSON tree creation fails.
+ */
+ public static final String JSON_TREE_ERR = "Unable to form JSON tree " +
+ "object from the JSON body provided.";
+
+ /**
+ * Error message when a XML tree creation fails.
+ */
+ public static final String XML_TREE_ERR = "Unable to form XML tree object" +
+ " from the XML body provided.";
+
+ //No instantiation.
+ private DfSerializerUtil() {
+ }
+
+ /**
+ * Returns the writer which contains the pretty formatted XML string.
+ *
+ * @param input input XML
+ * @param indent indentation level
+ * @return writer with XML
+ * @throws SvcLogicException when transformation of source fails
+ */
+ public static Writer getXmlWriter(String input, String indent)
+ throws SvcLogicException {
+ try {
+ Transformer transformer = TransformerFactory.newInstance()
+ .newTransformer();
+ transformer.setOutputProperty(INDENT, YES);
+ transformer.setOutputProperty(INDENT_XMLNS, indent);
+ StreamResult result = new StreamResult(new StringWriter());
+ DOMSource source = new DOMSource(parseXml(input));
+ transformer.transform(source, result);
+ return result.getWriter();
+ } catch (TransformerException e) {
+ throw new SvcLogicException(XML_PARSE_ERR + input, e);
+ }
+ }
+
+ /**
+ * Parses the XML and converts it into dom document which can be used for
+ * formatting the XML.
+ *
+ * @param in input XML
+ * @return dom document of XML
+ * @throws SvcLogicException when document building fails
+ */
+ private static Document parseXml(String in) throws SvcLogicException {
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ DocumentBuilder db;
+ try {
+ db = dbf.newDocumentBuilder();
+ InputSource is = new InputSource(new StringReader(in));
+ return db.parse(is);
+ } catch (SAXException | IOException | ParserConfigurationException e) {
+ throw new SvcLogicException(XML_PARSE_ERR + in, e);
+ }
+ }
+
+ /**
+ * Returns the resolved namespace object from the input received from the
+ * abstract data format.
+ *
+ * @param mName module name
+ * @param mUri module URI
+ * @param ctx schema context
+ * @param parent parent properties node
+ * @return namespace
+ * @throws SvcLogicException when resolving namespace fails
+ */
+ static Namespace getResolvedNamespace(String mName, String mUri,
+ SchemaContext ctx,
+ PropertiesNode parent)
+ throws SvcLogicException {
+ if (mName == null && mUri == null) {
+ Namespace parentNs = parent.namespace();
+ return new Namespace(parentNs.moduleName(), parentNs.moduleNs(),
+ parentNs.revision());
+ }
+
+ Iterator<Module> it;
+ Module mod;
+ if (mName != null) {
+ it = ctx.findModules(mName).iterator();
+ } else {
+ URI modUri = null;
+ try {
+ modUri = new URI(mUri);
+ } catch (URISyntaxException e) {
+ throw new SvcLogicException(URI_ERR, e);
+ }
+ it = ctx.findModules(modUri).iterator();
+ }
+
+ if (!it.hasNext()) {
+ return null;
+ }
+ mod = it.next();
+
+ return new Namespace(mod.getName(), mod.getQNameModule().getNamespace(),
+ getRevision(mod.getRevision()));
+ }
+
+ /**
+ * Returns the node type of a XML element.
+ *
+ * @param element XML element
+ * @return node type of the XML element
+ */
+ static XmlNodeType getXmlNodeType(Element element) {
+ Element newElement = element.createCopy();
+ newElement.remove(element.getNamespace());
+ return newElement.hasContent() && newElement.isTextOnly() ?
+ TEXT_NODE : OBJECT_NODE;
+ }
+
+ /**
+ * Resolves the super type to the base type from type definition.
+ *
+ * @param type super type
+ * @return base type definition
+ */
+ static TypeDefinition<?> resolveBaseTypeFrom(TypeDefinition<?> type) {
+ TypeDefinition superType = type;
+ while (superType.getBaseType() != null) {
+ superType = superType.getBaseType();
+ }
+ return superType;
+ }
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/JsonListener.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/JsonListener.java
new file mode 100644
index 000000000..89fd4c8c8
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/JsonListener.java
@@ -0,0 +1,55 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Huawei Technologies Co., Ltd. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.yangserializers.dfserializer;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.NodeType;
+
+/**
+ * Abstraction of an entity which provides call back methods, which in turn
+ * are called by JSON walker while walking the JSON tree. This interface
+ * needs to be implemented by protocol, implementing listener based call
+ * while doing JSON walk.
+ */
+public interface JsonListener extends Listener {
+
+ /**
+ * Call back invoked during JSON node entry. All other related
+ * information can be obtained from the JSON node.
+ *
+ * @param nodeName JSON node name
+ * @param node JSON node
+ * @param nodeType JSON node type
+ * @throws SvcLogicException when node type is of wrong format
+ */
+ void enterJsonNode(String nodeName, JsonNode node, NodeType nodeType)
+ throws SvcLogicException;
+
+ /**
+ * Call back invoked during JSON node exit. All the related information
+ * can be obtained from the JSON node.
+ *
+ * @param node JSON node
+ * @throws SvcLogicException when JSON node exit doesn't happen
+ */
+ void exitJsonNode(JsonNode node) throws SvcLogicException;
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/JsonSerializer.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/JsonSerializer.java
new file mode 100644
index 000000000..91adb8126
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/JsonSerializer.java
@@ -0,0 +1,91 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Huawei Technologies Co., Ltd. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.yangserializers.dfserializer;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.List;
+import java.util.Map;
+
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.DefaultPropertiesNodeWalker;
+import org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.PropertiesNode;
+import org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.PropertiesNodeWalker;
+
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DataFormat.JSON;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DfSerializerUtil.JSON_LIS_ERR;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DfSerializerUtil.JSON_TREE_ERR;
+
+/**
+ * Representation of JSON serializer which encodes properties to JSON and
+ * decodes properties from JSON with the data format serializer.
+ */
+public class JsonSerializer extends DataFormatSerializer {
+
+ /**
+ * Creates an instance of data format serializer.
+ *
+ * @param serializerContext data format serializer context
+ */
+ protected JsonSerializer(DataFormatSerializerContext serializerContext) {
+ super(JSON, serializerContext);
+ }
+
+ @Override
+ public String encode(Map<String, String> param,
+ Map<String, List<Annotation>> annotations)
+ throws SvcLogicException {
+ PropertiesNode propNode = serializerContext().getPropNodeSerializer()
+ .encode(param);
+ PropertiesNodeWalker nodeWalker = new DefaultPropertiesNodeWalker<>();
+ PropertiesNodeJsonListener jsonLis = new PropertiesNodeJsonListener();
+ nodeWalker.walk(jsonLis, propNode);
+ Writer writer = jsonLis.getWriter();
+ return writer.toString();
+ }
+
+ @Override
+ public Map<String, String> decode(String dataFormatBody)
+ throws SvcLogicException {
+ if (!(serializerContext().listener() instanceof JsonListener)) {
+ throw new SvcLogicException(JSON_LIS_ERR);
+ }
+
+ JsonListener listener = (JsonListener) serializerContext().listener();
+ JsonWalker walker = new DefaultJsonWalker();
+ ObjectMapper mapper = new ObjectMapper();
+ JsonNode jsonNode;
+
+ try {
+ jsonNode = mapper.readTree(dataFormatBody);
+ } catch (IOException e) {
+ throw new SvcLogicException(JSON_TREE_ERR, e);
+ }
+
+ walker.walk(listener, jsonNode);
+
+ return serializerContext().getPropNodeSerializer().decode(
+ listener.serializerHelper().getPropertiesNode());
+ }
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/JsonWalker.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/JsonWalker.java
new file mode 100644
index 000000000..588070a12
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/JsonWalker.java
@@ -0,0 +1,44 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Huawei Technologies Co., Ltd. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.yangserializers.dfserializer;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+
+/**
+ * Abstraction of an entity which provides interface for JSON walk. This
+ * interface serves as a common tool for anyone who needs to parse the JSON
+ * node with depth-first algorithm.
+ */
+public interface JsonWalker {
+
+ /**
+ * Walks the JSON data tree. Protocols implement JSON listener service
+ * and walks the JSON tree with input as implemented object. JSON walker
+ * provides call back to the implemented methods.
+ *
+ * @param listener JSON listener implemented by the protocol
+ * @param jsonNode root node of the JSON data tree
+ * @throws SvcLogicException when walking the JSON node fails
+ */
+ void walk(JsonListener listener, JsonNode jsonNode)
+ throws SvcLogicException;
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/Listener.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/Listener.java
new file mode 100644
index 000000000..e5812dbb7
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/Listener.java
@@ -0,0 +1,34 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Huawei Technologies Co., Ltd. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.yangserializers.dfserializer;
+
+/**
+ * Abstraction of listener.
+ */
+public interface Listener {
+
+ /**
+ * Returns serializer helper for this listener.
+ *
+ * @return serializer helper
+ */
+ SerializerHelper serializerHelper();
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/MdsalSerializerHelper.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/MdsalSerializerHelper.java
new file mode 100644
index 000000000..1fd0d2dee
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/MdsalSerializerHelper.java
@@ -0,0 +1,297 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Huawei Technologies Co., Ltd. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.yangserializers.dfserializer;
+
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.Namespace;
+import org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.NodeType;
+import org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.PropertiesNode;
+import org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.RootNode;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.Revision;
+import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.LeafListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.LeafSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.ListSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaNode;
+import org.opendaylight.yangtools.yang.model.api.TypeDefinition;
+import org.opendaylight.yangtools.yang.model.api.type.IdentityrefTypeDefinition;
+
+import java.util.Deque;
+
+import static java.lang.String.format;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DfSerializerUtil.DF_ERR;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DfSerializerUtil.NODE_TYPE_ERR;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DfSerializerUtil.PROP_NODE_ERR;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DfSerializerUtil.getResolvedNamespace;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DfSerializerUtil.resolveBaseTypeFrom;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.getRevision;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.NodeType.MULTI_INSTANCE_HOLDER_NODE;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.NodeType.MULTI_INSTANCE_LEAF_HOLDER_NODE;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.NodeType.MULTI_INSTANCE_LEAF_NODE;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.NodeType.MULTI_INSTANCE_NODE;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.NodeType.SINGLE_INSTANCE_LEAF_NODE;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.NodeType.SINGLE_INSTANCE_NODE;
+import static org.opendaylight.yangtools.yang.data.impl.schema.SchemaUtils.findDataChildSchemaByQName;
+import static org.opendaylight.yangtools.yang.data.impl.schema.SchemaUtils.findSchemaForChild;
+import static org.opendaylight.yangtools.yang.data.util.ParserStreamUtils.findSchemaNodeByNameAndNamespace;
+
+/**
+ * Representation of MDSAL based serializer helper, which adds properties
+ * node to the properties tree based on its types.
+ */
+public class MdsalSerializerHelper extends SerializerHelper<SchemaNode, SchemaContext> {
+
+ /**
+ * Current properties node.
+ */
+ private PropertiesNode propNode;
+
+ /**
+ * Current schema node.
+ */
+ private SchemaNode curSchemaNode;
+
+
+ /**
+ * Creates MDSAL serializer helper with root schema node, schema context
+ * and URI.
+ *
+ * @param n schema node of the URI's last node
+ * @param c schema context
+ * @param u URI of the request
+ */
+ public MdsalSerializerHelper(SchemaNode n, SchemaContext c,
+ String u) {
+ super(n, c, u);
+ Namespace ns = new Namespace(n.getQName().getLocalName(),
+ n.getQName().getNamespace(),
+ getRevision(n.getQName().getRevision()));
+ propNode = new RootNode<>(n.getQName().getLocalName(), ns,
+ getSchemaNode(), u);
+ curSchemaNode = getSchemaNode();
+ }
+
+ @Override
+ protected SchemaNode getSchemaNode() {
+ return schemaNode;
+ }
+
+ @Override
+ protected SchemaContext getSchemaCtx() {
+ return schemaCtx;
+ }
+
+ @Override
+ protected SchemaNode getCurSchema() {
+ return curSchemaNode;
+ }
+
+ @Override
+ protected void addNode(String name, String nameSpace, String value,
+ String valNameSpace, NodeType type)
+ throws SvcLogicException {
+ Namespace ns;
+ if (type == null) {
+ ns = getResolvedNamespace(null, nameSpace,
+ getSchemaCtx(), propNode);
+ } else {
+ ns = getResolvedNamespace(nameSpace, null,
+ getSchemaCtx(), propNode);
+ }
+ if (isChildPresent(name, ns)) {
+ addNodeToProperty(name, ns, value, valNameSpace, type);
+ } else {
+ throw new SvcLogicException(format(
+ "Unable to add the node %s", name));
+ }
+ }
+
+ @Override
+ protected void exitNode() throws SvcLogicException {
+ propNode = propNode.parent();
+ if (propNode != null) {
+ NodeType type = propNode.nodeType();
+ if (type == MULTI_INSTANCE_HOLDER_NODE ||
+ type == MULTI_INSTANCE_LEAF_HOLDER_NODE) {
+ propNode = propNode.parent();
+ }
+ }
+ if (propNode == null || propNode.appInfo() == null
+ || !(propNode.appInfo() instanceof SchemaNode)) {
+ throw new SvcLogicException(PROP_NODE_ERR);
+ }
+ curSchemaNode = (SchemaNode) propNode.appInfo();
+ }
+
+ @Override
+ protected PropertiesNode getPropertiesNode() {
+ return propNode;
+ }
+
+ /**
+ * Adds the node to property node based on the type of the schema node,
+ * which is decided based on the name and namespace of the input
+ * information.
+ *
+ * @param name name of the node
+ * @param ns namespace of the node
+ * @param value value of the node if its a leaf/leaf-list
+ * @param valNamespace namespace of the value
+ * @param type type of the node
+ * @throws SvcLogicException when adding child fails
+ */
+ private void addNodeToProperty(String name, Namespace ns, String value,
+ String valNamespace, NodeType type)
+ throws SvcLogicException {
+ Namespace valueNs;
+ if (type != null) {
+ validateNodeType(type);
+ }
+ if (curSchemaNode instanceof LeafSchemaNode) {
+ valueNs = getValueNs(curSchemaNode, valNamespace, type);
+ propNode = propNode.addChild(name, ns,
+ SINGLE_INSTANCE_LEAF_NODE,
+ value, valueNs, curSchemaNode);
+ } else if (curSchemaNode instanceof LeafListSchemaNode) {
+ valueNs = getValueNs(curSchemaNode, valNamespace, type);
+ propNode = propNode.addChild(null, name, ns,
+ MULTI_INSTANCE_LEAF_NODE, value,
+ valueNs, curSchemaNode);
+ } else if (curSchemaNode instanceof ListSchemaNode) {
+ propNode = propNode.addChild(null, name, ns, MULTI_INSTANCE_NODE,
+ curSchemaNode);
+ } else {
+ propNode = propNode.addChild(name, ns, SINGLE_INSTANCE_NODE,
+ curSchemaNode);
+ }
+ }
+
+ /**
+ * Returns the namespace of the value namespace in case of identity ref.
+ *
+ * @param schemaNode schema node
+ * @param valNs value name space
+ * @param nodeType node type
+ * @return namespace of value namespace
+ * @throws SvcLogicException when namespace resolution fails for identityref
+ */
+ private Namespace getValueNs(SchemaNode schemaNode, String valNs,
+ NodeType nodeType) throws SvcLogicException {
+ Namespace ns = null;
+ if (valNs != null) {
+ TypeDefinition type;
+ if (schemaNode instanceof LeafSchemaNode) {
+ type = ((LeafSchemaNode) schemaNode).getType();
+ } else {
+ type = ((LeafListSchemaNode) schemaNode).getType();
+ }
+ TypeDefinition<?> baseType = resolveBaseTypeFrom(type);
+ if (baseType instanceof IdentityrefTypeDefinition) {
+ if (nodeType == null) {
+ ns = getResolvedNamespace(null, valNs, getSchemaCtx(),
+ propNode);
+ } else {
+ ns = getResolvedNamespace(valNs, null, getSchemaCtx(),
+ propNode);
+ }
+ }
+ }
+ return ns;
+ }
+
+ /**
+ * Validates that the node type from the data format matches with that of
+ * the corresponding schema node.
+ *
+ * @param type node type from the abstract data format
+ * @throws SvcLogicException when the node type is wrong
+ */
+ private void validateNodeType(NodeType type) throws SvcLogicException {
+ boolean verify;
+ switch (type) {
+ case SINGLE_INSTANCE_LEAF_NODE:
+ verify = curSchemaNode instanceof LeafSchemaNode;
+ break;
+
+ case MULTI_INSTANCE_LEAF_NODE:
+ verify = curSchemaNode instanceof LeafListSchemaNode;
+ break;
+
+ case MULTI_INSTANCE_NODE:
+ verify = curSchemaNode instanceof ListSchemaNode;
+ break;
+
+ case SINGLE_INSTANCE_NODE:
+ verify = (!(curSchemaNode instanceof LeafSchemaNode) &&
+ !(curSchemaNode instanceof LeafListSchemaNode) &&
+ !(curSchemaNode instanceof ListSchemaNode));
+ break;
+
+ default:
+ throw new SvcLogicException(format(NODE_TYPE_ERR,
+ type.toString()));
+ }
+ if (!verify) {
+ throw new SvcLogicException(format(DF_ERR, curSchemaNode
+ .getQName().getLocalName(), type.toString()));
+ }
+ }
+
+ /**
+ * Returns true if the child schema is present with the name and
+ * namespace inside the current schema node, if present updates the
+ * current schema node; false otherwise.
+ *
+ * @param name name of the child schema node
+ * @param namespace namespace of the child schema node
+ * @return returns true if the child schema is available; false otherwise
+ */
+ private boolean isChildPresent(String name, Namespace namespace) {
+ QName qname = QName.create(namespace.moduleNs(),
+ Revision.of(namespace.revision()), name);
+ SchemaNode childNode = null;
+ if (curSchemaNode instanceof DataSchemaNode) {
+ Deque<DataSchemaNode> dataSchema = findSchemaNodeByNameAndNamespace(
+ (DataSchemaNode) curSchemaNode, name, namespace.moduleNs());
+
+ if (dataSchema != null && !dataSchema.isEmpty()) {
+ childNode = dataSchema.pop();
+ }
+
+ if (dataSchema != null && !dataSchema.isEmpty()) {
+ childNode = findSchemaForChild(((ChoiceSchemaNode) childNode),
+ qname);
+ }
+
+ } else {
+ childNode = findDataChildSchemaByQName(curSchemaNode, qname);
+ }
+
+ if (childNode != null) {
+ curSchemaNode = childNode;
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/PropertiesNodeJsonListener.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/PropertiesNodeJsonListener.java
new file mode 100644
index 000000000..0f03039e5
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/PropertiesNodeJsonListener.java
@@ -0,0 +1,233 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Huawei Technologies Co., Ltd. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.yangserializers.dfserializer;
+
+import com.google.gson.stream.JsonWriter;
+
+import java.io.IOException;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.util.Collection;
+import java.util.Map;
+
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.DefaultPropertiesNodeWalker;
+import org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.LeafNode;
+import org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.Namespace;
+import org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.PropertiesNode;
+import org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.PropertiesNodeListener;
+import org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.RootNode;
+
+import static com.google.common.base.Strings.repeat;
+import static java.lang.String.format;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DfSerializerUtil.JSON_WRITE_ERR;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DfSerializerUtil.NODE_TYPE_ERR;
+
+/**
+ * Representation of JSON implementation of properties node listener.
+ */
+public class PropertiesNodeJsonListener implements PropertiesNodeListener{
+
+ /**
+ * JSON writer to write the JSON data format.
+ */
+ private JsonWriter jsonWriter;
+
+ /**
+ * Writer to write the JSON.
+ */
+ private Writer writer;
+
+ /**
+ * Creates the properties node JSON listener by instantiating and
+ * indenting the writer.
+ */
+ public PropertiesNodeJsonListener() {
+ writer = new StringWriter();
+ jsonWriter = new JsonWriter(writer);
+ jsonWriter.setIndent(repeat(" ", 4));
+ }
+
+ @Override
+ public void start(PropertiesNode node) throws SvcLogicException {
+ try {
+ jsonWriter.beginObject();
+ } catch (IOException e) {
+ throw new SvcLogicException(JSON_WRITE_ERR, e);
+ }
+ }
+
+ @Override
+ public void end(PropertiesNode node) throws SvcLogicException {
+ try {
+ jsonWriter.endObject();
+ jsonWriter.flush();
+ } catch (IOException e) {
+ throw new SvcLogicException(JSON_WRITE_ERR, e);
+ }
+ }
+
+ @Override
+ public void enterPropertiesNode(PropertiesNode node)
+ throws SvcLogicException {
+ String val;
+ String nodeName = getNodeName(node);
+ try {
+ switch (node.nodeType()) {
+ case SINGLE_INSTANCE_NODE:
+ jsonWriter.name(nodeName);
+ jsonWriter.beginObject();
+ break;
+
+ case MULTI_INSTANCE_NODE:
+ jsonWriter.beginObject();
+ break;
+
+ case SINGLE_INSTANCE_LEAF_NODE:
+ val = getValueWithNs((LeafNode) node);
+ jsonWriter.name(nodeName).value(val);
+ break;
+
+ case MULTI_INSTANCE_HOLDER_NODE:
+ case MULTI_INSTANCE_LEAF_HOLDER_NODE:
+ jsonWriter.name(nodeName);
+ jsonWriter.beginArray();
+ break;
+
+ case MULTI_INSTANCE_LEAF_NODE:
+ val = getValueWithNs((LeafNode) node);
+ jsonWriter.value(val);
+ break;
+
+ case ANY_XML_NODE:
+ jsonWriter.name(nodeName);
+ val = ((LeafNode) node).value();
+ try {
+ jsonWriter.jsonValue(val);
+ } catch (IOException e) {
+ throw new SvcLogicException(JSON_WRITE_ERR, e);
+ }
+ break;
+
+ default:
+ throw new SvcLogicException(format(
+ NODE_TYPE_ERR, node.nodeType().toString()));
+
+ }
+ } catch (IOException e) {
+ throw new SvcLogicException(JSON_WRITE_ERR, e);
+ }
+ }
+
+ @Override
+ public void exitPropertiesNode(PropertiesNode node) throws SvcLogicException {
+ walkAugmentationNode(node);
+ try {
+ switch (node.nodeType()) {
+ case SINGLE_INSTANCE_NODE:
+ case MULTI_INSTANCE_NODE:
+ jsonWriter.endObject();
+ break;
+
+ case MULTI_INSTANCE_HOLDER_NODE:
+ case MULTI_INSTANCE_LEAF_HOLDER_NODE:
+ jsonWriter.endArray();
+ break;
+
+ case SINGLE_INSTANCE_LEAF_NODE:
+ case MULTI_INSTANCE_LEAF_NODE:
+ case ANY_XML_NODE:
+ break;
+
+ default:
+ throw new SvcLogicException(format(
+ NODE_TYPE_ERR, node.nodeType().toString()));
+ }
+ } catch (IOException e) {
+ throw new SvcLogicException(JSON_WRITE_ERR, e);
+ }
+ }
+
+ /**
+ * Returns the writer.
+ *
+ * @return writer
+ */
+ public Writer getWriter() {
+ return writer;
+ }
+
+ /**
+ * Returns the abstract JSON node name to be used in JSON data format
+ * from the properties node.
+ *
+ * @param node properties node
+ * @return abstract JSON node
+ */
+ private String getNodeName(PropertiesNode node) {
+ PropertiesNode parent = node.parent();
+ if (parent instanceof RootNode || !parent.namespace().moduleName()
+ .equals(node.namespace().moduleName())) {
+ if (!parent.nonAppend()) {
+ return node.namespace().moduleName() + ":" + node.name();
+ }
+ }
+ return node.name();
+ }
+
+ /**
+ * Returns the value of JSON leaf node with module name if required.
+ *
+ * @param node properties node
+ * @return value with namespace
+ */
+ private String getValueWithNs(LeafNode node) {
+ Namespace valNs = node.valueNs();
+ String modName = (valNs == null) ? null : valNs.moduleName();
+ if (modName != null) {
+ return modName + ":" + node.value();
+ }
+ return node.value();
+ }
+
+ /**
+ * Gets all the augmentation of the given node and walks through it.
+ *
+ * @param node properties node
+ * @throws SvcLogicException when walking the properties node fails
+ */
+ private void walkAugmentationNode(PropertiesNode node)
+ throws SvcLogicException {
+ for (Map.Entry<Object, Collection<PropertiesNode>>
+ augToChild : node.augmentations().asMap().entrySet()) {
+ Collection<PropertiesNode> augChild = augToChild.getValue();
+ if (!augChild.isEmpty()) {
+ DefaultPropertiesNodeWalker walker = new
+ DefaultPropertiesNodeWalker();
+ for (PropertiesNode p : augChild) {
+ enterPropertiesNode(p);
+ walker.walkChildNode(this, p);
+ exitPropertiesNode(p);
+ }
+ }
+ }
+ }
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/PropertiesNodeXmlListener.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/PropertiesNodeXmlListener.java
new file mode 100644
index 000000000..f098195e4
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/PropertiesNodeXmlListener.java
@@ -0,0 +1,246 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Huawei Technologies Co., Ltd. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.yangserializers.dfserializer;
+
+import org.dom4j.Document;
+import org.dom4j.DocumentHelper;
+import org.dom4j.Element;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.DefaultPropertiesNodeWalker;
+import org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.LeafNode;
+import org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.Namespace;
+import org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.PropertiesNode;
+import org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.PropertiesNodeListener;
+import org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.RootNode;
+
+import java.io.Writer;
+import java.net.URI;
+import java.util.Collection;
+import java.util.Map;
+import java.util.Stack;
+
+import static java.lang.String.format;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DfSerializerUtil.NODE_TYPE_ERR;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DfSerializerUtil.UTF_HEADER;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DfSerializerUtil.XML_PREFIX;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DfSerializerUtil.getXmlWriter;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.NodeType.MULTI_INSTANCE_HOLDER_NODE;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.NodeType.MULTI_INSTANCE_LEAF_HOLDER_NODE;
+
+/**
+ * Representation of XML implementation of properties node listener.
+ */
+public class PropertiesNodeXmlListener implements PropertiesNodeListener {
+
+ /**
+ * XML data from the element.
+ */
+ private String xmlData;
+
+ /**
+ * Root element of the XML document.
+ */
+ private Element rootElement;
+
+ /**
+ * Writer to write the XML.
+ */
+ private Writer writer;
+
+ /**
+ * XML element stack to store the elements.
+ */
+ private final Stack<Element> elementStack = new Stack<>();
+
+ /**
+ * Creates the properties node XML listener.
+ */
+ public PropertiesNodeXmlListener() {
+ }
+
+ @Override
+ public void start(PropertiesNode node) {
+ rootElement = addElement(null, node);
+ elementStack.push(rootElement);
+ }
+
+ @Override
+ public void end(PropertiesNode node) throws SvcLogicException {
+ xmlData = rootElement.asXML();
+ xmlData = UTF_HEADER + xmlData;
+ writer = getXmlWriter(xmlData, "4");
+ }
+
+ @Override
+ public void enterPropertiesNode(PropertiesNode node)
+ throws SvcLogicException {
+ Element element = null;
+ String ns = getNodeNamespace(node);
+ switch (node.nodeType()) {
+ case MULTI_INSTANCE_LEAF_HOLDER_NODE:
+ case MULTI_INSTANCE_HOLDER_NODE:
+ break;
+
+ case SINGLE_INSTANCE_NODE:
+ case MULTI_INSTANCE_NODE:
+ element = addElement(ns, node);
+ break;
+
+ case MULTI_INSTANCE_LEAF_NODE:
+ case SINGLE_INSTANCE_LEAF_NODE:
+ element = addElement(ns, node);
+ setValueWithNs(element, (LeafNode) node);
+ break;
+
+ default:
+ throw new SvcLogicException(format(
+ NODE_TYPE_ERR, node.nodeType().toString()));
+ }
+ if (element != null) {
+ elementStack.push(element);
+ }
+ }
+
+ @Override
+ public void exitPropertiesNode(PropertiesNode node)
+ throws SvcLogicException {
+ walkAugmentationNode(node);
+ switch (node.nodeType()) {
+ case MULTI_INSTANCE_LEAF_HOLDER_NODE:
+ case MULTI_INSTANCE_HOLDER_NODE:
+ break;
+
+ case SINGLE_INSTANCE_NODE:
+ case MULTI_INSTANCE_NODE:
+ case MULTI_INSTANCE_LEAF_NODE:
+ case SINGLE_INSTANCE_LEAF_NODE:
+ if (!elementStack.isEmpty()) {
+ elementStack.pop();
+ }
+ break;
+
+ default:
+ throw new SvcLogicException(format(
+ NODE_TYPE_ERR, node.nodeType().toString()));
+ }
+ }
+
+ /**
+ * Returns the writer.
+ *
+ * @return writer
+ */
+ public Writer getWriter() {
+ return writer;
+ }
+
+ /**
+ * Adds an XML element to the stack with namespace if present. If the
+ * stack is empty it creates new document and adds element else adds to
+ * the parent element.
+ *
+ * @param ns namespace of the element
+ * @param node properties node
+ * @return new added element
+ */
+ private Element addElement(String ns, PropertiesNode node) {
+ Element element;
+ if (elementStack.isEmpty()) {
+ Document doc = DocumentHelper.createDocument();
+ if (ns != null) {
+ element = doc.addElement(node.name(), ns);
+ } else {
+ element = doc.addElement(node.name());
+ }
+ } else {
+ element = elementStack.peek();
+ if (ns != null) {
+ element = element.addElement(node.name(), ns);
+ } else {
+ element = element.addElement(node.name());
+ }
+ }
+
+ return element;
+ }
+
+ /**
+ * Returns the abstract XML namespace to be used in XML data format from
+ * the properties node.
+ *
+ * @param node properties node
+ * @return abstract XML namespace
+ */
+ private String getNodeNamespace(PropertiesNode node) {
+ PropertiesNode parent = node.parent();
+ if (parent.nodeType() == MULTI_INSTANCE_HOLDER_NODE ||
+ parent.nodeType() == MULTI_INSTANCE_LEAF_HOLDER_NODE) {
+ parent = parent.parent();
+ }
+ if (parent instanceof RootNode || ! parent.namespace().moduleName()
+ .equals(node.namespace().moduleName())) {
+ return node.namespace().moduleNs().toString();
+ }
+ return null;
+ }
+
+ /**
+ * Sets the value to the element for a leaf node and adds the value
+ * namespace if required.
+ *
+ * @param element XML element
+ * @param node leaf properties node
+ */
+ private void setValueWithNs(Element element, LeafNode node) {
+ Namespace valNs = node.valueNs();
+ URI modNs = (valNs == null) ? null : valNs.moduleNs();
+ String val = node.value();
+ if (modNs != null) {
+ element.addNamespace(XML_PREFIX, modNs.toString());
+ element.setText(XML_PREFIX + ":" + val);
+ } else {
+ element.setText(val);
+ }
+ }
+
+ /**
+ * Gets all the augmentation of the given node and walks through it.
+ *
+ * @param node properties node
+ * @throws SvcLogicException when walking the properties node fails
+ */
+ private void walkAugmentationNode(PropertiesNode node)
+ throws SvcLogicException {
+ for (Map.Entry<Object, Collection<PropertiesNode>>
+ augToChild : node.augmentations().asMap().entrySet()) {
+ Collection<PropertiesNode> augChild = augToChild.getValue();
+ if (!augChild.isEmpty()) {
+ DefaultPropertiesNodeWalker walker = new
+ DefaultPropertiesNodeWalker();
+ for (PropertiesNode p : augChild) {
+ enterPropertiesNode(p);
+ walker.walkChildNode(this, p);
+ exitPropertiesNode(p);
+ }
+ }
+ }
+ }
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/SerializerHelper.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/SerializerHelper.java
new file mode 100644
index 000000000..db9befb21
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/SerializerHelper.java
@@ -0,0 +1,116 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Huawei Technologies Co., Ltd. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.yangserializers.dfserializer;
+
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.NodeType;
+import org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.PropertiesNode;
+
+/**
+ * Abstraction of an entity which helps the data format serializers to obtain
+ * schema context details and to build properties from data.
+ *
+ * @param <T> type of schema node
+ * @param <P> type of schema context
+ */
+public abstract class SerializerHelper<T, P> {
+
+ /**
+ * Schema node of the last element in the URI.
+ */
+ protected T schemaNode;
+
+ /**
+ * Root schema context.
+ */
+ protected P schemaCtx;
+
+ /**
+ * Root URI.
+ */
+ protected String rootUri;
+
+ /**
+ * Creates an instance of the serializer helper with the schema node,
+ * schema context and the URI.
+ *
+ * @param t schema node
+ * @param p schema context
+ * @param u root URI
+ */
+ protected SerializerHelper(T t, P p, String u) {
+ schemaNode = t;
+ schemaCtx = p;
+ rootUri = u;
+ }
+
+ /**
+ * Returns schema node of the last element in the URI.
+ *
+ * @return schema node
+ */
+ protected abstract T getSchemaNode();
+
+ /**
+ * Returns the root schema context.
+ *
+ * @return schema context
+ */
+ protected abstract P getSchemaCtx();
+
+ /**
+ * Returns the current schema context node.
+ *
+ * @return current schema context node
+ */
+ protected abstract T getCurSchema();
+
+ /**
+ * Adds a node to the properties node tree.
+ *
+ * @param name name of the node
+ * @param nameSpace name space of the node, it can be either module
+ * name or namespace; null indicates parent namespace
+ * @param value value of the node; applicable for leaf/leaf-list node
+ * @param valNameSpace value namespace for identityref, could be module
+ * name or namespace
+ * @param type type of node if known like in case of JSON
+ * @throws SvcLogicException when adding node fails
+ */
+ protected abstract void addNode(String name, String nameSpace, String value,
+ String valNameSpace, NodeType type)
+ throws SvcLogicException;
+
+ /**
+ * Exits the node, in case if it's leaf node then it adds to the properties
+ * map.
+ *
+ * @throws SvcLogicException when properties node tree is improper
+ */
+ protected abstract void exitNode() throws SvcLogicException;
+
+ /**
+ * Returns the built properties corresponding to the data.
+ *
+ * @return properties node.
+ */
+ protected abstract PropertiesNode getPropertiesNode();
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/XmlListener.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/XmlListener.java
new file mode 100644
index 000000000..784e7af1f
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/XmlListener.java
@@ -0,0 +1,53 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Huawei Technologies Co., Ltd. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.yangserializers.dfserializer;
+
+import org.dom4j.Element;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+
+/**
+ * Abstraction of an entity which provides call back methods, which in turn
+ * are called by XML walker while walking the XML tree. This interface needs
+ * to be implemented by protocol implementing listener based call while doing
+ * XML walk.
+ */
+public interface XmlListener extends Listener {
+
+ /**
+ * Callback invoked during a node entry. All the related information
+ * about the node can be obtained from the element.
+ *
+ * @param element current XML element
+ * @param nodeType node type of the element
+ * @throws SvcLogicException when node type is of wrong format
+ */
+ void enterXmlElement(Element element, XmlNodeType nodeType)
+ throws SvcLogicException;
+
+ /**
+ * Callback invoked during a node exit. All the related information about
+ * the node can be obtained from the element.
+ *
+ * @param element current xml element.
+ * @throws SvcLogicException when XML node exit doesn't happen
+ */
+ void exitXmlElement(Element element) throws SvcLogicException;
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/XmlNodeType.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/XmlNodeType.java
new file mode 100644
index 000000000..7a6db3c86
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/XmlNodeType.java
@@ -0,0 +1,37 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Huawei Technologies Co., Ltd. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.yangserializers.dfserializer;
+
+/**
+ * Represents the XML node type.
+ */
+public enum XmlNodeType {
+
+ /**
+ * Object XML node type.
+ */
+ OBJECT_NODE,
+
+ /**
+ * Text XML node type.
+ */
+ TEXT_NODE
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/XmlSerializer.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/XmlSerializer.java
new file mode 100644
index 000000000..f3c6723e1
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/XmlSerializer.java
@@ -0,0 +1,104 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Huawei Technologies Co., Ltd. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.yangserializers.dfserializer;
+
+import org.dom4j.Document;
+import org.dom4j.DocumentException;
+import org.dom4j.DocumentHelper;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.DefaultPropertiesNodeWalker;
+import org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.PropertiesNode;
+import org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.PropertiesNodeWalker;
+
+import java.io.Writer;
+import java.util.List;
+import java.util.Map;
+
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DataFormat.XML;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DfSerializerUtil.XML_LIS_ERR;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DfSerializerUtil.XML_TREE_ERR;
+
+/**
+ * Representation of XML serializer which encodes properties to XML and
+ * decodes properties from XML with the data format serializer.
+ */
+public class XmlSerializer extends DataFormatSerializer {
+
+ /**
+ * Creates an instance of XML serializer.
+ *
+ * @param serializerContext data format serializer context
+ */
+ protected XmlSerializer(DataFormatSerializerContext serializerContext) {
+ super(XML, serializerContext);
+ }
+
+ @Override
+ public String encode(Map<String, String> param,
+ Map<String, List<Annotation>> annotations)
+ throws SvcLogicException {
+ PropertiesNode propNode = serializerContext().getPropNodeSerializer()
+ .encode(param);
+ PropertiesNodeWalker nodeWalker = new DefaultPropertiesNodeWalker<>();
+ PropertiesNodeXmlListener xmlListener = new PropertiesNodeXmlListener();
+ nodeWalker.walk(xmlListener, propNode);
+ Writer writer = xmlListener.getWriter();
+ return removeRootNode(writer.toString(), propNode.name());
+ }
+
+ @Override
+ public Map<String, String> decode(String dataFormatBody)
+ throws SvcLogicException {
+ if (!(serializerContext().listener() instanceof XmlListener)) {
+ throw new SvcLogicException(XML_LIS_ERR);
+ }
+
+ XmlListener listener = (XmlListener) serializerContext().listener();
+ XmlWalker walker = new DefaultXmlWalker();
+ Document document;
+
+ try {
+ document = DocumentHelper.parseText(dataFormatBody);
+ } catch (DocumentException e) {
+ throw new SvcLogicException(XML_TREE_ERR, e);
+ }
+ walker.walk(listener, document.getRootElement());
+
+ return serializerContext().getPropNodeSerializer().decode(
+ listener.serializerHelper().getPropertiesNode());
+ }
+
+ /**
+ * Removes root node from the XML data format message and makes the
+ * string to be pretty print.
+ *
+ * @param xml XML data format message
+ * @param rootName root node name
+ * @return pretty print format XML message
+ */
+ private static String removeRootNode(String xml, String rootName) {
+ xml = xml.replace("\n<" + rootName + ">", "\n");
+ xml = xml.replace("</" + rootName + ">" + "\n", "");
+ xml = xml.replaceAll("\n" + " ", "\n");
+ xml = xml.replaceFirst("\n", "");
+ return xml;
+ }
+} \ No newline at end of file
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/XmlWalker.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/XmlWalker.java
new file mode 100644
index 000000000..3835faa7e
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/XmlWalker.java
@@ -0,0 +1,44 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Huawei Technologies Co., Ltd. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.yangserializers.dfserializer;
+
+import org.dom4j.Element;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+
+/**
+ * Abstraction of an entity which provides interface for XML walk. This
+ * interface serves as a common tool for anyone who needs to parse the XML
+ * node with depth-first algorithm.
+ */
+public interface XmlWalker {
+
+ /**
+ * Walks the XML data tree. Protocols implement XML listener service and
+ * walks the XML tree with input as implemented object. XML walker
+ * provides call back to the implemented methods.
+ *
+ * @param listener XML listener implemented by the protocol
+ * @param xmlElement root element of the XML data tree
+ * @throws SvcLogicException when walking the XML node fails
+ */
+ void walk(XmlListener listener, Element xmlElement) throws
+ SvcLogicException;
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/YangParameters.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/YangParameters.java
new file mode 100644
index 000000000..8eb3fb6e8
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/YangParameters.java
@@ -0,0 +1,42 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Huawei Technologies Co., Ltd. All rights reserved.
+ * ================================================================================
+ * Modifications Copyright © 2018 IBM
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.yangserializers.dfserializer;
+
+import org.onap.ccsdk.sli.plugins.restapicall.Parameters;
+
+/**
+ * Representation of the YANG parameters for the restconf api call node.
+ */
+public class YangParameters extends Parameters {
+ /**
+ * Directory path of the YANG file.
+ */
+ public String dirPath;
+
+ /**
+ * Creates an instance of the YANG parameters.
+ */
+ public YangParameters() {
+ super();
+ }
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/DataNodeChild.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/DataNodeChild.java
new file mode 100644
index 000000000..7be54690a
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/DataNodeChild.java
@@ -0,0 +1,27 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Huawei Technologies Co., Ltd. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.yangserializers.pnserializer;
+
+/**
+ * Abstraction of entity representing child's to data node.
+ */
+public interface DataNodeChild extends NodeChild {
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/DefaultPropertiesNodeListener.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/DefaultPropertiesNodeListener.java
new file mode 100644
index 000000000..2fa00bfb7
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/DefaultPropertiesNodeListener.java
@@ -0,0 +1,105 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Huawei Technologies Co., Ltd. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.yangserializers.pnserializer;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.COLON;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.UNDERSCORE;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.NodeType.MULTI_INSTANCE_LEAF_NODE;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.NodeType.SINGLE_INSTANCE_LEAF_NODE;
+
+/**
+ * Represents implementation of PropertiesNodeListener.
+ */
+public class DefaultPropertiesNodeListener implements PropertiesNodeListener {
+
+ private Map<String, String> params = new HashMap<>();
+
+ @Override
+ public void start(PropertiesNode node) {
+ // do nothing
+ }
+
+ @Override
+ public void end(PropertiesNode node) throws SvcLogicException {
+ exitPropertiesNode(node);
+ }
+
+ @Override
+ public void enterPropertiesNode(PropertiesNode node) {
+ /*
+ * Only if it is leaf node or leaf-list node,
+ * then create a property entry and add to map
+ */
+ if (node.nodeType() == SINGLE_INSTANCE_LEAF_NODE
+ || node.nodeType() == MULTI_INSTANCE_LEAF_NODE) {
+ String val = ((LeafNode) node).value();
+ if (((LeafNode) node).valueNs() != null) {
+ val = ((LeafNode) node).valueNs().moduleName() + COLON + val;
+ }
+ String uri = node.uri().replaceAll(COLON, UNDERSCORE);
+ params.put(uri, val);
+ }
+ }
+
+ @Override
+ public void exitPropertiesNode(PropertiesNode node) throws
+ SvcLogicException {
+ if (!node.augmentations().isEmpty()) {
+ for (Map.Entry<Object, Collection<PropertiesNode>> augmentationTochild
+ : node.augmentations().asMap().entrySet()) {
+ Collection<PropertiesNode> childsFromAugmentations = augmentationTochild
+ .getValue();
+ if (!childsFromAugmentations.isEmpty()) {
+ PropertiesNodeWalker walker = new DefaultPropertiesNodeWalker<>();
+ for (PropertiesNode pNode : childsFromAugmentations) {
+ enterPropertiesNode(pNode);
+ walker.walk(this, pNode);
+ exitPropertiesNode(pNode);
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns properties.
+ *
+ * @return properties
+ */
+ public Map<String, String> params() {
+ return params;
+ }
+
+ /**
+ * Sets properties.
+ *
+ * @param params properties
+ */
+ public void params(Map<String, String> params) {
+ this.params = params;
+ }
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/DefaultPropertiesNodeWalker.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/DefaultPropertiesNodeWalker.java
new file mode 100644
index 000000000..5034530d5
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/DefaultPropertiesNodeWalker.java
@@ -0,0 +1,119 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Huawei Technologies Co., Ltd. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.yangserializers.pnserializer;
+
+import java.util.Collection;
+import java.util.Map;
+
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+
+/**
+ * Implementation of properties node walker which helps in forming a new tree from properties node.
+ *
+ * @param <T> node child of properties node.
+ */
+public class DefaultPropertiesNodeWalker<T extends NodeChild> implements PropertiesNodeWalker {
+
+ @Override
+ public void walk(PropertiesNodeListener listener,
+ PropertiesNode propertiesNode) throws SvcLogicException {
+ listener.start(propertiesNode);
+ walkChildNode(listener, propertiesNode);
+ listener.end(propertiesNode);
+ }
+
+ /**
+ * Walks the children node from the parent node.
+ *
+ * @param listener properties node listener
+ * @param propertiesNode properties node
+ * @throws SvcLogicException when properties node walking fails
+ */
+ public void walkChildNode(PropertiesNodeListener listener,
+ PropertiesNode propertiesNode)
+ throws SvcLogicException {
+ Map<String, T> children = getChildren(propertiesNode);
+ if (children != null) {
+ for (Map.Entry<String, T> entry : children.entrySet()) {
+ PropertiesNode node = ((PropertiesNode) entry.getValue());
+ listener.enterPropertiesNode(node);
+ walkChildNode(listener, node);
+ listener.exitPropertiesNode(node);
+ }
+ }
+ if (propertiesNode instanceof RootNode) {
+ processAugments(propertiesNode, listener);
+ }
+ }
+
+ /**
+ * Processes the augments present in the root node.
+ *
+ * @param node root node
+ * @param listener properties node listener
+ * @throws SvcLogicException when augment node walking fails
+ */
+ private void processAugments(PropertiesNode node,
+ PropertiesNodeListener listener)
+ throws SvcLogicException {
+ for (Map.Entry<Object, Collection<PropertiesNode>>
+ augToChild : node.augmentations().asMap().entrySet()) {
+ Collection<PropertiesNode> child = augToChild.getValue();
+ if (!child.isEmpty()) {
+ for (PropertiesNode p : child) {
+ listener.enterPropertiesNode(p);
+ walkChildNode(listener, p);
+ listener.exitPropertiesNode(p);
+ }
+ }
+ }
+ }
+
+ /**
+ * Returns the children node according to the property node type.
+ *
+ * @param value property node
+ * @return property node children
+ */
+ private Map<String,T> getChildren(PropertiesNode value) {
+ if (value instanceof RootNode) {
+ return ((RootNode) value).children();
+ }
+ switch (value.nodeType()) {
+ case SINGLE_INSTANCE_NODE:
+ return ((InnerNode) value).children();
+ case MULTI_INSTANCE_HOLDER_NODE:
+ return ((Map<String, T>) ((ListHolderNode) value).children());
+ case MULTI_INSTANCE_NODE:
+ return ((Map<String, T>) ((MultiInstanceNode) value)
+ .children());
+ case MULTI_INSTANCE_LEAF_HOLDER_NODE:
+ return ((Map<String, T>) ((LeafListHolderNode) value)
+ .children());
+ case SINGLE_INSTANCE_LEAF_NODE:
+ case MULTI_INSTANCE_LEAF_NODE:
+ case ANY_XML_NODE:
+ return null;
+ default:
+ throw new IllegalArgumentException("No more types allowed");
+ }
+ }
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/HolderNode.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/HolderNode.java
new file mode 100644
index 000000000..52bec3412
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/HolderNode.java
@@ -0,0 +1,59 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Huawei Technologies Co., Ltd. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.yangserializers.pnserializer;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Abstraction of an entity that represents holder node to multi instance node
+ * in properties data tree.
+ *
+ * @param <T> type of child
+ */
+public abstract class HolderNode<T extends NodeChild> extends PropertiesNode {
+
+ private Map<String, T> children = new HashMap<>();
+
+ protected HolderNode(String name, Namespace namespace, String uri,
+ PropertiesNode parent, Object appInfo,
+ NodeType nodeType) {
+ super(name, namespace, uri, parent, appInfo, nodeType);
+ }
+
+ /**
+ * Returns children.
+ *
+ * @return children
+ */
+ public Map<String, T> children() {
+ return children;
+ }
+
+ /**
+ * Returns child based on index.
+ *
+ * @return child based on index
+ */
+ public T child(String index) {
+ return children.get(index);
+ }
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/InnerNode.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/InnerNode.java
new file mode 100644
index 000000000..1cf99b2d4
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/InnerNode.java
@@ -0,0 +1,215 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Huawei Technologies Co., Ltd. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.yangserializers.pnserializer;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.opendaylight.yangtools.yang.model.api.AugmentationSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.addToAugmentations;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.createNode;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.getAugmentationNode;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.getUri;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.isNamespaceAsParent;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.resolveName;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.NodeType.MULTI_INSTANCE_HOLDER_NODE;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.NodeType.MULTI_INSTANCE_LEAF_HOLDER_NODE;
+import static org.opendaylight.yangtools.yang.data.impl.schema.SchemaUtils.findCorrespondingAugment;
+
+/**
+ * Abstraction of an entity that represents an inner node to properties data
+ * tree.
+ *
+ * @param <T> type of child
+ */
+public abstract class InnerNode<T extends NodeChild> extends PropertiesNode {
+
+ private Map<String, T> children = new HashMap<String, T>();
+
+ protected InnerNode(String name, Namespace namespace, String uri,
+ PropertiesNode parent, Object appInfo, NodeType nodeType) {
+ super(name, namespace, uri, parent, appInfo, nodeType);
+ }
+
+ /**
+ * Returns children.
+ *
+ * @return children
+ */
+ public Map<String, T> children() {
+ return children;
+ }
+
+ /**
+ * Sets children.
+ *
+ * @param children child nodes
+ */
+ public void children(Map<String, T> children) {
+ this.children = children;
+ }
+
+ @Override
+ public PropertiesNode addChild(String name, Namespace namespace,
+ NodeType type,
+ Object appInfo) throws SvcLogicException {
+ PropertiesNode node = ((PropertiesNode) children.get(name));
+ if (node != null) {
+ return node;
+ }
+
+ // get augment schema, if it is augmented node
+ AugmentationSchemaNode augSchema = null;
+ if (((DataSchemaNode) appInfo).isAugmenting()) {
+ augSchema = findCorrespondingAugment(((DataSchemaNode) this.appInfo()), ((DataSchemaNode) appInfo));
+ node = getAugmentationNode(augSchema, this, name);
+ }
+
+ // create node based on type
+ if (node == null) {
+ String uri = getUri(this, name, namespace);
+ node = createNode(name, namespace, uri, this, appInfo, type);
+ }
+
+ // If namespace is not same as parent then it is augmented node
+ if (augSchema != null && !isNamespaceAsParent(this, node)) {
+ addToAugmentations(augSchema, this, node);
+ } else {
+ children.put(name, ((T) node));
+ }
+ return node;
+ }
+
+ @Override
+ public PropertiesNode addChild(String name, Namespace namespace,
+ NodeType type, String value,
+ Namespace valueNs,
+ Object appInfo) throws SvcLogicException {
+ LeafNode node = ((LeafNode) children.get(name));
+ if (node != null) {
+ return node;
+ }
+
+ AugmentationSchemaNode augSchema = null;
+ String uri = getUri(this, name, namespace);
+ node = new LeafNode(name, namespace, uri, this,
+ appInfo, type, value);
+
+ if (type != NodeType.ANY_XML_NODE) {
+ if (((DataSchemaNode) appInfo).isAugmenting()) {
+ augSchema = findCorrespondingAugment(
+ ((DataSchemaNode) this.appInfo()),
+ ((DataSchemaNode) appInfo));
+ }
+ node.valueNs(valueNs);
+ }
+
+ if (augSchema != null && !isNamespaceAsParent(this, node)) {
+ addToAugmentations(augSchema, this, node);
+ } else {
+ children.put(name, ((T) node));
+ }
+ return node;
+ }
+
+ @Override
+ public PropertiesNode addChild(String index, String name,
+ Namespace namespace, NodeType type,
+ Object appInfo) throws SvcLogicException {
+ String localname = resolveName(name);
+ PropertiesNode node = ((PropertiesNode) children.get(localname));
+
+ if (node == null) {
+ AugmentationSchemaNode augSchema = null;
+ if (((DataSchemaNode) appInfo).isAugmenting()) {
+ augSchema = findCorrespondingAugment(((DataSchemaNode) this.appInfo()),
+ ((DataSchemaNode) appInfo));
+ node = getAugmentationNode(augSchema, this, localname);
+ }
+
+ if (node == null) {
+ String uri = getUri(this, name, namespace);
+ node = new ListHolderNode(localname, namespace, uri,
+ this, appInfo, MULTI_INSTANCE_HOLDER_NODE);
+ }
+
+ if (augSchema != null && !isNamespaceAsParent(this, node)) {
+ addToAugmentations(augSchema, this, node);
+ } else {
+ children.put(localname, ((T) node));
+ }
+
+ node = node.addChild(index, localname, namespace, type, appInfo);
+ } else if (node instanceof ListHolderNode) {
+ ListHolderChild child = ((ListHolderNode) node).child(index);
+ node = (child != null ? ((MultiInstanceNode) child) :
+ node.addChild(index, localname, namespace, type, appInfo));
+ } else {
+ throw new SvcLogicException("Duplicate node exist with same node");
+ }
+ return node;
+ }
+
+ @Override
+ public PropertiesNode addChild(String index, String name,
+ Namespace namespace, NodeType type,
+ String value, Namespace valueNs,
+ Object appInfo) throws SvcLogicException {
+ String localName = resolveName(name);
+ PropertiesNode node = ((PropertiesNode) children.get(localName));
+
+ if (node == null) {
+
+ AugmentationSchemaNode augSchema = null;
+ if (((DataSchemaNode) appInfo).isAugmenting()) {
+ augSchema = findCorrespondingAugment(((DataSchemaNode) this.appInfo()),
+ ((DataSchemaNode) appInfo));
+ node = getAugmentationNode(augSchema, this, localName);
+ }
+
+ if (node == null) {
+ String uri = getUri(this, name, namespace);
+ node = new LeafListHolderNode(localName, namespace, uri, this,
+ appInfo, MULTI_INSTANCE_LEAF_HOLDER_NODE);
+ }
+
+ if (augSchema != null && !isNamespaceAsParent(this, node)) {
+ addToAugmentations(augSchema, this, node);
+ } else {
+ children.put(localName, ((T) node));
+ }
+
+ node = node.addChild(index, localName, namespace, type, value, valueNs, appInfo);
+ } else if (node instanceof LeafListHolderNode) {
+ LeafNode child = ((LeafNode) ((HolderNode) node).child(index));
+ node = (child != null ? child : node.addChild(index, localName,
+ namespace, type,
+ value, valueNs,
+ appInfo));
+ } else {
+ throw new SvcLogicException("Duplicate node exist with same node");
+ }
+ return node;
+ }
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/LeafListHolderChild.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/LeafListHolderChild.java
new file mode 100644
index 000000000..e43249a3d
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/LeafListHolderChild.java
@@ -0,0 +1,28 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Huawei Technologies Co., Ltd. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.yangserializers.pnserializer;
+
+/**
+ * Abstraction of entity representing child's to leaf list holder.
+ */
+public interface LeafListHolderChild extends NodeChild {
+
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/LeafListHolderNode.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/LeafListHolderNode.java
new file mode 100644
index 000000000..46ab5bb63
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/LeafListHolderNode.java
@@ -0,0 +1,93 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Huawei Technologies Co., Ltd. All rights reserved.
+ * ================================================================================
+ * Modifications Copyright © 2018 IBM
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.yangserializers.pnserializer;
+
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+
+/**
+ * Representation of leaf list holder node which will hold multi instance leaf
+ * node in properties data tree.
+ */
+public class LeafListHolderNode extends HolderNode<LeafListHolderChild> implements DataNodeChild {
+
+ private static final String node = " holder node";
+
+ /**
+ * Creates an instance of LeafListHolderNode.
+ *
+ * @param name name of the leaf-list node
+ * @param namespace namespace of the leaf-list node
+ * @param uri uri of the leaf-list node
+ * @param parent parent node of the leaf-list
+ * @param appInfo application info
+ * @param nodeType node type
+ */
+ public LeafListHolderNode(String name, Namespace namespace,
+ String uri, PropertiesNode parent,
+ Object appInfo, NodeType nodeType) {
+ super(name, namespace, uri, parent, appInfo, nodeType);
+ }
+
+ @Override
+ public PropertiesNode addChild(String name, Namespace namespace,
+ NodeType type, String value,
+ Namespace valueNs,
+ Object appInfo) throws SvcLogicException {
+ throw new SvcLogicException("Leaf cannot be child of leaf-list" +
+ node);
+ }
+
+ @Override
+ public PropertiesNode addChild(String name, Namespace namespace,
+ NodeType type,
+ Object appInfo) throws SvcLogicException {
+ throw new SvcLogicException("Container cannot be child of leaf-list" +
+ node);
+ }
+
+ @Override
+ public PropertiesNode addChild(String index, String name,
+ Namespace namespace,
+ NodeType type,
+ Object appInfo) throws SvcLogicException {
+ throw new SvcLogicException("List cannot be child of leaf-list" +
+ node);
+ }
+
+ @Override
+ public PropertiesNode addChild(String index, String name,
+ Namespace namespace, NodeType type,
+ String value, Namespace valueNs,
+ Object appInfo) throws SvcLogicException {
+ LeafNode node = ((LeafNode) children().get(index));
+ if (index == null) {
+ index = String.valueOf(children().size());
+ }
+ String uri = this.uri() + "[" + index + "]";
+ node = (node != null) ? node : new LeafNode(name, namespace, uri,
+ this, appInfo, type, value);
+ node.valueNs(valueNs);
+ children().put(index, node);
+ return node;
+ }
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/LeafNode.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/LeafNode.java
new file mode 100644
index 000000000..041175ca7
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/LeafNode.java
@@ -0,0 +1,122 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Huawei Technologies Co., Ltd. All rights reserved.
+ *
+ * Modifications Copyright © 2018 IBM
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.yangserializers.pnserializer;
+
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+
+/**
+ * Representation of leaf node in properties data tree.
+ */
+public class LeafNode extends PropertiesNode implements LeafListHolderChild, DataNodeChild {
+
+ private String value;
+ private Namespace valueNs;
+ private static final String svcLogicException = "Leaf cannot hold child nodes";
+
+ /**
+ * Creates an instance of leaf node.
+ *
+ * @param name name of the leaf node
+ * @param namespace namespace of the leaf node
+ * @param uri uri of the leaf node
+ * @param parent parent of the leaf node
+ * @param appInfo application info
+ * @param nodeType node type
+ * @param value value of the leaf
+ */
+ public LeafNode(String name, Namespace namespace,
+ String uri, PropertiesNode parent,
+ Object appInfo, NodeType nodeType,
+ String value) {
+ super(name, namespace, uri, parent, appInfo, nodeType);
+ this.value = value;
+ }
+
+ /**
+ * Returns value of the leaf.
+ *
+ * @return value of the leaf
+ */
+ public String value() {
+ return value;
+ }
+
+ /**
+ * Sets value of the leaf.
+ *
+ * @param value value of the leaf
+ */
+ public void value(String value) {
+ this.value = value;
+ }
+
+ /**
+ * Returns value namespace.
+ *
+ * @return value namespace
+ */
+ public Namespace valueNs() {
+ return valueNs;
+ }
+
+ /**
+ * Sets value namespace.
+ *
+ * @param valueNs value namespace
+ */
+ public void valueNs(Namespace valueNs) {
+ this.valueNs = valueNs;
+ }
+
+ @Override
+ public PropertiesNode addChild(String name, Namespace namespace,
+ NodeType type,
+ Object appInfo) throws SvcLogicException {
+ throw new SvcLogicException(svcLogicException);
+ }
+
+ @Override
+ public PropertiesNode addChild(String name, Namespace namespace,
+ NodeType type, String value,
+ Namespace valueNs,
+ Object appInfo) throws SvcLogicException {
+ throw new SvcLogicException(svcLogicException);
+ }
+
+ @Override
+ public PropertiesNode addChild(String index, String name,
+ Namespace namespace,
+ NodeType type,
+ Object appInfo) throws SvcLogicException {
+ throw new SvcLogicException(svcLogicException);
+ }
+
+ @Override
+ public PropertiesNode addChild(String index, String name,
+ Namespace namespace,
+ NodeType type, String value,
+ Namespace valueNs,
+ Object appInfo) throws SvcLogicException {
+ throw new SvcLogicException("Leaf cannot hold child nodes");
+ }
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/ListHolderChild.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/ListHolderChild.java
new file mode 100644
index 000000000..ec9cc2a0f
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/ListHolderChild.java
@@ -0,0 +1,28 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Huawei Technologies Co., Ltd. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.yangserializers.pnserializer;
+
+/**
+ * Abstraction of entity representing child's to list holder.
+ */
+public interface ListHolderChild extends NodeChild {
+
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/ListHolderNode.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/ListHolderNode.java
new file mode 100644
index 000000000..ba9da54cf
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/ListHolderNode.java
@@ -0,0 +1,73 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Huawei Technologies Co., Ltd. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.yangserializers.pnserializer;
+
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+
+/**
+ * Representation of list holder node which will hold multi instance node in
+ * properties data tree.
+ */
+public class ListHolderNode extends HolderNode<ListHolderChild> implements DataNodeChild {
+
+ protected ListHolderNode(String name, Namespace namespace, String uri,
+ PropertiesNode parent, Object appInfo, NodeType nodeType) {
+ super(name, namespace, uri, parent, appInfo, nodeType);
+ }
+
+ @Override
+ public PropertiesNode addChild(String name, Namespace namespace,
+ NodeType type, String value,
+ Namespace valueNs,
+ Object appInfo) throws SvcLogicException {
+ throw new SvcLogicException("Leaf cannot be child of list holder node");
+ }
+
+ @Override
+ public PropertiesNode addChild(String name, Namespace namespace,
+ NodeType type,
+ Object appInfo) throws SvcLogicException {
+ throw new SvcLogicException("Container cannot be child of list holder node");
+ }
+
+ @Override
+ public PropertiesNode addChild(String index, String name,
+ Namespace namespace, NodeType type,
+ Object appInfo) throws SvcLogicException {
+ MultiInstanceNode node = ((MultiInstanceNode) children().get(index));
+ if (index == null) {
+ index = String.valueOf(children().size());
+ }
+ String uri = this.uri() + "[" + index + "]";
+ node = (node != null) ? node : new MultiInstanceNode(name, namespace, uri,
+ this, appInfo, type);
+ children().put(index, node);
+ return node;
+ }
+
+ @Override
+ public PropertiesNode addChild(String index, String name,
+ Namespace namespace, NodeType type,
+ String value, Namespace valueNs,
+ Object appInfo) throws SvcLogicException {
+ throw new SvcLogicException("Leaf-list cannot be child of list holder node");
+ }
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/MdsalPropertiesNodeSerializer.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/MdsalPropertiesNodeSerializer.java
new file mode 100644
index 000000000..8a6e75668
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/MdsalPropertiesNodeSerializer.java
@@ -0,0 +1,227 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Huawei Technologies Co., Ltd. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.yangserializers.pnserializer;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaNode;
+import org.opendaylight.yangtools.yang.model.util.SchemaContextUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.DOT_REGEX;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.SLASH;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.getChildSchemaNode;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.getIndex;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.getListName;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.getNamespace;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.getNodeType;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.getParsedValue;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.getProcessedPath;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.getRevision;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.getValueNamespace;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.resolveName;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.NodeType.ANY_XML_NODE;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.NodeType.MULTI_INSTANCE_LEAF_NODE;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.NodeType.MULTI_INSTANCE_NODE;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.NodeType.SINGLE_INSTANCE_LEAF_NODE;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.NodeType.SINGLE_INSTANCE_NODE;
+
+/**
+ * Representation of mdsal based properties node serializer implementation.
+ */
+public class MdsalPropertiesNodeSerializer extends PropertiesNodeSerializer<SchemaNode, SchemaContext> {
+
+ private static final Logger log = LoggerFactory.getLogger(
+ MdsalPropertiesNodeSerializer.class);
+ private SchemaNode curSchema;
+ private PropertiesNode node;
+
+ /**
+ * Creates the properties node serializer.
+ *
+ * @param schemaNode schema node.
+ * @param schemaCtx schema context
+ * @param uri URL of the request
+ */
+ public MdsalPropertiesNodeSerializer(SchemaNode schemaNode,
+ SchemaContext schemaCtx, String uri) {
+ super(schemaNode, schemaCtx, uri);
+ }
+
+ @Override
+ public PropertiesNode encode(Map<String, String> paramMap) throws SvcLogicException {
+ curSchema = schemaNode();
+ String nodeInUri[] = uri().split("\\/");
+ String lastNodeName = nodeInUri[nodeInUri.length - 1];
+ String rootUri = uri().replaceAll("\\/", "\\.");
+ node = createRootNode(lastNodeName, rootUri);
+
+ paramMap = convertToValidParam(paramMap);
+
+ updateModNameReq(paramMap, rootUri);
+
+ for (Map.Entry<String, String> entry : paramMap.entrySet()) {
+ String[] names = entry.getKey().split("\\.");
+ for (int i = 0; i < names.length; i++) {
+ if (i < nodeInUri.length) {
+ if (!(nodeInUri[i].equals(names[i]))) {
+ break;
+ }
+ } else {
+ createPropertyNode(i, names.length, names[i],
+ entry.getValue());
+ }
+ }
+ }
+ return node;
+ }
+
+ private void updateModNameReq(Map<String, String> paramMap,
+ String rootUri) {
+ String isReqStr = rootUri + "." + "isNonAppend";
+ String val = paramMap.get(isReqStr);
+ if (val != null && val.equals("true")) {
+ node.nonAppend(true);
+ }
+ }
+
+ /**
+ * Converts all the params in the svc logic context into a valid param by
+ * replacing the underscore in module name to colon at necessary places.
+ *
+ * @param paramMap list of invalid parameters
+ * @return list of partially valid parameters
+ */
+ private Map<String, String> convertToValidParam(Map<String, String> paramMap) {
+ Map<String, String> fixedParams = new HashMap<>();
+ for(Map.Entry<String, String> entry : paramMap.entrySet()) {
+ String key = entry.getKey().replaceAll(DOT_REGEX, SLASH);
+ try {
+ SchemaPathHolder fixedUrl = getProcessedPath(key, schemaCtx());
+ String fixedUri = fixedUrl.getUri().replaceAll(
+ SLASH, DOT_REGEX);
+ fixedParams.put(fixedUri, entry.getValue());
+ } catch (IllegalArgumentException | RestconfDocumentedException
+ | NullPointerException e) {
+ log.info("Exception while processing properties by replacing " +
+ "underscore with colon. Process the properties as it is." + e);
+ fixedParams.put(entry.getKey(), entry.getValue());
+ }
+ }
+ return fixedParams;
+ }
+
+ @Override
+ public Map<String, String> decode(PropertiesNode propertiesNode)
+ throws SvcLogicException {
+ PropertiesNodeWalker walker = new DefaultPropertiesNodeWalker<>();
+ DefaultPropertiesNodeListener listener = new DefaultPropertiesNodeListener();
+ walker.walk(listener, propertiesNode);
+ return listener.params();
+ }
+
+ private RootNode createRootNode(String lastNodeName, String rootUri) {
+ Module m = SchemaContextUtil.findParentModule(schemaCtx(), curSchema);
+ Namespace ns = new Namespace(m.getName(), m.getNamespace(),
+ getRevision(m.getRevision()));
+ return new RootNode(lastNodeName, ns, schemaNode(), rootUri);
+ }
+
+ private void createPropertyNode(int index, int length, String name,
+ String value) throws SvcLogicException {
+
+ Namespace ns = getNamespace(getListName(name), schemaCtx(),
+ node, curSchema);
+ String localName = resolveName(ns, name);
+ SchemaNode schema = getChildSchemaNode(curSchema, localName, ns);
+ if (schema == null) {
+ return;
+ }
+
+ switch (getNodeType(index, length, name, schema)) {
+ case SINGLE_INSTANCE_NODE:
+ node = node.addChild(localName, ns,
+ SINGLE_INSTANCE_NODE, schema);
+ curSchema = schema;
+ break;
+
+ case MULTI_INSTANCE_NODE:
+ node = node.addChild(getIndex(name), localName, ns,
+ MULTI_INSTANCE_NODE, schema);
+ curSchema = schema;
+ break;
+
+ case SINGLE_INSTANCE_LEAF_NODE:
+ addLeafNode(value, SINGLE_INSTANCE_LEAF_NODE, localName,
+ ns, schema, name);
+ break;
+
+ case MULTI_INSTANCE_LEAF_NODE:
+ addLeafNode(value, MULTI_INSTANCE_LEAF_NODE, localName,
+ ns, schema, name);
+ break;
+
+ case ANY_XML_NODE:
+ node = node.addChild(localName, ns, ANY_XML_NODE,
+ value, null, schema);
+ node = node.endNode();
+ curSchema = ((SchemaNode) node.appInfo());
+ break;
+
+ default:
+ throw new SvcLogicException("Invalid node type");
+ }
+ }
+
+ /**
+ * Adds leaf property node to the current node.
+ *
+ * @param value value of the leaf node
+ * @param type single instance or multi instance leaf node
+ * @param localName name of the leaf node
+ * @param ns namespace of the leaf node
+ * @param schema schema of the leaf node
+ * @param name name of the leaf in properties
+ * @throws SvcLogicException exception while adding leaf node
+ */
+ private void addLeafNode(String value, NodeType type,
+ String localName, Namespace ns,
+ SchemaNode schema, String name) throws SvcLogicException {
+ Namespace valNs = getValueNamespace(value, schemaCtx());
+ value = getParsedValue(valNs, value);
+ if (SINGLE_INSTANCE_LEAF_NODE == type) {
+ node = node.addChild(localName, ns, SINGLE_INSTANCE_LEAF_NODE,
+ value, valNs, schema);
+ } else {
+ node = node.addChild(getIndex(name), localName, ns,
+ MULTI_INSTANCE_LEAF_NODE, value,
+ valNs, schema);
+ }
+ node = node.endNode();
+ curSchema = ((SchemaNode) node.appInfo());
+ }
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/MdsalPropertiesNodeUtils.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/MdsalPropertiesNodeUtils.java
new file mode 100644
index 000000000..e6fa064f5
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/MdsalPropertiesNodeUtils.java
@@ -0,0 +1,578 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Huawei Technologies Co., Ltd. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.yangserializers.pnserializer;
+
+import java.util.Collection;
+import java.util.Deque;
+import java.util.Iterator;
+import java.util.Optional;
+
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.opendaylight.restconf.common.context.InstanceIdentifierContext;
+import org.opendaylight.restconf.common.errors.RestconfDocumentedException;
+import org.opendaylight.yangtools.yang.common.QName;
+import org.opendaylight.yangtools.yang.common.Revision;
+import org.opendaylight.yangtools.yang.data.impl.schema.SchemaUtils;
+import org.opendaylight.yangtools.yang.data.util.ParserStreamUtils;
+import org.opendaylight.yangtools.yang.data.util.codec.IdentityCodecUtil;
+import org.opendaylight.yangtools.yang.model.api.AnyXmlSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.AugmentationSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.ChoiceSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.IdentitySchemaNode;
+import org.opendaylight.yangtools.yang.model.api.Module;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.model.api.SchemaNode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static java.lang.String.format;
+import static java.util.regex.Pattern.quote;
+import static org.opendaylight.restconf.nb.rfc8040.utils.parser.ParserIdentifier.toInstanceIdentifier;
+
+/**
+ * Represents utilities for properties node tree.
+ */
+public final class MdsalPropertiesNodeUtils {
+
+ static final String COLON = ":";
+
+ static final String UNDERSCORE = "_";
+
+ static final String SLASH = "/";
+
+ static final String DOT_REGEX = "\\.";
+
+ private static final String INFO_MSG = "The %s formed is currently not" +
+ " valid";
+
+ private static final String EXC_MSG = "Unable to form a formatted path";
+
+ /**
+ * Logger for the Mdsal properties util class.
+ */
+ private static final Logger log = LoggerFactory.getLogger(
+ MdsalPropertiesNodeUtils.class);
+
+ private MdsalPropertiesNodeUtils() {
+ }
+
+ /**
+ * Returns the index from multi instance property name.
+ *
+ * @param name name of the property
+ * @return index from multi instance property name
+ */
+ public static String getIndex(String name) {
+ return name.substring(name.indexOf("[") + 1,
+ name.indexOf("]"));
+ }
+
+ /**
+ * Returns the multi instance property name.
+ *
+ * @param name name of the property
+ * @return the multi instance property name
+ */
+ public static String getListName(String name) {
+ String[] s = name.split("\\[");
+ return s[0];
+ }
+
+ /**
+ * Returns true if property is multi instance.
+ *
+ * @param name name of the property
+ * @return true if property is multi instance
+ */
+ public static boolean isListEntry(String name) {
+ String s[] = name.split("\\[");
+ return s.length > 1;
+ }
+
+ /**
+ * Returns name of the property after pruning namespace and
+ * index if the property is multi instance.
+ *
+ * @param name name of the property
+ * @return name of the property
+ */
+ static String resolveName(String name) {
+ String localName = getListName(name);
+ final int lastIndexOfColon = localName.lastIndexOf(":");
+ if (lastIndexOfColon != -1) {
+ localName = localName.substring(lastIndexOfColon + 1);
+ }
+ return localName;
+ }
+
+ /**
+ * Returns name of the property after pruning namespace and index if the
+ * property is multi instance by knowing the module name from namespace.
+ *
+ * @param ns namespace
+ * @param name name of the node
+ * @return resolved name
+ */
+ static String resolveName(Namespace ns, String name) {
+ String localName = getListName(name);
+ String modName = ns.moduleName();
+ if ((localName.contains(COLON) || localName.contains(UNDERSCORE))
+ && localName.startsWith(modName)) {
+ localName = localName.substring(modName.length()+1);
+ }
+ return localName;
+ }
+
+ /**
+ * Adds current node to parent's augmentation map.
+ *
+ * @param augSchema augment schema
+ * @param parent parent property node
+ * @param curNode current property node
+ */
+ public static void addToAugmentations(AugmentationSchemaNode augSchema,
+ PropertiesNode parent,
+ PropertiesNode curNode) {
+ Collection<PropertiesNode> childsFromAugmentation = parent
+ .augmentations().get(augSchema);
+ if (!childsFromAugmentation.isEmpty()) {
+ for (PropertiesNode pNode : childsFromAugmentation) {
+ if (pNode.name().equals(curNode.name())) {
+ return;
+ }
+ }
+ }
+ parent.augmentations().put(augSchema, curNode);
+ }
+
+
+ /**
+ * Returns augmented properties node if it is already
+ * added in properties tree.
+ *
+ * @param augSchema augmented schema node
+ * @param parent parent properties node
+ * @param name name of the properties
+ * @return augmented properties node if it is already added
+ */
+ public static PropertiesNode getAugmentationNode(
+ AugmentationSchemaNode augSchema,
+ PropertiesNode parent, String name) {
+ if (augSchema == null) {
+ return null;
+ }
+
+ Collection<PropertiesNode> childsFromAugmentation = parent
+ .augmentations().get(augSchema);
+ if (!childsFromAugmentation.isEmpty()) {
+ for (PropertiesNode pNode : childsFromAugmentation) {
+ if (pNode.name().equals(name)) {
+ return pNode;
+ }
+ }
+ }
+
+ return null;
+ }
+
+ /**
+ * Creates uri with specified name and namespace.
+ *
+ * @param parent parent properties node
+ * @param name name of the node
+ * @param ns namespace of the node
+ * @return uri with specified name and namespace
+ */
+ public static String getUri(PropertiesNode parent, String name,
+ Namespace ns) {
+ String uri = name;
+ if (!(parent.namespace().moduleNs().equals(ns.moduleNs()))) {
+ uri = ns.moduleName() + ":" + name;
+ }
+ return parent.uri() + "." + uri;
+ }
+
+ /**
+ * Creates new properties with specified parameters.
+ *
+ * @param name name of the properties node
+ * @param namespace namespace of the properties node
+ * @param uri uri of the properties node
+ * @param parent parent node
+ * @param appInfo application info
+ * @param type node type
+ * @return new properties node
+ * @throws SvcLogicException exception while creating properties node
+ */
+ public static PropertiesNode createNode(String name, Namespace namespace,
+ String uri, PropertiesNode parent,
+ Object appInfo, NodeType type)
+ throws SvcLogicException {
+ switch (type) {
+ case SINGLE_INSTANCE_NODE:
+ return new SingleInstanceNode(name, namespace, uri, parent, appInfo, type);
+ case MULTI_INSTANCE_HOLDER_NODE:
+ return new ListHolderNode(name, namespace, uri, parent, appInfo, type);
+ case MULTI_INSTANCE_LEAF_HOLDER_NODE:
+ return new LeafListHolderNode(name, namespace, uri, parent, appInfo, type);
+ default:
+ throw new SvcLogicException("Invalid node type " + type);
+ }
+ }
+
+ /**
+ * Returns true if namespace is same as parent's namespace.
+ *
+ * @param parent parent property node
+ * @param curNode current property node
+ * @return true if namespace is same as parent namespace
+ */
+ public static boolean isNamespaceAsParent(PropertiesNode parent,
+ PropertiesNode curNode) {
+ return parent.namespace().moduleNs().equals(curNode.namespace().moduleNs());
+ }
+
+ /**
+ * Returns the schema path holder with a formatted url and the instance
+ * identifier context from a given uri or the parameters from svc logic
+ * context.
+ *
+ * @param uri unformatted uri or parameter
+ * @param context schema context
+ * @return schema path holder
+ */
+ public static SchemaPathHolder getProcessedPath(String uri,
+ SchemaContext context) {
+
+ String uri1 = uri.replaceAll(UNDERSCORE, COLON);
+ try {
+ InstanceIdentifierContext<?> id = toInstanceIdentifier(
+ uri1, context, null);
+ return new SchemaPathHolder(id, uri1);
+ } catch (IllegalArgumentException | RestconfDocumentedException
+ | NullPointerException e) {
+ log.info("Exception while converting uri to instance identifier" +
+ " context. Process each node in uri to get instance identifier" +
+ " context " + e);
+ return processNodesAndAppendPath(uri, context);
+ }
+ }
+
+ /**
+ * Processes the nodes in the given uri and finds instance identifier
+ * context till it reaches the last node in uri. If its not able to find
+ * schema for the path, it appends the suffix part and puts it back in
+ * the param list.
+ *
+ * @param uri uri with underscore
+ * @param context schema context
+ * @return schema and path holder
+ */
+ private static SchemaPathHolder processNodesAndAppendPath(String uri,
+ SchemaContext context) {
+
+ String actPath = "";
+ SchemaPathHolder id = new SchemaPathHolder(null, "");
+ String[] uriParts = uri.split(SLASH);
+ String sec = "";
+ if (uri.contains(UNDERSCORE)) {
+ sec = uri.substring(uriParts[0].length()+1);
+ }
+ for (int i = 0; i<uriParts.length; i++) {
+
+ try {
+ id = processIdentifier(uriParts[i], context, actPath);
+ } catch (IllegalArgumentException e) {
+ log.info(format(EXC_MSG, e));
+ id.setUri(actPath+ uriParts[i] + sec);
+ return id;
+ }
+
+ actPath = actPath + id.getUri() + SLASH;
+ if (sec.startsWith(SLASH)) {
+ sec = sec.replaceFirst(SLASH, "");
+ }
+ if (i+1 < uriParts.length) {
+ sec = sec.replaceFirst(quote(uriParts[i + 1]), "");
+ }
+ }
+ id.setUri(actPath.substring(0,actPath.length() - 1));
+ return id;
+ }
+
+ /**
+ * Processes the schema and path holder for a given node in the path. It
+ * figures if the path is valid by replacing underscore in the node
+ * consecutively, till it finds the proper schema for the node.
+ *
+ * @param node node in the path
+ * @param context schema context
+ * @param prefix prefix for the node in the path
+ * @return schema and path holder
+ */
+ private static SchemaPathHolder processIdentifier(String node,
+ SchemaContext context,
+ String prefix) {
+
+ String[] values = node.split(UNDERSCORE);
+ String val = values[0];
+ StringBuilder firstHalf = new StringBuilder();
+ String secondHalf = "";
+ if (node.contains(UNDERSCORE)) {
+ secondHalf = node.substring(values[0].length()+1);
+ }
+ InstanceIdentifierContext<?> id;
+ for (int i = 0; i< values.length-1; i++) {
+ val = values[i];
+ val = firstHalf + val + COLON + secondHalf;
+ try {
+ id = toInstanceIdentifier(prefix + val, context, null);
+ return new SchemaPathHolder(id, val);
+ } catch (IllegalArgumentException | RestconfDocumentedException |
+ NullPointerException e) {
+ log.info(format(INFO_MSG, val, e));
+ }
+ firstHalf.append(values[i]).append(UNDERSCORE);
+ secondHalf = secondHalf.replaceFirst(
+ values[i + 1] + UNDERSCORE,"");
+ }
+ val = val.replace(COLON,UNDERSCORE);
+ try {
+ id = toInstanceIdentifier(prefix + val, context, null);
+ return new SchemaPathHolder(id, val);
+ } catch (IllegalArgumentException | RestconfDocumentedException |
+ NullPointerException e1) {
+ throw new IllegalArgumentException(EXC_MSG, e1);
+ }
+ }
+
+ /**
+ * Returns the namespace of the given node name. If the node name is
+ * separated by colon, the it splits with colon and forms the namespace.
+ * If the node name is formed with underscore, then it splits the node
+ * name consecutively to figure out the proper module name.
+ *
+ * @param childName node name
+ * @param ctx schema context
+ * @param parent parent properties node
+ * @param curSchema current schema
+ * @return namespace of the given node
+ */
+ static Namespace getNamespace(String childName, SchemaContext ctx,
+ PropertiesNode parent, SchemaNode curSchema) {
+
+ Namespace parentNs = parent.namespace();
+ Namespace ns = new Namespace(parentNs.moduleName(),
+ parentNs.moduleNs(), parentNs.revision());
+ int lastIndexOfColon = childName.lastIndexOf(COLON);
+ if (lastIndexOfColon != -1) {
+ String moduleName = childName.substring(0, lastIndexOfColon);
+ childName = childName.substring(lastIndexOfColon+1);
+ Namespace ns1 = getNs(moduleName, ctx);
+ if (ns1 != null) {
+ ns = ns1;
+ }
+ }
+
+ SchemaNode child = getChildSchemaNode(curSchema, childName, ns);
+
+ if (child == null && childName.contains(UNDERSCORE)) {
+ String[] children = childName.split(UNDERSCORE);
+ String second = childName.substring(children[0].length() + 1);
+ StringBuilder first = new StringBuilder();
+
+ for (int i =0; i< children.length; i++) {
+ String moduleName = first + children[i];
+ Namespace newNs = getNs(moduleName, ctx);
+ if (newNs != null) {
+ return newNs;
+ }
+ first.append(children[i]).append(UNDERSCORE);
+ if (i + 1 < children.length) {
+ second = second.replaceFirst(
+ children[i + 1] + UNDERSCORE, "");
+ }
+ }
+ return ns;
+ }
+ return ns;
+ }
+
+ /**
+ * Returns the namespace by finding the given module in the schema context.
+ *
+ * @param modName module name
+ * @param ctx schema context
+ * @return namespace of the given node name
+ */
+ private static Namespace getNs(String modName, SchemaContext ctx) {
+ Iterator<Module> it = ctx.findModules(modName).iterator();
+ if (it.hasNext()) {
+ Module m = it.next();
+ return new Namespace(modName, m.getQNameModule().getNamespace(),
+ getRevision(m.getRevision()));
+ }
+ return null;
+ }
+
+ /**
+ * Returns child schema node.
+ *
+ * @param curSchema current schema node
+ * @param name name of the property
+ * @param namespace namespace of the property
+ * @return child schema node
+ */
+ public static SchemaNode getChildSchemaNode(SchemaNode curSchema,
+ String name,
+ Namespace namespace) {
+ if (namespace == null) {
+ return null;
+ }
+
+ QName qname = QName.create(namespace.moduleNs(),
+ Revision.of(namespace.revision()), name);
+
+ // YANG RPC will not be instance of DataSchemaNode
+ if (curSchema instanceof DataSchemaNode) {
+ Deque<DataSchemaNode> schemaNodeDeque = ParserStreamUtils.
+ findSchemaNodeByNameAndNamespace(((DataSchemaNode)
+ curSchema), name, namespace.moduleNs());
+ if (schemaNodeDeque.isEmpty()) {
+ // could not find schema node
+ return null;
+ }
+
+ DataSchemaNode schemaNode = schemaNodeDeque.pop();
+ if (schemaNodeDeque.isEmpty()){
+ // Simple node
+ return schemaNode;
+ }
+
+ // node is child of Choice/case
+ return SchemaUtils.findSchemaForChild(((ChoiceSchemaNode) schemaNode),
+ qname);
+ } else {
+ return SchemaUtils.findDataChildSchemaByQName(curSchema, qname);
+ }
+ }
+
+ /**
+ * Returns the property node type.
+ *
+ * @param index current index
+ * @param length length of the properties
+ * @param name name of the property
+ * @return the property node type
+ */
+ public static NodeType getNodeType(int index, int length, String name,
+ SchemaNode schema) {
+ if (index == length-1) {
+ if (schema instanceof AnyXmlSchemaNode){
+ return NodeType.ANY_XML_NODE;
+ }
+ return (isListEntry(name) ? NodeType.MULTI_INSTANCE_LEAF_NODE :
+ NodeType.SINGLE_INSTANCE_LEAF_NODE);
+ } else {
+ return (isListEntry(name) ? NodeType.MULTI_INSTANCE_NODE :
+ NodeType.SINGLE_INSTANCE_NODE);
+ }
+ }
+
+ /**
+ * Returns revision in string.
+ *
+ * @param r YANG revision
+ * @return revision in string
+ */
+ public static String getRevision(Optional<Revision> r) {
+ return (r.isPresent()) ? r.get().toString() : null;
+ }
+
+ /**
+ * Returns value namespace for leaf value.
+ *
+ * @param value value of the leaf
+ * @param ctx schema context
+ * @return value namespace
+ * @throws SvcLogicException if identity/module could not be found
+ */
+ static Namespace getValueNamespace(String value,
+ SchemaContext ctx)
+ throws SvcLogicException {
+ String prefix = getPrefixFromValue(value);
+ if (prefix == null) {
+ return null;
+ }
+
+ IdentitySchemaNode id = IdentityCodecUtil.parseIdentity(value,
+ ctx,
+ prefixToModule -> {
+ final Iterator<Module> modules = ctx.findModules(prefix).iterator();
+ checkArgument(modules.hasNext(), "Could not find " +
+ "module %s", prefix);
+ return modules.next().getQNameModule();
+ });
+
+ if (id == null) {
+ throw new SvcLogicException("Could not find identity");
+ }
+
+ return getModuleNamespace(id.getQName(), ctx);
+ }
+
+ private static String getPrefixFromValue(String value) {
+ int lastIndexOfColon = value.lastIndexOf(":");
+ if (lastIndexOfColon != -1) {
+ return value.substring(0, lastIndexOfColon);
+ }
+ return null;
+ }
+
+ /**
+ * Returns module namespace from a given qName.
+ *
+ * @param qName qName of a node
+ * @param ctx schema context
+ * @return module namespace of the node
+ * @throws SvcLogicException when the module is not available
+ */
+ public static Namespace getModuleNamespace(QName qName, SchemaContext ctx)
+ throws SvcLogicException {
+ Optional<Module> module = ctx.findModule(qName.getModule());
+ if (!module.isPresent()) {
+ throw new SvcLogicException("Could not find module node");
+ }
+ Module m = module.get();
+ return new Namespace(m.getName(), m.getQNameModule().getNamespace(),
+ getRevision(m.getRevision()));
+ }
+
+ static String getParsedValue(Namespace valNs, String value) {
+ if (valNs != null && value.contains(":")) {
+ String[] valArr = value.split(":");
+ return valArr[1];
+ }
+ return value;
+ }
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/MultiInstanceNode.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/MultiInstanceNode.java
new file mode 100644
index 000000000..c251cdaea
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/MultiInstanceNode.java
@@ -0,0 +1,32 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Huawei Technologies Co., Ltd. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.yangserializers.pnserializer;
+
+/**
+ * Representation of multi instance node in properties data tree.
+ */
+public class MultiInstanceNode extends InnerNode<DataNodeChild> implements ListHolderChild {
+
+ public MultiInstanceNode(String name, Namespace namespace, String uri,
+ PropertiesNode parent, Object appinfo, NodeType nodeType) {
+ super(name, namespace, uri, parent, appinfo, nodeType);
+ }
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/Namespace.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/Namespace.java
new file mode 100644
index 000000000..4f27ee1e7
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/Namespace.java
@@ -0,0 +1,100 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Huawei Technologies Co., Ltd. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.yangserializers.pnserializer;
+
+import java.net.URI;
+
+/**
+ * Representation of YANG namespace.
+ */
+public class Namespace {
+ private String moduleName;
+ private URI moduleNs;
+ private String revision;
+
+ /**
+ * Creates an instance of namespace with specified module name,
+ * namespace and revision.
+ *
+ * @param modulename module name
+ * @param moduleNs module namespace
+ * @param revision revision
+ */
+ public Namespace(String modulename, URI moduleNs, String revision) {
+ this.moduleName = modulename;
+ this.moduleNs = moduleNs;
+ this.revision = revision;
+ }
+
+ /**
+ * Returns module name.
+ *
+ * @return module name
+ */
+ public String moduleName() {
+ return moduleName;
+ }
+
+ /**
+ * Sets module name.
+ *
+ * @param moduleName module name
+ */
+ public void moduleName(String moduleName) {
+ this.moduleName = moduleName;
+ }
+
+ /**
+ * Sets module namespace.
+ *
+ * @return module namespace
+ */
+ public URI moduleNs() {
+ return moduleNs;
+ }
+
+ /**
+ * Sets module namespace.
+ *
+ * @param moduleNs module namespace
+ */
+ public void moduleNs(URI moduleNs) {
+ this.moduleNs = moduleNs;
+ }
+
+ /**
+ * Returns revision.
+ *
+ * @return revision
+ */
+ public String revision() {
+ return revision;
+ }
+
+ /**
+ * Sets revision.
+ *
+ * @param revision revision
+ */
+ public void revision(String revision) {
+ this.revision = revision;
+ }
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/NodeChild.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/NodeChild.java
new file mode 100644
index 000000000..d482c6763
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/NodeChild.java
@@ -0,0 +1,28 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Huawei Technologies Co., Ltd. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.yangserializers.pnserializer;
+
+/**
+ * Abstraction of an entity that represents child's of a node.
+ */
+public interface NodeChild {
+
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/NodeType.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/NodeType.java
new file mode 100644
index 000000000..0b6974e3e
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/NodeType.java
@@ -0,0 +1,34 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Huawei Technologies Co., Ltd. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.yangserializers.pnserializer;
+
+/**
+ * Representation of types of node in properties node tree.
+ */
+public enum NodeType {
+ SINGLE_INSTANCE_NODE,
+ MULTI_INSTANCE_NODE,
+ SINGLE_INSTANCE_LEAF_NODE,
+ MULTI_INSTANCE_LEAF_NODE,
+ MULTI_INSTANCE_HOLDER_NODE,
+ MULTI_INSTANCE_LEAF_HOLDER_NODE,
+ ANY_XML_NODE
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/PropertiesNode.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/PropertiesNode.java
new file mode 100644
index 000000000..7e0ad631e
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/PropertiesNode.java
@@ -0,0 +1,280 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Huawei Technologies Co., Ltd. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.yangserializers.pnserializer;
+
+import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.Multimap;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+
+/**
+ * Abstraction of properties node data tree. This intermediate representation
+ * will enable data format serializers to be agnostic of DG context memory
+ * nuances and thereby will enable faster development of new data format
+ * serializers.
+ */
+public abstract class PropertiesNode {
+
+ private String name;
+ private Namespace namespace;
+ private String uri;
+ private PropertiesNode parent;
+ private Object appInfo;
+ private NodeType nodeType;
+ private boolean nonAppend;
+ private Multimap<Object, PropertiesNode> augmentations = ArrayListMultimap.create();
+
+ /**
+ * Creates an instance of properties node.
+ *
+ * @param name name of node
+ * @param namespace namespace of node, null indicates parent namespace
+ * @param uri URI of this node, if null its calculated based on parent and
+ * current value of name and namespace
+ * @param parent parent's node
+ * @param appInfo application related information
+ * @param nodeType node type
+ */
+ protected PropertiesNode(String name, Namespace namespace, String uri,
+ PropertiesNode parent, Object appInfo, NodeType nodeType) {
+ this.name = name;
+ this.namespace = namespace;
+ this.uri = uri;
+ this.parent = parent;
+ this.appInfo = appInfo;
+ this.nodeType = nodeType;
+ }
+
+ /**
+ * Sets name.
+ *
+ * @param name name of the node
+ */
+ public void name(String name) {
+ this.name = name;
+ }
+
+ /**
+ * Sets namespace.
+ *
+ * @param namespace namespace of the node
+ */
+ public void namespace(Namespace namespace) {
+ this.namespace = namespace;
+ }
+
+ /**
+ * Sets uri.
+ *
+ * @param uri uri of the node
+ */
+ public void uri(String uri) {
+ this.uri = uri;
+ }
+
+ /**
+ * Sets parent node.
+ *
+ * @param parent parent node
+ */
+ public void parent(PropertiesNode parent) {
+ this.parent = parent;
+ }
+
+ /**
+ * Sets application info.
+ *
+ * @param appInfo application info
+ */
+ public void appInfo(Object appInfo) {
+ this.appInfo = appInfo;
+ }
+
+ /**
+ * Sets to true if module name is required in forming a request; false
+ * otherwise.
+ *
+ * @param isNotReq true if required; false otherwise
+ */
+ public void nonAppend(boolean isNotReq) {
+ this.nonAppend = isNotReq;
+ }
+
+ /**
+ * Returns parent.
+ *
+ * @return parent node
+ */
+ public PropertiesNode parent() {
+ return parent;
+ }
+
+ /**
+ * Returns name.
+ *
+ * @return name of the node
+ */
+ public String name() {
+ return name;
+ }
+
+ /**
+ * Returns namespace.
+ *
+ * @return namespace of the node
+ */
+ public Namespace namespace() {
+ return namespace;
+ }
+
+ /**
+ * Returns uri.
+ *
+ * @return uri of the node
+ */
+ public String uri() {
+ return uri;
+ }
+
+ /**
+ * Returns application info.
+ *
+ * @return application info
+ */
+ public Object appInfo() {
+ return appInfo;
+ }
+
+ /**
+ * Returns node type.
+ *
+ * @return node type
+ */
+ public NodeType nodeType() {
+ return nodeType;
+ }
+
+ /**
+ * Returns if module name is required.
+ *
+ * @return status of module name if required
+ */
+ public boolean nonAppend() {
+ return nonAppend;
+ }
+
+ /**
+ * Returns augmentations.
+ *
+ * @return augmentations
+ */
+ public Multimap<Object, PropertiesNode> augmentations() {
+ return augmentations;
+ }
+
+ /**
+ * Sets augmentations.
+ *
+ * @param augmentations augmentations of the node
+ */
+ public void augmentations(Multimap<Object, PropertiesNode> augmentations) {
+ this.augmentations = augmentations;
+ }
+
+ /**
+ * Adds a child to a current node.
+ *
+ * @param name name of child
+ * @param namespace namespace of child, null represents parent namespace
+ * @param type type of node
+ * @param appInfo application info
+ * @return added properties node
+ */
+ public abstract PropertiesNode addChild(String name, Namespace namespace,
+ NodeType type,
+ Object appInfo) throws SvcLogicException;
+
+ /**
+ * Adds a child with value to a current node.
+ *
+ * @param name name of child
+ * @param namespace namespace of child, null represents parent namespace
+ * @param type type of node
+ * @param value value of node
+ * @param valueNs value namespace
+ * @param appInfo application info
+ * @throws SvcLogicException if failed to add child
+ * @return added properties node
+ */
+ public abstract PropertiesNode addChild(String name, Namespace namespace,
+ NodeType type, String value,
+ Namespace valueNs,
+ Object appInfo) throws SvcLogicException;
+
+ /**
+ * Adds a child at a given index to a current node. To be used in case of
+ * leaf holder child's which is multi instance node.
+ *
+ * @param index index at which node is to be added
+ * @param name name of child
+ * @param namespace namespace of child, null represents parent namespace
+ * @param type type of node
+ * @param appInfo application info
+ * @throws SvcLogicException if failed to add child
+ * @return added properties node
+ */
+ public abstract PropertiesNode addChild(String index, String name,
+ Namespace namespace,
+ NodeType type,
+ Object appInfo) throws SvcLogicException;
+
+ /**
+ * Adds a child at a given index to a current node. To be used in case of
+ * leaf holder child's which is multi instance node.
+ *
+ * @param index index at which node is to be added
+ * @param name name of child
+ * @param namespace namespace of child, null represents parent namespace
+ * @param type type of node
+ * @param value value of node
+ * @param valueNs value namespace
+ * @param appInfo application info
+ * @throws SvcLogicException if failed to add child
+ * @return added properties node
+ */
+ public abstract PropertiesNode addChild(String index, String name,
+ Namespace namespace, NodeType type,
+ String value, Namespace valueNs,
+ Object appInfo) throws SvcLogicException;
+
+ /**
+ * Returns root node.
+ *
+ * @return root node
+ */
+ public PropertiesNode endNode() {
+ PropertiesNode node = this;
+ while (node.parent() != null){
+ node = node.parent();
+ }
+ return node;
+ }
+}
+
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/PropertiesNodeListener.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/PropertiesNodeListener.java
new file mode 100644
index 000000000..7b97ffaf8
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/PropertiesNodeListener.java
@@ -0,0 +1,61 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Huawei Technologies Co., Ltd. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.yangserializers.pnserializer;
+
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+
+/**
+ * Abstraction of properties node listener.
+ */
+public interface PropertiesNodeListener {
+
+ /**
+ * Pre-configurations required before starting the walking.
+ *
+ * @param node properties node
+ * @throws SvcLogicException when the pre-configuration fails
+ */
+ void start(PropertiesNode node) throws SvcLogicException;
+
+ /**
+ * Post-configurations required after starting the walking.
+ *
+ * @param node properties node
+ * @throws SvcLogicException when the post-configuration fails
+ */
+ void end(PropertiesNode node) throws SvcLogicException;
+
+ /**
+ * Enters the properties node.
+ *
+ * @param node properties node
+ * @throws SvcLogicException when entering the properties node fails
+ */
+ void enterPropertiesNode(PropertiesNode node) throws SvcLogicException;
+
+ /**
+ * Enters the properties node.
+ *
+ * @param node properties node
+ * @throws SvcLogicException when exiting the properties node fails
+ */
+ void exitPropertiesNode(PropertiesNode node) throws SvcLogicException;
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/PropertiesNodeSerializer.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/PropertiesNodeSerializer.java
new file mode 100644
index 000000000..fe6fed484
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/PropertiesNodeSerializer.java
@@ -0,0 +1,112 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Huawei Technologies Co., Ltd. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.yangserializers.pnserializer;
+
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+
+import java.util.Map;
+
+/**
+ * Abstraction of an entity to enable encoding and decoding of properties
+ * to an abstract properties node tree using YANG based schema.
+ * This serializer will be used by other data format serializers and will keep
+ * them abstract from properties nuances thereby enabling quick addition of any
+ * new data format serializer.
+ *
+ * @param <T> type of schema node
+ * @param <P> schema context of the model
+ */
+public abstract class PropertiesNodeSerializer<T, P> {
+
+ /**
+ * Schema node from which the property is made.
+ */
+ private T schemaNode;
+
+ /**
+ * Schema context of the model.
+ */
+ private P schemaCtx;
+
+ /**
+ * URL pointing to the schema node.
+ */
+ private String uri;
+
+ /**
+ * Creates the properties node serializer.
+ *
+ * @param schemaNode schema node.
+ * @param schemaCtx schema context
+ * @param uri URL of the request
+ */
+ public PropertiesNodeSerializer(T schemaNode, P schemaCtx, String uri) {
+ this.schemaNode = schemaNode;
+ this.schemaCtx = schemaCtx;
+ this.uri = uri;
+ }
+
+ /**
+ * Encodes from properties to properties-node tree.
+ *
+ * @param paramMap parameter map
+ * @throws SvcLogicException fails to encode properties to properties node
+ * @return properties node
+ */
+ public abstract PropertiesNode encode(Map<String, String> paramMap) throws SvcLogicException;
+
+ /**
+ * Decodes from properties-node to properties map.
+ *
+ * @param propertiesNode properties-node
+ * @return parameter map
+ * @throws SvcLogicException fails to decode properties node to properties
+ */
+ public abstract Map<String, String> decode(PropertiesNode propertiesNode)
+ throws SvcLogicException;
+
+ /**
+ * Returns the schema node of the property
+ *
+ * @return schema node
+ */
+ public T schemaNode(){
+ return schemaNode;
+ }
+
+ /**
+ * Returns the schema context
+ *
+ * @return schema node
+ */
+ public P schemaCtx() {
+ return schemaCtx;
+ }
+
+ /**
+ * Returns the URI.
+ *
+ * @return uri
+ */
+ public String uri() {
+ return uri;
+ }
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/PropertiesNodeWalker.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/PropertiesNodeWalker.java
new file mode 100644
index 000000000..36ee4dd9d
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/PropertiesNodeWalker.java
@@ -0,0 +1,38 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Huawei Technologies Co., Ltd. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.yangserializers.pnserializer;
+
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+
+/**
+ * Abstraction of properties node walker
+ */
+public interface PropertiesNodeWalker {
+ /**
+ * Walks the properties node with the listener.
+ *
+ * @param listener properties node listener.
+ * @param propertiesNode properties node
+ * @throws SvcLogicException when walking the properties node fails
+ */
+ void walk(PropertiesNodeListener listener, PropertiesNode propertiesNode)
+ throws SvcLogicException;
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/RootNode.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/RootNode.java
new file mode 100644
index 000000000..c7f7340fd
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/RootNode.java
@@ -0,0 +1,212 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Huawei Technologies Co., Ltd. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.yangserializers.pnserializer;
+
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.opendaylight.yangtools.yang.model.api.AugmentationSchemaNode;
+import org.opendaylight.yangtools.yang.model.api.DataSchemaNode;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.addToAugmentations;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.createNode;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.getAugmentationNode;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.getUri;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.isNamespaceAsParent;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.MdsalPropertiesNodeUtils.resolveName;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.NodeType.MULTI_INSTANCE_HOLDER_NODE;
+import static org.onap.ccsdk.sli.plugins.yangserializers.pnserializer.NodeType.MULTI_INSTANCE_LEAF_HOLDER_NODE;
+import static org.opendaylight.yangtools.yang.data.impl.schema.SchemaUtils.findCorrespondingAugment;
+
+/**
+ * Abstraction of node representing properties data tree.
+ */
+public class RootNode<T extends NodeChild> extends PropertiesNode {
+
+ private Map<String, T> children = new HashMap<String, T>();
+
+ /**
+ * Creates an instance of the root node to build the properties.
+ *
+ * @param name name of the node
+ * @param namespace namespace of the node
+ * @param appInfo application info
+ * @param uri URI of the node
+ */
+ public RootNode(String name, Namespace namespace,
+ Object appInfo, String uri) {
+ super(name, namespace, uri, null, appInfo, null);
+ }
+
+ /**
+ * Returns children.
+ *
+ * @return children
+ */
+ public Map<String, T> children() {
+ return children;
+ }
+
+ /**
+ * Sets children.
+ *
+ * @param children child nodes
+ */
+ public void children(Map<String, T> children) {
+ this.children = children;
+ }
+
+ @Override
+ public PropertiesNode addChild(String name, Namespace namespace,
+ NodeType type,
+ Object appInfo) throws SvcLogicException {
+ PropertiesNode node = ((PropertiesNode) children.get(name));
+ if (node != null) {
+ return node;
+ }
+
+ // get augment schema, if it is augmented node
+ AugmentationSchemaNode augSchema = null;
+ if (((DataSchemaNode) appInfo).isAugmenting()) {
+ augSchema = findCorrespondingAugment(((DataSchemaNode) this.appInfo()),
+ ((DataSchemaNode) appInfo));
+ node = getAugmentationNode(augSchema, this, name);
+ }
+
+ // create node based on type, this api will be invoked only for these three types
+ if (node == null) {
+ String uri = getUri(this, name, namespace);
+ node = createNode(name, namespace, uri, this, appInfo, type);
+ }
+
+ // If namespace is not same as parent then it is augmented node
+ if (augSchema != null && !isNamespaceAsParent(this, node)) {
+ addToAugmentations(augSchema, this, node);
+ } else {
+ children.put(name, ((T) node));
+ }
+ return node;
+ }
+
+ @Override
+ public PropertiesNode addChild(String name, Namespace namespace,
+ NodeType type, String value,
+ Namespace valuens,
+ Object appInfo) throws SvcLogicException {
+ LeafNode node = ((LeafNode) children.get(name));
+ if (node != null) {
+ return node;
+ }
+
+ AugmentationSchemaNode augSchema = null;
+ if (((DataSchemaNode) appInfo).isAugmenting()) {
+ augSchema = findCorrespondingAugment(((DataSchemaNode) this.appInfo()),
+ ((DataSchemaNode) appInfo));
+ }
+
+ String uri = getUri(this, name, namespace);
+ node = new LeafNode(name, namespace, uri, this,
+ appInfo, type, value);
+
+ if (augSchema != null && !isNamespaceAsParent(this, node)) {
+ addToAugmentations(augSchema, this, node);
+ } else {
+ children.put(name, ((T) node));
+ }
+ return node;
+ }
+
+ @Override
+ public PropertiesNode addChild(String index, String name,
+ Namespace namespace, NodeType type,
+ Object appInfo) throws SvcLogicException {
+ String localname = resolveName(name);
+ PropertiesNode node = ((PropertiesNode) children.get(localname));
+ if (node == null) {
+ String uri = getUri(this, name, namespace);
+ AugmentationSchemaNode augSchema = null;
+ if (((DataSchemaNode) appInfo).isAugmenting()) {
+ augSchema = findCorrespondingAugment(((DataSchemaNode) this.appInfo()),
+ ((DataSchemaNode) appInfo));
+ node = getAugmentationNode(augSchema, this, localname);
+ }
+
+ if (node == null) {
+ node = new ListHolderNode(localname, namespace, uri,
+ this, appInfo, MULTI_INSTANCE_HOLDER_NODE);
+ }
+
+ if (augSchema != null && !isNamespaceAsParent(this, node)) {
+ addToAugmentations(augSchema, this, node);
+ } else {
+ children.put(localname, ((T) node));
+ }
+ node = node.addChild(index, localname, namespace, type, appInfo);
+ } else if (node instanceof ListHolderNode) {
+ ListHolderChild child = ((ListHolderNode) node).child(index);
+ node = (child != null ? ((MultiInstanceNode) child) :
+ node.addChild(index, localname, namespace, type, appInfo));
+ } else {
+ throw new SvcLogicException("Duplicate node exist with same node");
+ }
+ return node;
+ }
+
+ @Override
+ public PropertiesNode addChild(String index, String name,
+ Namespace namespace, NodeType type,
+ String value, Namespace valueNs,
+ Object appInfo) throws SvcLogicException {
+ String localName = resolveName(name);
+ PropertiesNode node = ((PropertiesNode) children.get(localName));
+ if (node == null) {
+ String uri = getUri(this, name, namespace);
+ AugmentationSchemaNode augSchema = null;
+ if (((DataSchemaNode) appInfo).isAugmenting()) {
+ augSchema = findCorrespondingAugment(((DataSchemaNode) this.appInfo()),
+ ((DataSchemaNode) appInfo));
+ node = getAugmentationNode(augSchema, this, localName);
+ }
+
+ if (node == null) {
+ node = new LeafListHolderNode(localName, namespace, uri, this,
+ appInfo, MULTI_INSTANCE_LEAF_HOLDER_NODE);
+ }
+
+ if (augSchema != null && !isNamespaceAsParent(this, node)) {
+ addToAugmentations(augSchema, this, node);
+ } else {
+ children.put(localName, ((T) node));
+ }
+ node = node.addChild(index, localName, namespace, type, value, valueNs, appInfo);
+ } else if (node instanceof LeafListHolderNode) {
+ LeafNode child = ((LeafNode) ((HolderNode) node).child(index));
+ node = (child != null ? child : node.addChild(index, localName,
+ namespace, type,
+ value, valueNs,
+ appInfo));
+ } else {
+ throw new SvcLogicException("Duplicate node exist with same node");
+ }
+ return node;
+ }
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/SchemaPathHolder.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/SchemaPathHolder.java
new file mode 100644
index 000000000..4ef1bc664
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/SchemaPathHolder.java
@@ -0,0 +1,77 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - CCSDK
+ * ================================================================================
+ * Copyright (C) 2019 Huawei Technologies Co., Ltd. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.yangserializers.pnserializer;
+
+import org.opendaylight.restconf.common.context.InstanceIdentifierContext;
+
+/**
+ * Representation of a holder for a proper path and its corresponding schema.
+ */
+public class SchemaPathHolder {
+
+ /**
+ * Schema context for the path.
+ */
+ private InstanceIdentifierContext insId;
+
+ /**
+ * Formatted path.
+ */
+ private String uri;
+
+ /**
+ * Constructs schema path holder with path and its schema.
+ *
+ * @param insId instance identifier context
+ * @param uri path
+ */
+ public SchemaPathHolder(InstanceIdentifierContext insId, String uri) {
+ this.insId = insId;
+ this.uri = uri;
+ }
+
+ /**
+ * Returns the instance identifier context of the path.
+ *
+ * @return schema of the path
+ */
+ public InstanceIdentifierContext getInsId() {
+ return insId;
+ }
+
+ /**
+ * Returns the formatted path.
+ *
+ * @return formatted path
+ */
+ public String getUri() {
+ return uri;
+ }
+
+ /**
+ * Sets the formatted path.
+ *
+ * @param uri formatted path
+ */
+ public void setUri(String uri) {
+ this.uri = uri;
+ }
+}
diff --git a/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/SingleInstanceNode.java b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/SingleInstanceNode.java
new file mode 100644
index 000000000..6eb24c1a4
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/SingleInstanceNode.java
@@ -0,0 +1,33 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Huawei Technologies Co., Ltd. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.yangserializers.pnserializer;
+
+/**
+ * Representation of single instance node in properties data tree.
+ */
+public class SingleInstanceNode extends InnerNode<DataNodeChild> implements DataNodeChild {
+
+ public SingleInstanceNode(String name, Namespace namespace, String uri,
+ PropertiesNode parent, Object appInfo,
+ NodeType nodeType) {
+ super(name, namespace, uri, parent, appInfo, nodeType);
+ }
+}
diff --git a/plugins/restconf-client/provider/src/main/resources/OSGI-INF/blueprint/restconf-client-blueprint.xml b/plugins/restconf-client/provider/src/main/resources/OSGI-INF/blueprint/restconf-client-blueprint.xml
new file mode 100755
index 000000000..45c335b13
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/resources/OSGI-INF/blueprint/restconf-client-blueprint.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * ============LICENSE_START=======================================================
+ * ONAP - CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Huawei Technologies Co., Ltd. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ -->
+
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+ xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0"
+ odl:use-default-for-reference-types="true">
+
+ <reference xmlns:ext="http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.0.0"
+ id="restapiCallNodeProvider"
+ interface="org.onap.ccsdk.sli.plugins.restapicall.RestapiCallNode"
+ ext:proxy-method="classes"/>
+
+ <bean id="restconfapiCallNodeProvider" class="org.onap.ccsdk.sli.plugins.restconfapicall.RestconfApiCallNode" >
+ <argument ref="restapiCallNodeProvider"/>
+ </bean>
+
+ <bean id="restconfDiscoveryNodeProvider" class="org.onap.ccsdk.sli.plugins.restconfdiscovery.RestconfDiscoveryNode" >
+ <argument ref="restconfapiCallNodeProvider"/>
+ </bean>
+
+ <service ref="restconfapiCallNodeProvider">
+ <interfaces>
+ <value>org.onap.ccsdk.sli.plugins.restconfapicall.RestconfApiCallNode</value>
+ </interfaces>
+ </service>
+
+ <service ref="restconfDiscoveryNodeProvider">
+ <interfaces>
+ <value>org.onap.ccsdk.sli.plugins.restconfdiscovery.RestconfDiscoveryNode</value>
+ </interfaces>
+ </service>
+
+</blueprint> \ No newline at end of file
diff --git a/plugins/restconf-client/provider/src/main/resources/org/opendaylight/blueprint/restconf-client-blueprint.xml b/plugins/restconf-client/provider/src/main/resources/org/opendaylight/blueprint/restconf-client-blueprint.xml
new file mode 100755
index 000000000..45c335b13
--- /dev/null
+++ b/plugins/restconf-client/provider/src/main/resources/org/opendaylight/blueprint/restconf-client-blueprint.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * ============LICENSE_START=======================================================
+ * ONAP - CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Huawei Technologies Co., Ltd. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ -->
+
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+ xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0"
+ odl:use-default-for-reference-types="true">
+
+ <reference xmlns:ext="http://aries.apache.org/blueprint/xmlns/blueprint-ext/v1.0.0"
+ id="restapiCallNodeProvider"
+ interface="org.onap.ccsdk.sli.plugins.restapicall.RestapiCallNode"
+ ext:proxy-method="classes"/>
+
+ <bean id="restconfapiCallNodeProvider" class="org.onap.ccsdk.sli.plugins.restconfapicall.RestconfApiCallNode" >
+ <argument ref="restapiCallNodeProvider"/>
+ </bean>
+
+ <bean id="restconfDiscoveryNodeProvider" class="org.onap.ccsdk.sli.plugins.restconfdiscovery.RestconfDiscoveryNode" >
+ <argument ref="restconfapiCallNodeProvider"/>
+ </bean>
+
+ <service ref="restconfapiCallNodeProvider">
+ <interfaces>
+ <value>org.onap.ccsdk.sli.plugins.restconfapicall.RestconfApiCallNode</value>
+ </interfaces>
+ </service>
+
+ <service ref="restconfDiscoveryNodeProvider">
+ <interfaces>
+ <value>org.onap.ccsdk.sli.plugins.restconfdiscovery.RestconfDiscoveryNode</value>
+ </interfaces>
+ </service>
+
+</blueprint> \ No newline at end of file
diff --git a/plugins/restconf-client/provider/src/test/java/org/onap/ccsdk/sli/plugins/restconfdiscovery/SseServerMock.java b/plugins/restconf-client/provider/src/test/java/org/onap/ccsdk/sli/plugins/restconfdiscovery/SseServerMock.java
new file mode 100644
index 000000000..35ac221fb
--- /dev/null
+++ b/plugins/restconf-client/provider/src/test/java/org/onap/ccsdk/sli/plugins/restconfdiscovery/SseServerMock.java
@@ -0,0 +1,68 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Huawei Technologies Co., Ltd. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.ccsdk.sli.plugins.restconfdiscovery;
+
+import org.glassfish.jersey.media.sse.EventOutput;
+import org.glassfish.jersey.media.sse.OutboundEvent;
+import org.glassfish.jersey.media.sse.SseFeature;
+
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import java.io.IOException;
+
+@Path("events")
+public class SseServerMock {
+
+ @GET
+ @Produces(SseFeature.SERVER_SENT_EVENTS)
+ public EventOutput getServerSentEvents() throws IOException {
+ String data = "{" +
+ "\"ietf-restconf:notification\" : {" +
+ " \"eventTime\" : \"2017-10-25T08:22:33.44Z\"," +
+ " \"ietf-yang-push:push-change-update\": {" +
+ "\"subscription-id\":\"89\"," +
+ "\"datastore-changes\": {" +
+ "\"ietf-yang-patch:yang-patch\":{" +
+ "\"patch-id\":\"1\"," +
+ "\"edit\":[{" +
+ "\"edit-id\":\"edit1\"," +
+ "\"operation\":\"merge\"," +
+ "\"target\":\"/ietf-interfaces:interfaces-state\"," +
+ "\"value\": {" +
+ "\"ietf-interfaces:interfaces-state\":{"+
+ "\"interface\": {" +
+ "\"name\":\"eth0\"," +
+ "\"oper-status\":\"down\"," +
+ "}" +
+ "}" +
+ "}" +
+ "}]"+
+ "}" +
+ "}" +
+ "}" +
+ "}" +
+ "}";
+ final EventOutput result = new EventOutput();
+ result.write(new OutboundEvent.Builder().data(String.class, data).build());
+ result.close();
+ return result;
+ }
+}
diff --git a/plugins/restconf-client/provider/src/test/java/org/onap/ccsdk/sli/plugins/restconfdiscovery/TestRestconfDiscoveryNode.java b/plugins/restconf-client/provider/src/test/java/org/onap/ccsdk/sli/plugins/restconfdiscovery/TestRestconfDiscoveryNode.java
new file mode 100644
index 000000000..aa89d67d7
--- /dev/null
+++ b/plugins/restconf-client/provider/src/test/java/org/onap/ccsdk/sli/plugins/restconfdiscovery/TestRestconfDiscoveryNode.java
@@ -0,0 +1,175 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Huawei Technologies Co., Ltd. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.restconfdiscovery;
+
+import org.glassfish.grizzly.http.server.HttpServer;
+import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
+import org.glassfish.jersey.media.sse.SseFeature;
+import org.glassfish.jersey.server.ResourceConfig;
+import org.junit.Test;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.plugins.restapicall.RestapiCallNode;
+import org.onap.ccsdk.sli.plugins.restconfapicall.RestconfApiCallNode;
+
+import java.io.IOException;
+import java.net.URI;
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.Is.is;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+
+public class TestRestconfDiscoveryNode {
+
+ private static final URI CONTEXT = URI.create("http://localhost:8080/");
+
+ @Test
+ public void sendRequest() throws SvcLogicException, InterruptedException, IOException {
+ final ResourceConfig resourceConfig = new ResourceConfig(
+ SseServerMock.class, SseFeature.class);
+ HttpServer server = GrizzlyHttpServerFactory.createHttpServer(CONTEXT,
+ resourceConfig);
+ server.start();
+ RestconfApiCallNode restconf = mock(RestconfApiCallNode.class);
+ doNothing().when(restconf)
+ .sendRequest(any(Map.class), any(SvcLogicContext.class));
+ RestapiCallNode restApi = new RestapiCallNode();
+ doReturn(restApi).when(restconf).getRestapiCallNode();
+
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute("prop.encoding-json", "encoding-json");
+ ctx.setAttribute("restapi-result.response-code", "200");
+ ctx.setAttribute("restapi-result.ietf-subscribed-notifications" +
+ ":establish-subscription.output.identifier",
+ "89");
+
+ Map<String, String> p = new HashMap<>();
+ p.put("sseConnectURL", "http://localhost:8080/events");
+ p.put("subscriberId", "networkId");
+ p.put("responsePrefix", "restapi-result");
+ p.put("restapiUser", "access");
+ p.put("restapiPassword", "abc@123");
+ p.put("customHttpHeaders", "X-ACCESS-TOKEN=x-ik2ps4ikvzupbx0486ft" +
+ "1ebzs7rt85futh9ho6eofy3wjsap7wqktemlqm4bbsmnar3vrtbyrzuk" +
+ "bv5itd6m1cftldpjarnyle3sdcqq9hftc4lebz464b5ffxmlbvg9");
+ p.put("restapiUrl", "https://localhost:8080/restconf/operations/" +
+ "ietf-subscribed-notifications:establish-subscription");
+ p.put("module", "testmodule");
+ p.put("rpc", "testrpc");
+ p.put("version", "1.0");
+ p.put("mode", "sync");
+ RestconfDiscoveryNode rdn = new RestconfDiscoveryNode(restconf);
+ rdn.establishSubscription(p, ctx);
+ Thread.sleep(1000);
+ rdn.deleteSubscription(p, ctx);
+ server.shutdown();
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void testSubGraphExecution() throws SvcLogicException{
+ SvcLogicGraphInfo subDg = new SvcLogicGraphInfo();
+ subDg.mode("sync");
+ subDg.module("l3VpnService");
+ subDg.rpc("createVpn");
+ subDg.version("1.0");
+ SvcLogicContext ctx = new SvcLogicContext();
+ subDg.executeGraph(ctx);
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void testEstablishSubscriptionWithoutSubscriberId()
+ throws SvcLogicException{
+ SvcLogicContext ctx = new SvcLogicContext();
+ Map<String, String> p = new HashMap<>();
+ RestconfDiscoveryNode rdn = new RestconfDiscoveryNode(
+ new RestconfApiCallNode(new RestapiCallNode()));
+ rdn.establishSubscription(p, ctx);
+ }
+
+ @Test
+ public void testResponseCode() {
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute("restapi-result.response-code", "200");
+ ctx.setAttribute("response-code", "404");
+ RestconfDiscoveryNode rdn = new RestconfDiscoveryNode(
+ new RestconfApiCallNode(new RestapiCallNode()));
+ assertThat(rdn.getResponseCode("restapi-result", ctx),
+ is("200"));
+ assertThat(rdn.getResponseCode(null, ctx),
+ is("404"));
+ }
+
+ @Test
+ public void testOutputIdentifier() {
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute("restapi-result.ietf-subscribed-notifications:" +
+ "establish-subscription.output.identifier",
+ "89");
+ ctx.setAttribute("ietf-subscribed-notifications:establish-subscripti" +
+ "on.output.identifier", "89");
+ RestconfDiscoveryNode rdn = new RestconfDiscoveryNode(
+ new RestconfApiCallNode(new RestapiCallNode()));
+ assertThat(rdn.getOutputIdentifier("restapi-result", ctx),
+ is("89"));
+ }
+
+ @Test
+ public void testGetTokenId() {
+ String customHttpHeaders = "X-ACCESS-TOKEN=x-ik2ps4ikvzupbx0486ft1ebzs7rt85" +
+ "futh9ho6eofy3wjsap7wqktemlqm4bbsmnar3vrtbyrzukbv5itd6m1cftldpjarny" +
+ "le3sdcqq9hftc4lebz464b5ffxmlbvg9";
+ RestconfDiscoveryNode rdn = new RestconfDiscoveryNode(
+ new RestconfApiCallNode(new RestapiCallNode()));
+
+ assertThat(rdn.getTokenId(customHttpHeaders),
+ is("x-ik2ps4ikvzupbx0486ft1ebzs7rt85futh9ho6eofy3wjsap7wqkt" +
+ "emlqm4bbsmnar3vrtbyrzukbv5itd6m1cftldpjarnyle3sdcqq9h" +
+ "ftc4lebz464b5ffxmlbvg9"));
+ }
+
+ @Test
+ public void testSubscriptionInfo() throws SvcLogicException {
+ SubscriptionInfo info = new SubscriptionInfo();
+ info.subscriberId("network-id");
+ info.subscriptionId("8");
+ info.filterUrl("/ietf-interfaces:interfaces");
+ info.yangFilePath("/opt/yang");
+ SvcLogicGraphInfo svcLogicGraphInfo = new SvcLogicGraphInfo();
+ svcLogicGraphInfo.mode("sync");
+ svcLogicGraphInfo.module("testModule");
+ svcLogicGraphInfo.rpc("testRpc");
+ svcLogicGraphInfo.version("1.0");
+ info.callBackDG(svcLogicGraphInfo);
+ assertThat(info.subscriberId(), is("network-id"));
+ assertThat(info.subscriptionId(), is("8"));
+ assertThat(info.filterUrl(), is("/ietf-interfaces:interfaces"));
+ assertThat(info.yangFilePath(), is("/opt/yang"));
+ assertThat(info.callBackDG().module(), is("testModule"));
+ assertThat(info.callBackDG().mode(), is("sync"));
+ assertThat(info.callBackDG().rpc(), is("testRpc"));
+ assertThat(info.callBackDG().version(), is("1.0"));
+ }
+}
diff --git a/plugins/restconf-client/provider/src/test/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DataFormatSerializerTest.java b/plugins/restconf-client/provider/src/test/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DataFormatSerializerTest.java
new file mode 100644
index 000000000..aa1e50d6a
--- /dev/null
+++ b/plugins/restconf-client/provider/src/test/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DataFormatSerializerTest.java
@@ -0,0 +1,996 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Huawei Technologies Co., Ltd. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.yangserializers.dfserializer;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.plugins.restapicall.HttpResponse;
+import org.onap.ccsdk.sli.plugins.restapicall.RestapiCallNode;
+import org.onap.ccsdk.sli.plugins.restconfapicall.RestconfApiCallNode;
+import org.opendaylight.restconf.common.context.InstanceIdentifierContext;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.Is.is;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doCallRealMethod;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.onap.ccsdk.sli.plugins.restapicall.HttpMethod.GET;
+import static org.onap.ccsdk.sli.plugins.restapicall.HttpMethod.PATCH;
+import static org.onap.ccsdk.sli.plugins.restapicall.HttpMethod.POST;
+import static org.onap.ccsdk.sli.plugins.restapicall.HttpMethod.PUT;
+import static org.onap.ccsdk.sli.plugins.restconfapicall.RestconfApiUtils.parseUrl;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DataFormatUtilsTest.DECODE_ANYXML_RESPONSE;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DataFormatUtilsTest.DECODE_FROM_JSON_RPC;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DataFormatUtilsTest.DECODE_FROM_XML_RPC;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DataFormatUtilsTest.ENCODE_TO_ANYXML;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DataFormatUtilsTest.ENCODE_TO_JSON_ID;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DataFormatUtilsTest.ENCODE_TO_JSON_ID_PUT;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DataFormatUtilsTest.ENCODE_TO_JSON_RPC;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DataFormatUtilsTest.ENCODE_TO_JSON_YANG;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DataFormatUtilsTest.ENCODE_TO_JSON_YANG_AUG_POST;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DataFormatUtilsTest.ENCODE_TO_JSON_YANG_PUT;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DataFormatUtilsTest.ENCODE_TO_XML_ID;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DataFormatUtilsTest.ENCODE_TO_XML_ID_PUT;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DataFormatUtilsTest.ENCODE_TO_XML_RPC;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DataFormatUtilsTest.ENCODE_TO_XML_YANG;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DataFormatUtilsTest.ENCODE_TO_XML_YANG_AUG_POST;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DataFormatUtilsTest.ENCODE_TO_XML_YANG_PUT;
+
+
+/**
+ * Unit test cases for data format serialization and restconf api call node.
+ */
+public class DataFormatSerializerTest {
+
+ private Map<String, String> p;
+
+ private RestconfApiCallNode restconf;
+
+ private RestapiCallNode restApi;
+
+ private DfCaptor dfCaptor;
+
+ /**
+ * Sets up the pre-requisite for each test case.
+ *
+ * @throws SvcLogicException when test case fails
+ */
+ @Before
+ public void setUp() throws SvcLogicException {
+ p = new HashMap<>();
+ p.put("restapiUser", "user1");
+ p.put("restapiPassword", "abc123");
+ p.put("responsePrefix", "response");
+ p.put("skipSending", "true");
+ restApi = new RestapiCallNode();
+ restconf = mock(RestconfApiCallNode.class);
+ dfCaptor = new DfCaptor();
+ createMethodMocks();
+ }
+
+ /**
+ * Creates method mocks using mockito for RestconfApiCallNode class.
+ *
+ * @throws SvcLogicException when test case fails
+ */
+ private void createMethodMocks() throws SvcLogicException {
+ doReturn(restApi).when(restconf).getRestapiCallNode();
+ doCallRealMethod().when(restconf).sendRequest(
+ any(Map.class), any(SvcLogicContext.class));
+ doCallRealMethod().when(restconf).sendRequest(
+ any(Map.class), any(SvcLogicContext.class), any(Integer.class));
+ doAnswer(dfCaptor).when(restconf).serializeRequest(
+ any(Map.class), any(YangParameters.class), any(String.class),
+ any(InstanceIdentifierContext.class));
+ doAnswer(dfCaptor).when(restconf).updateReq(
+ any(String.class), any(YangParameters.class),
+ any(InstanceIdentifierContext.class));
+ }
+
+ /**
+ * Creates mock using mockito with input data for decoding.
+ *
+ * @param decodeData input data
+ * @throws SvcLogicException when test case fails
+ */
+ private void createMockForDecode(String decodeData)
+ throws SvcLogicException {
+ doReturn(decodeData).when(restconf).getResponse(
+ any(SvcLogicContext.class), any(YangParameters.class),
+ any(String.class), any(HttpResponse.class));
+ doCallRealMethod().when(restconf).serializeResponse(
+ any(YangParameters.class), any(String.class), any(String.class),
+ any(InstanceIdentifierContext.class));
+ }
+
+ /**
+ * Verifies encoding of parameters to JSON data format with identity-ref
+ * and inter-file linking.
+ *
+ * @throws SvcLogicException when test case fails
+ */
+ @Test
+ public void encodeToJsonId() throws SvcLogicException {
+ String pre = "identity-test_test.";
+ SvcLogicContext ctx = createAttList(pre);
+ ctx.setAttribute(pre + "l", "abc");
+ p.put("dirPath", "src/test/resources");
+ p.put("format", "json");
+ p.put("httpMethod", "post");
+ p.put("restapiUrl", "http://echo.getpostman" +
+ ".com/restconf/operations/identity-test:test");
+ restconf.sendRequest(p, ctx);
+ assertThat(dfCaptor.getResult(), is(ENCODE_TO_JSON_ID));
+ }
+
+ /**
+ * Verifies encoding of parameters to JSON data format any xml in it.
+ *
+ * @throws SvcLogicException when test case fails
+ */
+ @Test
+ public void encodeForAnyXml() throws SvcLogicException {
+ String pre = "execution-service_process.";
+ SvcLogicContext ctx = createAnyXmlAttList(pre);
+ p.put("dirPath", "src/test/resources");
+ p.put("format", "json");
+ p.put("httpMethod", "post");
+ p.put("restapiUrl", "http://echo.getpostman" +
+ ".com/api/v1/execution-service/process");
+ restconf.sendRequest(p, ctx);
+ assertThat(dfCaptor.getResult(), is(ENCODE_TO_ANYXML));
+ }
+
+ /**
+ * Verifies encoding of parameters to JSON data format with identity-ref
+ * and inter-file linking for put operation-type.
+ *
+ * @throws SvcLogicException when test case fails
+ */
+ @Test
+ public void encodeToJsonIdWithPut() throws SvcLogicException {
+ String pre = "identity-test_test.";
+ SvcLogicContext ctx = createAttList(pre);
+ ctx.setAttribute(pre + "l", "abc");
+ p.put("dirPath", "src/test/resources");
+ p.put("format", "json");
+ p.put("httpMethod", "put");
+ p.put("restapiUrl", "http://echo.getpostman" +
+ ".com/restconf/operations/identity-test:test");
+ restconf.sendRequest(p, ctx);
+ assertThat(dfCaptor.getResult(), is(ENCODE_TO_JSON_ID_PUT));
+ }
+
+ /**
+ * Verifies encoding of parameters to JSON data format with identity-ref
+ * and inter-file linking for patch operation-type.
+ *
+ * @throws SvcLogicException when test case fails
+ */
+ @Test
+ public void encodeToJsonIdWithPatch() throws SvcLogicException {
+ String pre = "identity-test_test.";
+ SvcLogicContext ctx = createAttList(pre);
+ ctx.setAttribute(pre + "l", "abc");
+ p.put("dirPath", "src/test/resources");
+ p.put("format", "json");
+ p.put("httpMethod", "patch");
+ p.put("restapiUrl", "http://echo.getpostman" +
+ ".com/restconf/operations/identity-test:test");
+ restconf.sendRequest(p, ctx);
+ assertThat(dfCaptor.getResult(), is(ENCODE_TO_JSON_ID_PUT));
+ }
+
+ /**
+ * Verifies encoding of parameters to XML data format with identity-ref
+ * and inter-file linking.
+ *
+ * @throws SvcLogicException when test case fails
+ */
+ @Test
+ public void encodeToXmlId() throws SvcLogicException {
+ String pre = "identity-test_test.";
+ SvcLogicContext ctx = createAttList(pre);
+ p.put("dirPath", "src/test/resources");
+ p.put("format", "xml");
+ p.put("httpMethod", "post");
+ p.put("restapiUrl", "http://echo.getpostman" +
+ ".com/restconf/operations/identity-test:test");
+ restconf.sendRequest(p, ctx);
+ assertThat(dfCaptor.getResult(), is(ENCODE_TO_XML_ID));
+ }
+
+ /**
+ * Verifies encoding of parameters to XML data format with identity-ref
+ * and inter-file linking for put operation-type.
+ *
+ * @throws SvcLogicException when test case fails
+ */
+ @Test
+ public void encodeToXmlIdWithPut() throws SvcLogicException {
+ String pre = "identity-test_test.";
+ SvcLogicContext ctx = createAttList(pre);
+ p.put("dirPath", "src/test/resources");
+ p.put("format", "xml");
+ p.put("httpMethod", "put");
+ p.put("restapiUrl", "http://echo.getpostman" +
+ ".com/restconf/operations/identity-test:test");
+ restconf.sendRequest(p, ctx);
+ assertThat(dfCaptor.getResult(), is(ENCODE_TO_XML_ID_PUT));
+ }
+
+ /**
+ * Verifies encoding of parameters to XML data format with identity-ref
+ * and inter-file linking for patch operation-type.
+ *
+ * @throws SvcLogicException when test case fails
+ */
+ @Test
+ public void encodeToXmlIdWithPatch() throws SvcLogicException {
+ String pre = "identity-test_test.";
+ SvcLogicContext ctx = createAttList(pre);
+ p.put("dirPath", "src/test/resources");
+ p.put("format", "xml");
+ p.put("httpMethod", "patch");
+ p.put("restapiUrl", "http://echo.getpostman" +
+ ".com/restconf/operations/identity-test:test");
+ restconf.sendRequest(p, ctx);
+ assertThat(dfCaptor.getResult(), is(ENCODE_TO_XML_ID_PUT));
+ }
+
+ /**
+ * Verifies decoding of parameters from JSON data format with identity-ref
+ * and inter-file linking.
+ *
+ * @throws SvcLogicException when test case fails
+ */
+ @Test
+ public void decodeToJsonId() throws SvcLogicException {
+ createMockForDecode(ENCODE_TO_JSON_ID);
+ SvcLogicContext ctx = new SvcLogicContext();
+ String pre = "identity-test_test.";
+ p.put("dirPath", "src/test/resources");
+ p.put("format", "json");
+ p.put("httpMethod", "get");
+ p.put("restapiUrl", "http://echo.getpostman" +
+ ".com/restconf/operations/identity-test:test");
+ restconf.sendRequest(p, ctx);
+ assertThat(ctx.getAttribute(pre + "l"), is("abc"));
+ verifyAttList(ctx, pre);
+ }
+
+ /**
+ * Verifies decoding of parameters from XML data format with identity-ref
+ * and inter-file linking.
+ *
+ * @throws SvcLogicException when test case fails
+ */
+ @Test
+ public void decodeToXmlId() throws SvcLogicException {
+ createMockForDecode(ENCODE_TO_XML_ID);
+ SvcLogicContext ctx = new SvcLogicContext();
+ String pre = "identity-test_test.";
+ p.put("dirPath", "src/test/resources");
+ p.put("format", "xml");
+ p.put("httpMethod", "get");
+ p.put("restapiUrl", "http://echo.getpostman" +
+ ".com/restconf/operations/identity-test:test");
+ restconf.sendRequest(p, ctx);
+ verifyAttList(ctx, pre);
+ }
+
+ /**
+ * Verifies encoding of parameters to JSON data format with containers,
+ * grouping and augment.
+ *
+ * @throws SvcLogicException when test case fails
+ */
+ @Test
+ public void encodeToJsonYang() throws SvcLogicException {
+ String pre = "test-yang_cont1.cont2.";
+ SvcLogicContext ctx = createAttListYang(pre);
+ p.put("dirPath", "src/test/resources");
+ p.put("format", "json");
+ p.put("httpMethod", "post");
+ p.put("restapiUrl", "http://echo.getpostman" +
+ ".com/restconf/operations/test-yang:cont1");
+ restconf.sendRequest(p, ctx);
+ assertThat(dfCaptor.getResult(), is(ENCODE_TO_JSON_YANG));
+ }
+
+ /**
+ * Verifies encoding of parameters to JSON data format with containers,
+ * grouping and augment for put operation-type.
+ *
+ * @throws SvcLogicException when test case fails
+ */
+ @Test
+ public void encodeToJsonYangWithPut() throws SvcLogicException {
+ String pre = "test-yang_cont1.cont2.";
+ SvcLogicContext ctx = createAttListYang(pre);
+ p.put("dirPath", "src/test/resources");
+ p.put("format", "json");
+ p.put("httpMethod", "put");
+ p.put("restapiUrl", "http://echo.getpostman" +
+ ".com/restconf/operations/test-yang:cont1/cont2/cont4");
+ restconf.sendRequest(p, ctx);
+ assertThat(dfCaptor.getResult(), is(ENCODE_TO_JSON_YANG_PUT));
+ }
+
+ /**
+ * Verifies encoding of parameters to JSON data format with containers,
+ * grouping and augment for patch operation-type.
+ *
+ * @throws SvcLogicException when test case fails
+ */
+ @Test
+ public void encodeToJsonYangWithPatch() throws SvcLogicException {
+ String pre = "test-yang_cont1.cont2.";
+ SvcLogicContext ctx = createAttListYang(pre);
+ p.put("dirPath", "src/test/resources");
+ p.put("format", "json");
+ p.put("httpMethod", "patch");
+ p.put("restapiUrl", "http://echo.getpostman" +
+ ".com/restconf/operations/test-yang:cont1/cont2/cont4");
+ restconf.sendRequest(p, ctx);
+ assertThat(dfCaptor.getResult(), is(ENCODE_TO_JSON_YANG_PUT));
+ }
+
+ /**
+ * Verifies encoding of parameters to JSON data format with augment as
+ * root child.
+ *
+ * @throws SvcLogicException when test case fails
+ */
+ @Test
+ public void encodeToJsonWithAugAsRootChild() throws SvcLogicException {
+ String pre = "test-yang_cont1.cont2.";
+ SvcLogicContext ctx = createAttListYang(pre);
+ p.put("dirPath", "src/test/resources");
+ p.put("format", "json");
+ p.put("httpMethod", "post");
+ p.put("restapiUrl", "http://echo.getpostman" +
+ ".com/restconf/operations/test-yang:cont1/cont2/cont4");
+ restconf.sendRequest(p, ctx);
+ assertThat(dfCaptor.getResult(), is(ENCODE_TO_JSON_YANG_AUG_POST));
+ }
+
+ /**
+ * Verifies decoding of parameters from JSON data format with containers,
+ * grouping and augment.
+ *
+ * @throws SvcLogicException when test case fails
+ */
+ @Test
+ public void decodeToJsonYang() throws SvcLogicException {
+ createMockForDecode(ENCODE_TO_JSON_YANG);
+ SvcLogicContext ctx = new SvcLogicContext();
+ String pre = "test-yang_cont1.cont2.";
+ p.put("dirPath", "src/test/resources");
+ p.put("format", "json");
+ p.put("httpMethod", "get");
+ p.put("restapiUrl", "http://echo.getpostman" +
+ ".com/restconf/operations/test-yang:cont1");
+ restconf.sendRequest(p, ctx);
+ verifyAttListYang(ctx, pre);
+ }
+
+ /**
+ * Verifies encoding of parameters to XML data format with containers,
+ * grouping and augment.
+ *
+ * @throws SvcLogicException when test case fails
+ */
+ @Test
+ public void encodeToXmlYang() throws SvcLogicException {
+ String pre = "test-yang_cont1.cont2.";
+ SvcLogicContext ctx = createAttListYang(pre);
+ p.put("dirPath", "src/test/resources");
+ p.put("format", "xml");
+ p.put("httpMethod", "post");
+ p.put("restapiUrl", "http://echo.getpostman" +
+ ".com/restconf/operations/test-yang:cont1");
+ restconf.sendRequest(p, ctx);
+ assertThat(dfCaptor.getResult(), is(ENCODE_TO_XML_YANG));
+ }
+
+ /**
+ * Verifies encoding of parameters to XML data format with containers,
+ * grouping and augment for put operation-type
+ *
+ * @throws SvcLogicException when test case fails
+ */
+ @Test
+ public void encodeToXmlYangWithPut() throws SvcLogicException {
+ String pre = "test-yang_cont1.cont2.";
+ SvcLogicContext ctx = createAttListYang(pre);
+ p.put("dirPath", "src/test/resources");
+ p.put("format", "xml");
+ p.put("httpMethod", "put");
+ p.put("restapiUrl", "http://echo.getpostman" +
+ ".com/restconf/operations/test-yang:cont1/cont2/cont4");
+ restconf.sendRequest(p, ctx);
+ assertThat(dfCaptor.getResult(), is(ENCODE_TO_XML_YANG_PUT));
+ }
+
+ /**
+ * Verifies encoding of parameters to XML data format with containers,
+ * grouping and augment for patch operation-type
+ *
+ * @throws SvcLogicException when test case fails
+ */
+ @Test
+ public void encodeToXmlYangWithPatch() throws SvcLogicException {
+ String pre = "test-yang_cont1.cont2.";
+ SvcLogicContext ctx = createAttListYang(pre);
+ p.put("dirPath", "src/test/resources");
+ p.put("format", "xml");
+ p.put("httpMethod", "put");
+ p.put("restapiUrl", "http://echo.getpostman" +
+ ".com/restconf/operations/test-yang:cont1/cont2/cont4");
+ restconf.sendRequest(p, ctx);
+ assertThat(dfCaptor.getResult(), is(ENCODE_TO_XML_YANG_PUT));
+ }
+
+ /**
+ * Verifies encoding of parameters to XML data format with augment as
+ * root child.
+ *
+ * @throws SvcLogicException when test case fails
+ */
+ @Test
+ public void encodeToXmlWithAugAsRootChild() throws SvcLogicException {
+ String pre = "test-yang_cont1.cont2.";
+ SvcLogicContext ctx = createAttListYang(pre);
+ p.put("dirPath", "src/test/resources");
+ p.put("format", "xml");
+ p.put("httpMethod", "post");
+ p.put("restapiUrl", "http://echo.getpostman" +
+ ".com/restconf/operations/test-yang:cont1/cont2/cont4");
+ restconf.sendRequest(p, ctx);
+ assertThat(dfCaptor.getResult(), is(ENCODE_TO_XML_YANG_AUG_POST));
+ }
+
+ /**
+ * Verifies decoding of parameters from XML data format with containers,
+ * grouping and augment.
+ *
+ * @throws SvcLogicException when test case fails
+ */
+ @Test
+ public void decodeToXmlYang() throws SvcLogicException {
+ createMockForDecode(ENCODE_TO_XML_YANG);
+ SvcLogicContext ctx = new SvcLogicContext();
+ String pre = "test-yang_cont1.cont2.";
+ p.put("dirPath", "src/test/resources");
+ p.put("format", "xml");
+ p.put("httpMethod", "get");
+ p.put("restapiUrl", "http://echo.getpostman" +
+ ".com/restconf/operations/test-yang:cont1");
+ restconf.sendRequest(p, ctx);
+ verifyAttListYang(ctx, pre);
+ }
+
+ /**
+ * Verifies encoding of and decoding from, JSON respectively for data
+ * format with containers, grouping and augment.
+ *
+ * @throws SvcLogicException when test case fails
+ */
+ @Test
+ public void codecToJsonRpc() throws SvcLogicException {
+ createMockForDecode(DECODE_FROM_JSON_RPC);
+ String inPre = "test-yang_create-sfc.input.";
+ String outPre = "test-yang_create-sfc.output.";
+ SvcLogicContext ctx = createAttListRpc(inPre);
+ p.put("dirPath", "src/test/resources");
+ p.put("format", "json");
+ p.put("httpMethod", "post");
+ p.put("restapiUrl", "http://echo.getpostman" +
+ ".com/restconf/operations/test-yang:create-sfc");
+ restconf.sendRequest(p, ctx);
+ assertThat(dfCaptor.getResult(), is(ENCODE_TO_JSON_RPC));
+ verifyAttListRpc(ctx, outPre);
+ }
+
+ /**
+ * Verifies encoding of and decoding from, JSON for ANYXML.
+ *
+ * @throws SvcLogicException when test case fails
+ */
+ @Test
+ public void codecForNormalAnyXml() throws SvcLogicException {
+ createMockForDecode(DECODE_ANYXML_RESPONSE);
+ String inPre = "execution-service_process.";
+ SvcLogicContext ctx = createAnyXmlAttList(inPre);
+ p.put("dirPath", "src/test/resources");
+ p.put("format", "json");
+ p.put("httpMethod", "post");
+ p.put("responsePrefix", "pp");
+ p.put("restapiUrl", "http://echo.getpostman" +
+ ".com/api/v1/execution-service/process");
+ restconf.sendRequest(p, ctx);
+ assertThat(dfCaptor.getResult(), is(ENCODE_TO_ANYXML));
+ verifyOutputOfAnyXml(ctx);
+ }
+
+ /**
+ * Verifies encoding of and decoding from, XML respectively for data
+ * format with containers, grouping and augment.
+ *
+ * @throws SvcLogicException when test case fails
+ */
+ @Test
+ public void codecToXmlRpc() throws SvcLogicException {
+ createMockForDecode(DECODE_FROM_XML_RPC);
+ String inPre = "test-yang_create-sfc.input.";
+ String outPre = "test-yang_create-sfc.output.";
+ SvcLogicContext ctx = createAttListRpc(inPre);
+ p.put("dirPath", "src/test/resources");
+ p.put("format", "xml");
+ p.put("httpMethod", "post");
+ p.put("restapiUrl", "http://echo.getpostman" +
+ ".com/restconf/operations/test-yang:create-sfc");
+ restconf.sendRequest(p, ctx);
+ assertThat(dfCaptor.getResult(), is(ENCODE_TO_XML_RPC));
+ verifyAttListRpc(ctx, outPre);
+ }
+
+ /**
+ * Verifies URL parser returning path with only schema information for all
+ * kind of URL.
+ *
+ * @throws SvcLogicException when test case fails
+ */
+ @Test
+ public void validateUrlParser() throws SvcLogicException {
+ String actVal = "identity-test:test";
+ String putId = "/for-put";
+ String url1 = "http://echo.getpostman.com/restconf/operations/" +
+ actVal;
+ String url2 = "http://echo.getpostman.com/restconf/data/" + actVal;
+ String url3 = "https://echo.getpostman.com/restconf/operations/" +
+ actVal;
+ String url4 = "https://echo.getpostman.com/restconf/data/" + actVal +
+ putId;
+ String url5 = "http://localhost:8282/restconf/operations/" + actVal;
+ String url6 = "https://localhost:8282/restconf/operations/" + actVal;
+ String url7 = "http://localhost:8282/restconf/data/" + actVal +
+ putId;
+ String url8 = "https://localhost:8282/restconf/data/" + actVal;
+ String url9 = "http://182.2.61.24:2250/restconf/data/" + actVal;
+ String url10 = "https://182.2.61.24:2250/restconf/operations/" + actVal;
+ String url11 = "https://182.2.61.24:2250/api/v1/execution-service" +
+ "/process";
+ String url12 = "https://182.2.61.24:2250/api/v1/execution-service" +
+ "/process/payload";
+ String url13 = "https://182.2.61.24:2250/api/v1/execution-service" +
+ "/process/payload/";
+ String val1 = parseUrl(url1, POST);
+ String val2 = parseUrl(url2, GET);
+ String val3 = parseUrl(url3, PATCH);
+ String val4 = parseUrl(url4, PUT);
+ String val5 = parseUrl(url5, GET);
+ String val6 = parseUrl(url6, POST);
+ String val7 = parseUrl(url7, PUT);
+ String val8 = parseUrl(url8, POST);
+ String val9 = parseUrl(url9, GET);
+ String val10 = parseUrl(url10, POST);
+ String val11 = parseUrl(url11, POST);
+ String val12 = parseUrl(url12, POST);
+ String val13 = parseUrl(url13, POST);
+ assertThat(val1, is(actVal));
+ assertThat(val2, is(actVal));
+ assertThat(val3, is(actVal));
+ assertThat(val4, is(actVal + putId));
+ assertThat(val5, is(actVal));
+ assertThat(val6, is(actVal));
+ assertThat(val7, is(actVal + putId));
+ assertThat(val8, is(actVal));
+ assertThat(val9, is(actVal));
+ assertThat(val10, is(actVal));
+ assertThat(val11, is("execution-service:process"));
+ assertThat(val12, is("execution-service:process/payload"));
+ assertThat(val13, is("execution-service:process/payload/"));
+ }
+
+ /**
+ * Creates attribute list for encoding JSON or XML with ANYXML YANG
+ * file.
+ *
+ * @param pre prefix
+ * @return service logic context
+ */
+ private SvcLogicContext createAnyXmlAttList(String pre) {
+ SvcLogicContext ctx = new SvcLogicContext();
+ String pre1 = pre + "commonHeader.";
+ String pre2 = pre + "actionIdentifiers.";
+ ctx.setAttribute(pre + "isNonAppend", "true");
+ ctx.setAttribute(pre1 + "originatorId", "SDNC_DG");
+ ctx.setAttribute(pre1 + "requestId", "123456-1000");
+ ctx.setAttribute(pre1 + "subRequestId", "sub-123456-1000");
+ ctx.setAttribute(pre2 + "blueprintName",
+ "baseconfiguration");
+ ctx.setAttribute(pre2 + "blueprintVersion", "1.0.0");
+ ctx.setAttribute(pre2 + "actionName", "assign-activate");
+ ctx.setAttribute(pre2 + "mode", "sync");
+ ctx.setAttribute(pre + "payload." +
+ "template-prefix", "vDNS-test");
+ ctx.setAttribute(pre + "payload.resource-assignment-request" +
+ ".resource-assignment-properties",
+ "{\n" +
+ " \"service-instance-id\": " +
+ "\"1234\",\n" +
+ " \"vnf-id\": \"3526\",\n" +
+ " \"customer-name\": \"htipl\",\n" +
+ " \"subscriber-name\": \"huawei\"\n" +
+ " }");
+ return ctx;
+ }
+
+ /**
+ * Creates attribute list for encoding JSON or XML with identity-ref YANG
+ * file.
+ *
+ * @param pre prefix
+ * @return service logic context
+ */
+ private SvcLogicContext createAttList(String pre) {
+ SvcLogicContext ctx = new SvcLogicContext();
+ String pre1 = pre + "con1.interfaces.";
+ ctx.setAttribute(pre + "con1.interface", "identity-types:physical");
+ ctx.setAttribute(pre1 + "int-list[0].iden", "optical");
+ ctx.setAttribute(pre1 + "int-list[0].available.ll[0]", "Giga");
+ ctx.setAttribute(pre1 + "int-list[0].available.ll[1]",
+ "identity-types:Loopback");
+ ctx.setAttribute(pre1 + "int-list[0].available.ll[2]",
+ "identity-types-second:Ethernet");
+ ctx.setAttribute(pre1 + "int-list[0].available.leaf1", "58");
+ ctx.setAttribute(pre1 + "int-list[0].available.leaf2",
+ "identity-types-second:iden2");
+
+ ctx.setAttribute(pre1 + "int-list[1].iden", "214748364");
+ ctx.setAttribute(pre1 + "int-list[1].available.ll[0]", "Giga");
+ ctx.setAttribute(pre1 + "int-list[1].available.ll[1]",
+ "identity-types:Loopback");
+ ctx.setAttribute(pre1 + "int-list[1].available.ll[2]",
+ "identity-types-second:Ethernet");
+ ctx.setAttribute(pre1 + "int-list[1].available.leaf1",
+ "8888");
+ ctx.setAttribute(pre1 + "int-list[1].available.leaf2",
+ "identity-types-second:iden2");
+ return ctx;
+ }
+
+ /**
+ * Creates attribute list for encoding JSON or XML with container,
+ * grouping and augmented YANG file.
+ *
+ * @param pre prefix
+ * @return service logic context
+ */
+ private SvcLogicContext createAttListYang(String pre) {
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute(pre + "cont3.leaf10", "abc");
+ ctx.setAttribute(pre + "list1[0].leaf1", "true");
+ ctx.setAttribute(pre + "list1[0].leaf2", "abc");
+ ctx.setAttribute(pre + "list1[0].leaf3", "abc");
+ ctx.setAttribute(pre + "list1[0].ll1[0]", "abc");
+ ctx.setAttribute(pre + "list1[0].ll1[1]", "abc");
+ ctx.setAttribute(pre + "list1[0].ll2[0]", "abc");
+ ctx.setAttribute(pre + "list1[0].ll2[1]", "abc");
+ ctx.setAttribute(pre + "list1[0].cont4.leaf11", "abc");
+ ctx.setAttribute(pre + "list1[0].list4[0].leaf8", "abc");
+ ctx.setAttribute(pre + "list1[0].list4[1].leaf8", "abc");
+ ctx.setAttribute(pre + "list1[0].list5[0].leaf9", "abc");
+ ctx.setAttribute(pre + "list1[0].list5[1].leaf9", "abc");
+ ctx.setAttribute(pre + "list1[1].leaf1", "true");
+ ctx.setAttribute(pre + "list1[1].leaf2", "abc");
+ ctx.setAttribute(pre + "list1[1].leaf3", "abc");
+ ctx.setAttribute(pre + "list1[1].ll1[0]", "abc");
+ ctx.setAttribute(pre + "list1[1].ll1[1]", "abc");
+ ctx.setAttribute(pre + "list1[1].ll2[0]", "abc");
+ ctx.setAttribute(pre + "list1[1].ll2[1]", "abc");
+ ctx.setAttribute(pre + "list1[1].cont4.leaf11", "abc");
+ ctx.setAttribute(pre + "list1[1].list4[0].leaf8", "abc");
+ ctx.setAttribute(pre + "list1[1].list4[1].leaf8", "abc");
+ ctx.setAttribute(pre + "list1[1].list5[0].leaf9", "abc");
+ ctx.setAttribute(pre + "list1[1].list5[1].leaf9", "abc");
+ ctx.setAttribute(pre + "list2[0].leaf4", "abc");
+ ctx.setAttribute(pre + "list2[1].leaf4", "abc");
+ ctx.setAttribute(pre + "leaf5", "abc");
+ ctx.setAttribute(pre + "leaf6", "abc");
+ ctx.setAttribute(pre + "ll3[0]", "abc");
+ ctx.setAttribute(pre + "ll3[1]", "abc");
+ ctx.setAttribute(pre + "ll4[0]", "abc");
+ ctx.setAttribute(pre + "ll4[1]", "abc");
+ ctx.setAttribute(pre + "cont4.leaf10", "abc");
+ ctx.setAttribute(pre + "list6[0].leaf11", "abc");
+ ctx.setAttribute(pre + "list6[1].leaf11", "abc");
+ ctx.setAttribute(pre + "leaf12", "abc");
+ ctx.setAttribute(pre + "ll5[0]", "abc");
+ ctx.setAttribute(pre + "ll5[1]", "abc");
+ ctx.setAttribute(pre + "cont4.test-augment_cont5.leaf13", "true");
+ ctx.setAttribute(pre + "cont4.test-augment_list7[0].leaf14", "test");
+ ctx.setAttribute(pre + "cont4.test-augment_list7[1].leaf14", "create");
+ ctx.setAttribute(pre + "cont4.test-augment_leaf15", "abc");
+ ctx.setAttribute(pre + "cont4.test-augment_ll6[0]", "unbounded");
+ ctx.setAttribute(pre + "cont4.test-augment_ll6[1]", "8");
+ ctx.setAttribute(pre + "cont4.test-augment_cont13.cont12.leaf26",
+ "abc");
+ ctx.setAttribute(pre + "cont4.test-augment_cont13.list9[0].leaf27",
+ "abc");
+ ctx.setAttribute(pre + "cont4.test-augment_cont13.list9[1].leaf27",
+ "abc");
+ ctx.setAttribute(pre + "cont4.test-augment_cont13.leaf28", "abc");
+ ctx.setAttribute(pre + "cont4.test-augment_cont13.ll9[0]", "abc");
+ ctx.setAttribute(pre + "cont4.test-augment_cont13.ll9[1]", "abc");
+ return ctx;
+ }
+
+ /**
+ * Creates attribute list for encoding JSON or XML with RPC YANG file.
+ *
+ * @param pre prefix
+ * @return service logic context
+ */
+ private SvcLogicContext createAttListRpc(String pre) {
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute(pre + "cont14.leaf28", "abc");
+ ctx.setAttribute(pre + "list10[0].leaf29", "abc");
+ ctx.setAttribute(pre + "list10[1].leaf29", "abc");
+ ctx.setAttribute(pre + "leaf30", "abc");
+ ctx.setAttribute(pre + "ll10[0]", "abc");
+ ctx.setAttribute(pre + "ll10[1]", "abc");
+ ctx.setAttribute(pre + "cont15.leaf31", "abc");
+ ctx.setAttribute(pre + "cont13.list9[0].leaf27", "abc");
+ ctx.setAttribute(pre + "cont13.list9[1].leaf27", "abc");
+ ctx.setAttribute(pre + "cont13.leaf28", "abc");
+ ctx.setAttribute(pre + "cont13.ll9[0]", "abc");
+ ctx.setAttribute(pre + "cont13.ll9[1]", "abc");
+ return ctx;
+ }
+
+ /**
+ * Verifies the attribute list for decoding from JSON or XML with
+ * identity-ref YANG file.
+ *
+ * @param ctx service logic context
+ * @param pre prefix
+ */
+ private void verifyAttList(SvcLogicContext ctx, String pre) {
+ String pre1 = pre + "con1.interfaces.";
+ assertThat(ctx.getAttribute(pre + "con1.interface"), is(
+ "identity-types:physical"));
+ assertThat(ctx.getAttribute(pre + "con1.interface"), is(
+ "identity-types:physical"));
+ assertThat(ctx.getAttribute(pre1 + "int-list[0].iden"), is("optical"));
+ assertThat(ctx.getAttribute(pre1 + "int-list[0].available.ll[0]"), is(
+ "Giga"));
+ assertThat(ctx.getAttribute(pre1 + "int-list[0].available.ll[1]"), is(
+ "identity-types:Loopback"));
+ assertThat(ctx.getAttribute(pre1 + "int-list[0].available.ll[2]"), is(
+ "identity-types-second:Ethernet"));
+ assertThat(ctx.getAttribute(pre1 + "int-list[0].available.leaf1"), is(
+ "58"));
+ assertThat(ctx.getAttribute(pre1 + "int-list[0].available.leaf2"), is(
+ "identity-types-second:iden2"));
+
+ assertThat(ctx.getAttribute(pre1 + "int-list[1].iden"), is(
+ "214748364"));
+ assertThat(ctx.getAttribute(pre1 + "int-list[1].available.ll[0]"), is(
+ "Giga"));
+ assertThat(ctx.getAttribute(pre1 + "int-list[1].available.ll[1]"), is(
+ "identity-types:Loopback"));
+ assertThat(ctx.getAttribute(pre1 + "int-list[1].available.ll[2]"), is(
+ "identity-types-second:Ethernet"));
+ assertThat(ctx.getAttribute(pre1 + "int-list[1].available.leaf1"), is(
+ "8888"));
+ assertThat(ctx.getAttribute(pre1 + "int-list[1].available.leaf2"), is(
+ "identity-types-second:iden2"));
+ }
+
+ /**
+ * Verifies the attribute list for decoding from JSON or XML with
+ * container, grouping and augmented file.
+ *
+ * @param ctx service logic context
+ * @param pre prefix
+ */
+ private void verifyAttListYang(SvcLogicContext ctx, String pre) {
+ assertThat(ctx.getAttribute(pre + "cont3.leaf10"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "list1[0].leaf1"), is("true"));
+ assertThat(ctx.getAttribute(pre + "list1[0].leaf2"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "list1[0].leaf3"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "list1[0].ll1[0]"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "list1[0].ll1[1]"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "list1[0].ll2[0]"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "list1[0].ll2[1]"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "list1[0].cont4.leaf11"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "list1[0].list4[0].leaf8"),
+ is("abc"));
+ assertThat(ctx.getAttribute(pre + "list1[0].list4[1].leaf8"),
+ is("abc"));
+ assertThat(ctx.getAttribute(pre + "list1[0].list5[0].leaf9"),
+ is("abc"));
+ assertThat(ctx.getAttribute(pre + "list1[0].list5[1].leaf9"),
+ is("abc"));
+ assertThat(ctx.getAttribute(pre + "list1[1].leaf1"), is("true"));
+ assertThat(ctx.getAttribute(pre + "list1[1].leaf2"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "list1[1].leaf3"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "list1[1].ll1[0]"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "list1[1].ll1[1]"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "list1[1].ll2[0]"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "list1[1].ll2[1]"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "list1[1].cont4.leaf11"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "list1[1].list4[0].leaf8"),
+ is("abc"));
+ assertThat(ctx.getAttribute(pre + "list1[1].list4[1].leaf8"),
+ is("abc"));
+ assertThat(ctx.getAttribute(pre + "list1[1].list5[0].leaf9"),
+ is("abc"));
+ assertThat(ctx.getAttribute(pre + "list1[1].list5[1].leaf9"),
+ is("abc"));
+ assertThat(ctx.getAttribute(pre + "list2[0].leaf4"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "list2[1].leaf4"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "leaf5"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "leaf6"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "ll3[0]"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "ll3[1]"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "ll4[0]"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "ll4[1]"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "cont4.leaf10"), is( "abc"));
+ assertThat(ctx.getAttribute(pre + "list6[0].leaf11"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "list6[1].leaf11"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "leaf12"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "ll5[0]"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "ll5[1]"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "cont4.test-augment_cont5.leaf13"),
+ is("true"));
+ assertThat(ctx.getAttribute(pre + "cont4.test-augment_list7[0].leaf14"),
+ is("test"));
+ assertThat(ctx.getAttribute(pre + "cont4.test-augment_list7[1].leaf14"),
+ is("create"));
+ assertThat(ctx.getAttribute(pre + "cont4.test-augment_leaf15"),
+ is("abc"));
+ assertThat(ctx.getAttribute(pre + "cont4.test-augment_ll6[0]"),
+ is("unbounded"));
+ assertThat(ctx.getAttribute(pre + "cont4.test-augment_ll6[1]"),
+ is("8"));
+ assertThat(ctx.getAttribute(pre + "cont4.test-augment_cont13" +
+ ".cont12.leaf26"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "cont4.test-augment_cont13.list9[0]" +
+ ".leaf27"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "cont4.test-augment_cont13.list9[1]" +
+ ".leaf27"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "cont4.test-augment_cont13.leaf28"),
+ is("abc"));
+ assertThat(ctx.getAttribute(pre + "cont4.test-augment_cont13.ll9[0]"),
+ is("abc"));
+ assertThat(ctx.getAttribute(pre + "cont4.test-augment_cont13.ll9[1]"),
+ is("abc"));
+ }
+
+ /**
+ * Verifies the attribute list for decoding from JSON or XML with
+ * RPC YANG file.
+ *
+ * @param ctx service logic context
+ * @param pre prefix
+ */
+ private void verifyAttListRpc(SvcLogicContext ctx, String pre) {
+ assertThat(ctx.getAttribute(pre + "cont16.leaf32"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "list11[0].leaf33"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "list11[1].leaf33"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "leaf34"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "ll11[0]"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "ll11[1]"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "cont17.leaf35"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "cont13.cont12.leaf26"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "cont13.list9[0].leaf27"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "cont13.list9[1].leaf27"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "cont13.ll9[0]"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "cont13.ll9[1]"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "cont13.leaf28"), is("abc"));
+ }
+
+ /**
+ * Verifies the attribute list for decoding from JSON or XML with
+ * ANYXML YANG file.
+ *
+ * @param ctx service logic context
+ */
+ private void verifyOutputOfAnyXml(SvcLogicContext ctx) {
+ System.out.println(ctx.getAttribute("pp.status.eventType"));
+ assertThat(ctx.getAttribute("pp.status.eventType"), is(
+ "EVENT_COMPONENT_EXECUTED"));
+ assertThat(ctx.getAttribute("pp.actionIdentifiers.blueprintName"),
+ is("golden"));
+ assertThat(ctx.getAttribute("pp.actionIdentifiers.mode"),
+ is("sync"));
+ assertThat(ctx.getAttribute("pp.stepData.name"),
+ is("resource-assignment"));
+ assertThat(ctx.getAttribute("pp.status.message"),
+ is("success"));
+ assertThat(ctx.getAttribute("pp.commonHeader.originatorId"),
+ is("System"));
+ assertThat(ctx.getAttribute("pp.status.code"),
+ is("200"));
+ assertThat(ctx.getAttribute("pp.commonHeader.requestId"),
+ is("1234"));
+ assertThat(ctx.getAttribute("pp.commonHeader.subRequestId"),
+ is("1234-12234"));
+ assertThat(ctx.getAttribute("pp.commonHeader.timestamp"),
+ is("2019-05-18T23:42:41.658Z"));
+ assertThat(ctx.getAttribute("pp.status.timestamp"),
+ is("2019-05-18T23:42:41.950Z"));
+ assertThat(ctx.getAttribute("pp.actionIdentifiers.blueprintV" +
+ "ersion"), is("1.0.0"));
+ assertThat(ctx.getAttribute("pp.actionIdentifiers.actionName"),
+ is("resource-assignment"));
+ assertThat(ctx.getAttribute("pp.payload.resource-assignment-resp" +
+ "onse.meshed-template.vf-module-1"),
+ is("<interface>\n <description>This i" +
+ "s the Virtual Firewall entity</description>\n" +
+ " <vfw>10.0.101.20/24</vfw>\n" +
+ "</interface>"));
+ assertThat(ctx.getAttribute("pp.actionIdentifiers.actionName"),
+ is("resource-assignment"));
+ }
+
+
+ /**
+ * Captures the data format messages by mocking it, which can be used in
+ * testing the value.
+ *
+ * @param <String> capturing data format
+ */
+ public class DfCaptor<String> implements Answer {
+
+ private String result;
+
+ /**
+ * Returns the captured data format message.
+ *
+ * @return data format message.
+ */
+ public String getResult() {
+ return result;
+ }
+
+ @Override
+ public String answer(InvocationOnMock invocationOnMock)
+ throws Throwable {
+ result = (String) invocationOnMock.callRealMethod();
+ return result;
+ }
+ }
+
+}
diff --git a/plugins/restconf-client/provider/src/test/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DataFormatUtilsTest.java b/plugins/restconf-client/provider/src/test/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DataFormatUtilsTest.java
new file mode 100644
index 000000000..c1bb71985
--- /dev/null
+++ b/plugins/restconf-client/provider/src/test/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/DataFormatUtilsTest.java
@@ -0,0 +1,631 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Huawei Technologies Co., Ltd. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.yangserializers.dfserializer;
+
+/**
+ * Unit test case utilities for data format serializer and restconf api call
+ * node.
+ */
+public final class DataFormatUtilsTest {
+
+ static final String ENCODE_TO_JSON_ID_COMMON = "\n \"interfaces\"" +
+ ": " +
+ "{\n" +
+ " \"int-list\": [\n" +
+ " {\n" +
+ " \"iden\": \"optical\",\n" +
+ " \"available\": {\n" +
+ " \"ll\": [\n" +
+ " \"Giga\",\n" +
+ " \"identity-types:Loopback\",\n" +
+ " \"identity-types-second:Ethernet" +
+ "\"\n" +
+ " ],\n" +
+ " \"leaf1\": \"58\",\n" +
+ " \"leaf2\": \"identity-types-second:iden" +
+ "2\"\n" +
+ " }\n" +
+ " },\n" +
+ " {\n" +
+ " \"iden\": \"214748364\",\n" +
+ " \"available\": {\n" +
+ " \"ll\": [\n" +
+ " \"Giga\",\n" +
+ " \"identity-types:Loopback\",\n" +
+ " \"identity-types-second:Ethernet" +
+ "\"\n" +
+ " ],\n" +
+ " \"leaf1\": \"8888\",\n" +
+ " \"leaf2\": \"identity-types-second:ide" +
+ "n2\"\n" +
+ " }\n" +
+ " }\n" +
+ " ]\n" +
+ " },\n" +
+ " \"interface\": \"identity-types:physical\"\n" +
+ " }";
+
+ static final String ENCODE_TO_JSON_ID = "{\n" +
+ " \"identity-test:con1\": {" + ENCODE_TO_JSON_ID_COMMON +
+ ",\n" +
+ " \"identity-test:l\": \"abc\"\n" +
+ "}";
+
+ static final String ENCODE_TO_ANYXML = "{\n" +
+ " \"actionIdentifiers\": {\n" +
+ " \"mode\": \"sync\",\n" +
+ " \"blueprintName\": \"baseconfiguration\",\n" +
+ " \"blueprintVersion\": \"1.0.0\",\n" +
+ " \"actionName\": \"assign-activate\"\n" +
+ " },\n" +
+ " \"payload\": {\n" +
+ " \"template-prefix\": \"vDNS-test\",\n" +
+ " \"resource-assignment-request\": {\n" +
+ " \"resource-assignment-properties\": {\n" +
+ " \"service-instance-id\": \"1234\",\n" +
+ " \"vnf-id\": \"3526\",\n" +
+ " \"customer-name\": \"htipl\",\n" +
+ " \"subscriber-name\": \"huawei\"\n" +
+ " }\n" +
+ " }\n" +
+ " },\n" +
+ " \"commonHeader\": {\n" +
+ " \"subRequestId\": \"sub-123456-1000\",\n" +
+ " \"requestId\": \"123456-1000\",\n" +
+ " \"originatorId\": \"SDNC_DG\"\n" +
+ " }\n" +
+ "}";
+
+ static final String ENCODE_TO_JSON_ID_PUT = "{\n" +
+ " \"identity-test:test\": {\n" +
+ " \"con1\": {" + addSpace(ENCODE_TO_JSON_ID_COMMON, 4) +
+ ",\n" +
+ " \"l\": \"abc\"\n" +
+ " }\n" +
+ "}";
+
+ static final String ENCODE_TO_XML_ID_COMMON = "\n <interfaces>\n" +
+ " <int-list>\n" +
+ " <iden>optical</iden>\n" +
+ " <available>\n" +
+ " <ll>Giga</ll>\n" +
+ " <ll xmlns:yangid=\"identity:list:ns:test:json:se" +
+ "r\">yangid:Loopback</ll>\n" +
+ " <ll xmlns:yangid=\"identity:list:second:ns:test" +
+ ":json:ser\">yangid:Ethernet</ll>\n" +
+ " <leaf1>58</leaf1>\n" +
+ " <leaf2 xmlns:yangid=\"identity:list:second:ns:t" +
+ "est:json:ser\">yangid:iden2</leaf2>\n" +
+ " </available>\n" +
+ " </int-list>\n" +
+ " <int-list>\n" +
+ " <iden>214748364</iden>\n" +
+ " <available>\n" +
+ " <ll>Giga</ll>\n" +
+ " <ll xmlns:yangid=\"identity:list:ns:test:json:s" +
+ "er\">yangid:Loopback</ll>\n" +
+ " <ll xmlns:yangid=\"identity:list:second:ns:test" +
+ ":json:ser\">yangid:Ethernet</ll>\n" +
+ " <leaf1>8888</leaf1>\n" +
+ " <leaf2 xmlns:yangid=\"identity:list:second:ns:t" +
+ "est:json:ser\">yangid:iden2</leaf2>\n" +
+ " </available>\n" +
+ " </int-list>\n" +
+ " </interfaces>\n" +
+ " <interface xmlns:yangid=\"identity:list:ns:test:json:ser\">" +
+ "yangid:physical</interface>";
+
+ static final String ENCODE_TO_XML_ID = "<?xml version=\"1.0\" encoding=" +
+ "\"UTF-8\" standalone=\"no\"?>\n" +
+ "<con1 xmlns=\"identity:ns:test:json:ser\">" +
+ ENCODE_TO_XML_ID_COMMON + "\n</con1>\n";
+
+ static final String ENCODE_TO_XML_ID_PUT = "<?xml version=\"1.0\" enco" +
+ "ding=\"UTF-8\" standalone=\"no\"?>\n" +
+ "<test xmlns=\"identity:ns:test:json:ser\">\n" +
+ " <con1>" + addSpace(ENCODE_TO_XML_ID_COMMON, 4)
+ + "\n </con1>\n" +
+ "</test>\n";
+
+ static final String ENCODE_TO_JSON_YANG_COMMON = "\n " +
+ "\"test-augment:ll6\": [\n" +
+ " \"unbounded\",\n" +
+ " \"8\"\n" +
+ " ],\n" +
+ " \"test-augment:cont13\": {\n" +
+ " \"ll9\": [\n" +
+ " \"abc\",\n" +
+ " \"abc\"\n" +
+ " ],\n" +
+ " \"list9\": [\n" +
+ " {\n" +
+ " \"leaf27\": \"abc\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"leaf27\": \"abc\"\n" +
+ " }\n" +
+ " ],\n" +
+ " \"leaf28\": \"abc\",\n" +
+ " \"cont12\": {\n" +
+ " \"leaf26\": \"abc\"\n" +
+ " }\n" +
+ " },\n" +
+ " \"test-augment:list7\": [\n" +
+ " {\n" +
+ " \"leaf14\": \"test\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"leaf14\": \"create\"\n" +
+ " }\n" +
+ " ],\n" +
+ " \"test-augment:leaf15\": \"abc\",\n" +
+ " \"test-augment:cont5\": {\n" +
+ " \"leaf13\": \"true\"\n" +
+ " }";
+
+ static final String ENCODE_TO_JSON_YANG_AUG_POST = "{\n" +
+ " \"test-yang:leaf10\": \"abc\"," +
+ ENCODE_TO_JSON_YANG_COMMON + "\n}";
+
+ static final String ENCODE_TO_JSON_YANG = "{\n" +
+ " \"test-yang:cont2\": {\n" +
+ " \"list1\": [\n" +
+ " {\n" +
+ " \"ll1\": [\n" +
+ " \"abc\",\n" +
+ " \"abc\"\n" +
+ " ],\n" +
+ " \"leaf1\": \"true\",\n" +
+ " \"ll2\": [\n" +
+ " \"abc\",\n" +
+ " \"abc\"\n" +
+ " ],\n" +
+ " \"list5\": [\n" +
+ " {\n" +
+ " \"leaf9\": \"abc\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"leaf9\": \"abc\"\n" +
+ " }\n" +
+ " ],\n" +
+ " \"leaf3\": \"abc\",\n" +
+ " \"leaf2\": \"abc\",\n" +
+ " \"list4\": [\n" +
+ " {\n" +
+ " \"leaf8\": \"abc\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"leaf8\": \"abc\"\n" +
+ " }\n" +
+ " ],\n" +
+ " \"cont4\": {\n" +
+ " \"leaf11\": \"abc\"\n" +
+ " }\n" +
+ " },\n" +
+ " {\n" +
+ " \"ll1\": [\n" +
+ " \"abc\",\n" +
+ " \"abc\"\n" +
+ " ],\n" +
+ " \"leaf1\": \"true\",\n" +
+ " \"ll2\": [\n" +
+ " \"abc\",\n" +
+ " \"abc\"\n" +
+ " ],\n" +
+ " \"leaf3\": \"abc\",\n" +
+ " \"list5\": [\n" +
+ " {\n" +
+ " \"leaf9\": \"abc\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"leaf9\": \"abc\"\n" +
+ " }\n" +
+ " ],\n" +
+ " \"list4\": [\n" +
+ " {\n" +
+ " \"leaf8\": \"abc\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"leaf8\": \"abc\"\n" +
+ " }\n" +
+ " ],\n" +
+ " \"leaf2\": \"abc\",\n" +
+ " \"cont4\": {\n" +
+ " \"leaf11\": \"abc\"\n" +
+ " }\n" +
+ " }\n" +
+ " ],\n" +
+ " \"ll3\": [\n" +
+ " \"abc\",\n" +
+ " \"abc\"\n" +
+ " ],\n" +
+ " \"ll5\": [\n" +
+ " \"abc\",\n" +
+ " \"abc\"\n" +
+ " ],\n" +
+ " \"cont4\": {\n" +
+ " \"leaf10\": \"abc\"," +
+ addSpace(ENCODE_TO_JSON_YANG_COMMON, 8) + "\n" +
+ " },\n" +
+ " \"ll4\": [\n" +
+ " \"abc\",\n" +
+ " \"abc\"\n" +
+ " ],\n" +
+ " \"cont3\": {\n" +
+ " \"leaf10\": \"abc\"\n" +
+ " },\n" +
+ " \"leaf5\": \"abc\",\n" +
+ " \"list2\": [\n" +
+ " {\n" +
+ " \"leaf4\": \"abc\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"leaf4\": \"abc\"\n" +
+ " }\n" +
+ " ],\n" +
+ " \"leaf12\": \"abc\",\n" +
+ " \"leaf6\": \"abc\",\n" +
+ " \"list6\": [\n" +
+ " {\n" +
+ " \"leaf11\": \"abc\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"leaf11\": \"abc\"\n" +
+ " }\n" +
+ " ]\n" +
+ " }\n" +
+ "}";
+
+ static final String ENCODE_TO_JSON_YANG_PUT = "{\n" +
+ " \"test-yang:cont4\": {" + addSpace(
+ ENCODE_TO_JSON_YANG_COMMON, 4) + ",\n" +
+ " \"leaf10\": \"abc\"\n" +
+ " }\n" +
+ "}";
+
+ static final String ENCODE_TO_XML_YANG_COMMON = "\n" +
+ "<ll6 xmlns=\"urn:opendaylight:params:xml:ns:yang:aug" +
+ "ment\">unbounded</ll6>\n" +
+ "<ll6 xmlns=\"urn:opendaylight:params:xml:ns:yang:aug" +
+ "ment\">8</ll6>\n" +
+ "<cont13 xmlns=\"urn:opendaylight:params:xml:ns:yang:" +
+ "augment\">\n" +
+ " <ll9>abc</ll9>\n" +
+ " <ll9>abc</ll9>\n" +
+ " <list9>\n" +
+ " <leaf27>abc</leaf27>\n" +
+ " </list9>\n" +
+ " <list9>\n" +
+ " <leaf27>abc</leaf27>\n" +
+ " </list9>\n" +
+ " <leaf28>abc</leaf28>\n" +
+ " <cont12>\n" +
+ " <leaf26>abc</leaf26>\n" +
+ " </cont12>\n" +
+ "</cont13>\n" +
+ "<list7 xmlns=\"urn:opendaylight:params:xml:ns:yang:a" +
+ "ugment\">\n" +
+ " <leaf14>test</leaf14>\n" +
+ "</list7>\n" +
+ "<list7 xmlns=\"urn:opendaylight:params:xml:ns:yang:a" +
+ "ugment\">\n" +
+ " <leaf14>create</leaf14>\n" +
+ "</list7>\n" +
+ "<leaf15 xmlns=\"urn:opendaylight:params:xml:ns:yang:" +
+ "augment\">abc</leaf15>\n" +
+ "<cont5 xmlns=\"urn:opendaylight:params:xml:ns:yang:a" +
+ "ugment\">\n" +
+ " <leaf13>true</leaf13>\n" +
+ "</cont5>";
+
+ static final String ENCODE_TO_XML_YANG_AUG_POST = "<?xml version=\"1.0\"" +
+ " encoding=\"UTF-8\" standalone=\"no\"?>\n" +
+ "<leaf10 xmlns=\"urn:opendaylight:params:xml:ns:yang:test\">abc" +
+ "</leaf10>" +
+ ENCODE_TO_XML_YANG_COMMON + "\n";
+
+ static final String ENCODE_TO_XML_YANG_PUT = "<?xml version=\"1.0\" enc" +
+ "oding=\"UTF-8\" standalone=\"no\"?>\n" +
+ "<cont4 xmlns=\"urn:opendaylight:params:xml:ns:yang:test\">\n" +
+ " <leaf10>abc</leaf10>" +
+ addSpace(ENCODE_TO_XML_YANG_COMMON, 4) + "\n</cont4>\n";
+
+ static final String ENCODE_TO_XML_YANG = "<?xml version=\"1.0\" encoding" +
+ "=\"UTF-8\" standalone=\"no\"?>\n" +
+ "<cont2 xmlns=\"urn:opendaylight:params:xml:ns:yang:test\">\n" +
+ " <list1>\n" +
+ " <ll1>abc</ll1>\n" +
+ " <ll1>abc</ll1>\n" +
+ " <leaf1>true</leaf1>\n" +
+ " <ll2>abc</ll2>\n" +
+ " <ll2>abc</ll2>\n" +
+ " <list5>\n" +
+ " <leaf9>abc</leaf9>\n" +
+ " </list5>\n" +
+ " <list5>\n" +
+ " <leaf9>abc</leaf9>\n" +
+ " </list5>\n" +
+ " <leaf3>abc</leaf3>\n" +
+ " <leaf2>abc</leaf2>\n" +
+ " <list4>\n" +
+ " <leaf8>abc</leaf8>\n" +
+ " </list4>\n" +
+ " <list4>\n" +
+ " <leaf8>abc</leaf8>\n" +
+ " </list4>\n" +
+ " <cont4>\n" +
+ " <leaf11>abc</leaf11>\n" +
+ " </cont4>\n" +
+ " </list1>\n" +
+ " <list1>\n" +
+ " <ll1>abc</ll1>\n" +
+ " <ll1>abc</ll1>\n" +
+ " <leaf1>true</leaf1>\n" +
+ " <ll2>abc</ll2>\n" +
+ " <ll2>abc</ll2>\n" +
+ " <leaf3>abc</leaf3>\n" +
+ " <list5>\n" +
+ " <leaf9>abc</leaf9>\n" +
+ " </list5>\n" +
+ " <list5>\n" +
+ " <leaf9>abc</leaf9>\n" +
+ " </list5>\n" +
+ " <list4>\n" +
+ " <leaf8>abc</leaf8>\n" +
+ " </list4>\n" +
+ " <list4>\n" +
+ " <leaf8>abc</leaf8>\n" +
+ " </list4>\n" +
+ " <leaf2>abc</leaf2>\n" +
+ " <cont4>\n" +
+ " <leaf11>abc</leaf11>\n" +
+ " </cont4>\n" +
+ " </list1>\n" +
+ " <ll3>abc</ll3>\n" +
+ " <ll3>abc</ll3>\n" +
+ " <ll5>abc</ll5>\n" +
+ " <ll5>abc</ll5>\n" +
+ " <cont4>\n" +
+ " <leaf10>abc</leaf10>"+
+ addSpace(ENCODE_TO_XML_YANG_COMMON, 8) + "\n" +
+ " </cont4>\n" +
+ " <ll4>abc</ll4>\n" +
+ " <ll4>abc</ll4>\n" +
+ " <cont3>\n" +
+ " <leaf10>abc</leaf10>\n" +
+ " </cont3>\n" +
+ " <leaf5>abc</leaf5>\n" +
+ " <list2>\n" +
+ " <leaf4>abc</leaf4>\n" +
+ " </list2>\n" +
+ " <list2>\n" +
+ " <leaf4>abc</leaf4>\n" +
+ " </list2>\n" +
+ " <leaf12>abc</leaf12>\n" +
+ " <leaf6>abc</leaf6>\n" +
+ " <list6>\n" +
+ " <leaf11>abc</leaf11>\n" +
+ " </list6>\n" +
+ " <list6>\n" +
+ " <leaf11>abc</leaf11>\n" +
+ " </list6>\n" +
+ "</cont2>\n";
+
+ static final String ENCODE_TO_JSON_RPC = "{\n" +
+ " \"test-yang:input\": {\n" +
+ " \"leaf30\": \"abc\",\n" +
+ " \"list10\": [\n" +
+ " {\n" +
+ " \"leaf29\": \"abc\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"leaf29\": \"abc\"\n" +
+ " }\n" +
+ " ],\n" +
+ " \"cont15\": {\n" +
+ " \"leaf31\": \"abc\"\n" +
+ " },\n" +
+ " \"cont14\": {\n" +
+ " \"leaf28\": \"abc\"\n" +
+ " },\n" +
+ " \"cont13\": {\n" +
+ " \"list9\": [\n" +
+ " {\n" +
+ " \"leaf27\": \"abc\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"leaf27\": \"abc\"\n" +
+ " }\n" +
+ " ],\n" +
+ " \"ll9\": [\n" +
+ " \"abc\",\n" +
+ " \"abc\"\n" +
+ " ],\n" +
+ " \"leaf28\": \"abc\"\n" +
+ " },\n" +
+ " \"ll10\": [\n" +
+ " \"abc\",\n" +
+ " \"abc\"\n" +
+ " ]\n" +
+ " }\n" +
+ "}";
+
+ static final String DECODE_FROM_JSON_RPC = "{\n" +
+ " \"test-yang:output\": {\n" +
+ " \"cont16\": {\n" +
+ " \"leaf32\": \"abc\"\n" +
+ " },\n" +
+ " \"list11\": [\n" +
+ " {\n" +
+ " \"leaf33\": \"abc\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"leaf33\": \"abc\"\n" +
+ " }\n" +
+ " ],\n" +
+ " \"leaf34\": \"abc\",\n" +
+ " \"ll11\": [\n" +
+ " \"abc\",\n" +
+ " \"abc\"\n" +
+ " ],\n" +
+ " \"cont17\": {\n" +
+ " \"leaf35\": \"abc\"\n" +
+ " },\n" +
+ " \"cont13\": {\n" +
+ " \"cont12\": {\n" +
+ " \"leaf26\": \"abc\"\n" +
+ " },\n" +
+ " \"list9\": [\n" +
+ " {\n" +
+ " \"leaf27\": \"abc\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"leaf27\": \"abc\"\n" +
+ " }\n" +
+ " ],\n" +
+ " \"ll9\": [\n" +
+ " \"abc\",\n" +
+ " \"abc\"\n" +
+ " ],\n" +
+ " \"leaf28\": \"abc\"\n" +
+ " }\n" +
+ " }\n" +
+ "}";
+
+ static final String DECODE_ANYXML_RESPONSE = "{\n" +
+ " \"commonHeader\": {\n" +
+ " \"timestamp\": \"2019-05-18T23:42:41.658Z\",\n" +
+ " \"originatorId\": \"System\",\n" +
+ " \"requestId\": \"1234\",\n" +
+ " \"subRequestId\": \"1234-12234\",\n" +
+ " \"flags\": null\n" +
+ " },\n" +
+ " \"actionIdentifiers\": {\n" +
+ " \"blueprintName\": \"golden\",\n" +
+ " \"blueprintVersion\": \"1.0.0\",\n" +
+ " \"actionName\": \"resource-assignment\",\n" +
+ " \"mode\": \"sync\"\n" +
+ " },\n" +
+ " \"status\": {\n" +
+ " \"code\": 200,\n" +
+ " \"eventType\": \"EVENT_COMPONENT_EXECUTED\",\n" +
+ " \"timestamp\": \"2019-05-18T23:42:41.950Z\",\n" +
+ " \"errorMessage\": null,\n" +
+ " \"message\": \"success\"\n" +
+ " },\n" +
+ " \"payload\": {\n" +
+ " \"resource-assignment-response\": {\n" +
+ " \"meshed-template\": {\n" +
+ " \"vf-module-1\": \"<interface>\\n " +
+ " <description>This is the Virtual Firewall entity</" +
+ "description>\\n <vfw>10.0.101.20/24</vfw>\\n</interface>\"\n" +
+ " }\n" +
+ " }\n" +
+ " },\n" +
+ " \"stepData\": {\n" +
+ " \"name\": \"resource-assignment\",\n" +
+ " \"properties\": {\n" +
+ " \"resource-assignment-params\": null,\n" +
+ " \"status\": null\n" +
+ " }\n" +
+ " }\n" +
+ "}";
+
+ static final String ENCODE_TO_XML_RPC = "<?xml version=\"1.0\" encoding" +
+ "=\"UTF-8\" standalone=\"no\"?>\n" +
+ "<input xmlns=\"urn:opendaylight:params:xml:ns:yang:test\">\n" +
+ " <leaf30>abc</leaf30>\n" +
+ " <list10>\n" +
+ " <leaf29>abc</leaf29>\n" +
+ " </list10>\n" +
+ " <list10>\n" +
+ " <leaf29>abc</leaf29>\n" +
+ " </list10>\n" +
+ " <cont15>\n" +
+ " <leaf31>abc</leaf31>\n" +
+ " </cont15>\n" +
+ " <cont14>\n" +
+ " <leaf28>abc</leaf28>\n" +
+ " </cont14>\n" +
+ " <cont13>\n" +
+ " <list9>\n" +
+ " <leaf27>abc</leaf27>\n" +
+ " </list9>\n" +
+ " <list9>\n" +
+ " <leaf27>abc</leaf27>\n" +
+ " </list9>\n" +
+ " <ll9>abc</ll9>\n" +
+ " <ll9>abc</ll9>\n" +
+ " <leaf28>abc</leaf28>\n" +
+ " </cont13>\n" +
+ " <ll10>abc</ll10>\n" +
+ " <ll10>abc</ll10>\n" +
+ "</input>\n";
+
+ static final String DECODE_FROM_XML_RPC = "<?xml version=\"1.0\" encodi" +
+ "ng=\"UTF-8\" standalone=\"no\"?>\n" +
+ "<output xmlns=\"urn:opendaylight:params:xml:ns:yang:test\">\n" +
+ " <cont16>\n" +
+ " <leaf32>abc</leaf32>\n" +
+ " </cont16>\n" +
+ " <list11>\n" +
+ " <leaf33>abc</leaf33>\n" +
+ " </list11>\n" +
+ " <list11>\n" +
+ " <leaf33>abc</leaf33>\n" +
+ " </list11>\n" +
+ " <leaf34>abc</leaf34>\n" +
+ " <ll11>abc</ll11>\n" +
+ " <ll11>abc</ll11>\n" +
+ " <cont17>\n" +
+ " <leaf35>abc</leaf35>\n" +
+ " </cont17>\n" +
+ " <cont13>\n" +
+ " <cont12>\n" +
+ " <leaf26>abc</leaf26>\n" +
+ " </cont12>\n" +
+ " <list9>\n" +
+ " <leaf27>abc</leaf27>\n" +
+ " </list9>\n" +
+ " <list9>\n" +
+ " <leaf27>abc</leaf27>\n" +
+ " </list9>\n" +
+ " <ll9>abc</ll9>\n" +
+ " <ll9>abc</ll9>\n" +
+ " <leaf28>abc</leaf28>\n" +
+ " </cont13>\n" +
+ "</output>";
+
+ /**
+ * Adds the specified number of space required for a req in each line.
+ *
+ * @param req request message
+ * @param i number of space
+ * @return space appended string
+ */
+ public static String addSpace(String req, int i) {
+ StringBuilder space = new StringBuilder();
+ for (int sp = 0; sp < i; sp++) {
+ space = space.append(" ");
+ }
+ return req.replaceAll("\n", "\n" + space.toString());
+ }
+}
diff --git a/plugins/restconf-client/provider/src/test/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/IdentifierValidationTest.java b/plugins/restconf-client/provider/src/test/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/IdentifierValidationTest.java
new file mode 100644
index 000000000..1109d426c
--- /dev/null
+++ b/plugins/restconf-client/provider/src/test/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/IdentifierValidationTest.java
@@ -0,0 +1,762 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - CCSDK
+ * ================================================================================
+ * Copyright (C) 2019 Huawei Technologies Co., Ltd. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.yangserializers.dfserializer;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.plugins.restapicall.HttpResponse;
+import org.onap.ccsdk.sli.plugins.restapicall.RestapiCallNode;
+import org.onap.ccsdk.sli.plugins.restconfapicall.RestconfApiCallNode;
+import org.opendaylight.restconf.common.context.InstanceIdentifierContext;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.Is.is;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doCallRealMethod;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.IdentifierValidationUtilsTest.DECODE_FROM_JSON_RPC_ID;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.IdentifierValidationUtilsTest.DECODE_FROM_XML_RPC_ID;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.IdentifierValidationUtilsTest.ENCODE_TO_JSON_RPC_ID;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.IdentifierValidationUtilsTest.ENCODE_TO_JSON_WITH_AUG_PATH;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.IdentifierValidationUtilsTest.ENCODE_TO_JSON_YANG_AUG_POST_ID;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.IdentifierValidationUtilsTest.ENCODE_TO_JSON_YANG_ID;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.IdentifierValidationUtilsTest.ENCODE_TO_JSON_YANG_PUT_ID;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.IdentifierValidationUtilsTest.ENCODE_TO_XML_RPC_ID;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.IdentifierValidationUtilsTest.ENCODE_TO_XML_YANG_AUG_POST_ID;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.IdentifierValidationUtilsTest.ENCODE_TO_XML_YANG_ID;
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.IdentifierValidationUtilsTest.ENCODE_TO_XML_YANG_PUT_ID;
+
+/**
+ * Unit test cases for identifier validation test.
+ */
+public class IdentifierValidationTest {
+
+ private Map<String, String> p;
+
+ private RestconfApiCallNode restconf;
+
+ private RestapiCallNode restApi;
+
+ private DfCaptor dfCaptor;
+
+ /**
+ * Sets up the pre-requisite for each test case.
+ *
+ * @throws SvcLogicException when test case fails
+ */
+ @Before
+ public void setUp() throws SvcLogicException {
+ p = new HashMap<>();
+ p.put("restapiUser", "user1");
+ p.put("restapiPassword", "abc123");
+ p.put("responsePrefix", "response");
+ p.put("skipSending", "true");
+ restApi = new RestapiCallNode();
+ restconf = mock(RestconfApiCallNode.class);
+ dfCaptor = new DfCaptor();
+ createMethodMocks();
+ }
+
+ /**
+ * Creates method mocks using mockito for RestconfApiCallNode class.
+ *
+ * @throws SvcLogicException when test case fails
+ */
+ private void createMethodMocks() throws SvcLogicException {
+ doReturn(restApi).when(restconf).getRestapiCallNode();
+ doCallRealMethod().when(restconf).sendRequest(
+ any(Map.class), any(SvcLogicContext.class));
+ doCallRealMethod().when(restconf).sendRequest(
+ any(Map.class), any(SvcLogicContext.class), any(Integer.class));
+ doAnswer(dfCaptor).when(restconf).serializeRequest(
+ any(Map.class), any(YangParameters.class), any(String.class),
+ any(InstanceIdentifierContext.class));
+ doAnswer(dfCaptor).when(restconf).updateReq(
+ any(String.class), any(YangParameters.class),
+ any(InstanceIdentifierContext.class));
+ }
+
+ /**
+ * Creates mock using mockito with input data for decoding.
+ *
+ * @param decodeData input data
+ * @throws SvcLogicException when test case fails
+ */
+ private void createMockForDecode(String decodeData)
+ throws SvcLogicException {
+ doReturn(decodeData).when(restconf).getResponse(
+ any(SvcLogicContext.class), any(YangParameters.class),
+ any(String.class), any(HttpResponse.class));
+ doCallRealMethod().when(restconf).serializeResponse(
+ any(YangParameters.class), any(String.class), any(String.class),
+ any(InstanceIdentifierContext.class));
+ }
+
+ /**
+ * Verifies encoding of parameters to JSON data format with containers,
+ * grouping and augment.
+ *
+ * @throws SvcLogicException when test case fails
+ */
+ @Test
+ public void encodeToJsonYang() throws SvcLogicException {
+ String pre = "test_name_of_the_module_name_of_the_cont1.name_" +
+ "of_the_cont2.";
+ SvcLogicContext ctx = createAttListYang(pre);
+ p.put("dirPath", "src/test/resources");
+ p.put("format", "json");
+ p.put("httpMethod", "post");
+ p.put("restapiUrl", "http://echo.getpostman.com/restconf/operati" +
+ "ons/test_name_of_the_module:name_of_the_cont1");
+ restconf.sendRequest(p, ctx);
+ assertThat(dfCaptor.getResult(), is(ENCODE_TO_JSON_YANG_ID));
+ }
+
+ /**
+ * Verifies encoding of parameters with augment in the URL.
+ *
+ * @throws SvcLogicException when test case fails
+ */
+ @Test
+ public void encodeToJsonYangWithAugUrl() throws SvcLogicException {
+ String pre = "test_name_of_the_module_name_of_the_cont1.name_" +
+ "of_the_cont2.";
+ SvcLogicContext ctx = createAttListYang(pre);
+ p.put("dirPath", "src/test/resources");
+ p.put("format", "json");
+ p.put("httpMethod", "post");
+ p.put("restapiUrl", "http://echo.getpostman.com/restconf/operati" +
+ "ons/test_name_of_the_module:name_of_the_cont1/name_of_t" +
+ "he_cont2/name_of_the_cont4/test_augment_1_for_module:na" +
+ "me_of_the_cont5");
+ restconf.sendRequest(p, ctx);
+ assertThat(dfCaptor.getResult(), is(ENCODE_TO_JSON_WITH_AUG_PATH));
+ }
+
+ /**
+ * Verifies encoding of parameters to JSON data format with containers,
+ * grouping and augment for put operation-type.
+ *
+ * @throws SvcLogicException when test case fails
+ */
+ @Test
+ public void encodeToJsonYangWithPut() throws SvcLogicException {
+ String pre = "test_name_of_the_module_name_of_the_cont1.name_of_the_cont2.";
+ SvcLogicContext ctx = createAttListYang(pre);
+ p.put("dirPath", "src/test/resources");
+ p.put("format", "json");
+ p.put("httpMethod", "put");
+ p.put("restapiUrl", "http://echo.getpostman" +
+ ".com/restconf/operations/test_name_of_the_module:name_of" +
+ "_the_cont1/name_of_the_cont2/name_of_the_cont4");
+ restconf.sendRequest(p, ctx);
+ assertThat(dfCaptor.getResult(), is(ENCODE_TO_JSON_YANG_PUT_ID));
+ }
+
+ /**
+ * Verifies encoding of parameters to JSON data format with containers,
+ * grouping and augment for patch operation-type.
+ *
+ * @throws SvcLogicException when test case fails
+ */
+ @Test
+ public void encodeToJsonYangWithPatch() throws SvcLogicException {
+ String pre = "test_name_of_the_module_name_of_the_cont1.name_o" +
+ "f_the_cont2.";
+ SvcLogicContext ctx = createAttListYang(pre);
+ p.put("dirPath", "src/test/resources");
+ p.put("format", "json");
+ p.put("httpMethod", "patch");
+ p.put("restapiUrl", "http://echo.getpostman" +
+ ".com/restconf/operations/test_name_of_the_module:name_of_" +
+ "the_cont1/name_of_the_cont2/name_of_the_cont4");
+ restconf.sendRequest(p, ctx);
+ assertThat(dfCaptor.getResult(), is(ENCODE_TO_JSON_YANG_PUT_ID));
+ }
+
+ /**
+ * Verifies encoding of parameters to JSON data format with augment as
+ * root child.
+ *
+ * @throws SvcLogicException when test case fails
+ */
+ @Test
+ public void encodeToJsonWithAugAsRootChild() throws SvcLogicException {
+ String pre = "test_name_of_the_module_name_of_the_cont1.name_of_" +
+ "the_cont2.";
+ SvcLogicContext ctx = createAttListYang(pre);
+ p.put("dirPath", "src/test/resources");
+ p.put("format", "json");
+ p.put("httpMethod", "post");
+ p.put("restapiUrl", "http://echo.getpostman" +
+ ".com/restconf/operations/test_name_of_the_module:name_of_" +
+ "the_cont1/name_of_the_cont2/name_of_the_cont4");
+ restconf.sendRequest(p, ctx);
+ assertThat(dfCaptor.getResult(), is(ENCODE_TO_JSON_YANG_AUG_POST_ID));
+ }
+
+ /**
+ * Verifies decoding of parameters from JSON data format with containers,
+ * grouping and augment.
+ *
+ * @throws SvcLogicException when test case fails
+ */
+ @Test
+ public void decodeToJsonYang() throws SvcLogicException {
+ createMockForDecode(ENCODE_TO_JSON_YANG_ID);
+ SvcLogicContext ctx = new SvcLogicContext();
+ String pre = "test_name_of_the_module_name_of_the_cont1.name_" +
+ "of_the_cont2.";
+ p.put("dirPath", "src/test/resources");
+ p.put("format", "json");
+ p.put("httpMethod", "get");
+ p.put("restapiUrl", "http://echo.getpostman" +
+ ".com/restconf/operations/test_name_of_the_module:name" +
+ "_of_the_cont1");
+ restconf.sendRequest(p, ctx);
+ verifyAttListYang(ctx, pre);
+ }
+
+ /**
+ * Verifies encoding of parameters to XML data format with containers,
+ * grouping and augment.
+ *
+ * @throws SvcLogicException when test case fails
+ */
+ @Test
+ public void encodeToXmlYang() throws SvcLogicException {
+ String pre = "test_name_of_the_module_name_of_the_cont1.name_of" +
+ "_the_cont2.";
+ SvcLogicContext ctx = createAttListYang(pre);
+ p.put("dirPath", "src/test/resources");
+ p.put("format", "xml");
+ p.put("httpMethod", "post");
+ p.put("restapiUrl", "http://echo.getpostman.com/restconf/operations/" +
+ "test_name_of_the_module:name_of_the_cont1");
+ restconf.sendRequest(p, ctx);
+ assertThat(dfCaptor.getResult(), is(ENCODE_TO_XML_YANG_ID));
+ }
+
+ /**
+ * Verifies encoding of parameters to XML data format with containers,
+ * grouping and augment for put operation-type
+ *
+ * @throws SvcLogicException when test case fails
+ */
+ @Test
+ public void encodeToXmlYangWithPut() throws SvcLogicException {
+ String pre = "test_name_of_the_module_name_of_the_cont1.name_" +
+ "of_the_cont2.";
+ SvcLogicContext ctx = createAttListYang(pre);
+ p.put("dirPath", "src/test/resources");
+ p.put("format", "xml");
+ p.put("httpMethod", "put");
+ p.put("restapiUrl", "http://echo.getpostman.com/restconf/operations/" +
+ "test_name_of_the_module:name_of_the_cont1/name_of_the_cont2" +
+ "/name_of_the_cont4");
+ restconf.sendRequest(p, ctx);
+ assertThat(dfCaptor.getResult(), is(ENCODE_TO_XML_YANG_PUT_ID));
+ }
+
+ /**
+ * Verifies encoding of parameters to XML data format with containers,
+ * grouping and augment for patch operation-type
+ *
+ * @throws SvcLogicException when test case fails
+ */
+ @Test
+ public void encodeToXmlYangWithPatch() throws SvcLogicException {
+ String pre = "test_name_of_the_module_name_of_the_cont1.name_of" +
+ "_the_cont2.";
+ SvcLogicContext ctx = createAttListYang(pre);
+ p.put("dirPath", "src/test/resources");
+ p.put("format", "xml");
+ p.put("httpMethod", "put");
+ p.put("restapiUrl", "http://echo.getpostman.com/restconf/operation" +
+ "s/test_name_of_the_module:name_of_the_cont1/name_of_the_c" +
+ "ont2/name_of_the_cont4");
+ restconf.sendRequest(p, ctx);
+ assertThat(dfCaptor.getResult(), is(ENCODE_TO_XML_YANG_PUT_ID));
+ }
+
+ /**
+ * Verifies encoding of parameters to XML data format with augment as
+ * root child.
+ *
+ * @throws SvcLogicException when test case fails
+ */
+ @Test
+ public void encodeToXmlWithAugAsRootChild() throws SvcLogicException {
+ String pre = "test_name_of_the_module_name_of_the_cont1.name_of_the" +
+ "_cont2.";
+ SvcLogicContext ctx = createAttListYang(pre);
+ p.put("dirPath", "src/test/resources");
+ p.put("format", "xml");
+ p.put("httpMethod", "post");
+ p.put("restapiUrl", "http://echo.getpostman.com/restconf/operations/" +
+ "test_name_of_the_module:name_of_the_cont1/name_of_the_cont2" +
+ "/name_of_the_cont4");
+ restconf.sendRequest(p, ctx);
+ assertThat(dfCaptor.getResult(), is(ENCODE_TO_XML_YANG_AUG_POST_ID));
+ }
+
+ /**
+ * Verifies decoding of parameters from XML data format with containers,
+ * grouping and augment.
+ *
+ * @throws SvcLogicException when test case fails
+ */
+ @Test
+ public void decodeToXmlYang() throws SvcLogicException {
+ createMockForDecode(ENCODE_TO_XML_YANG_ID);
+ SvcLogicContext ctx = new SvcLogicContext();
+ String pre = "test_name_of_the_module_name_of_the_cont1.name_of_" +
+ "the_cont2.";
+ p.put("dirPath", "src/test/resources");
+ p.put("format", "xml");
+ p.put("httpMethod", "get");
+ p.put("restapiUrl", "http://echo.getpostman.com/restconf/operation" +
+ "s/test_name_of_the_module:name_of_the_cont1");
+ restconf.sendRequest(p, ctx);
+ verifyAttListYang(ctx, pre);
+ }
+
+ /**
+ * Verifies encoding of and decoding from, JSON respectively for data
+ * format with containers, grouping and augment.
+ *
+ * @throws SvcLogicException when test case fails
+ */
+ @Test
+ public void codecToJsonRpc() throws SvcLogicException {
+ createMockForDecode(DECODE_FROM_JSON_RPC_ID);
+ String inPre = "test_name_of_the_module_name_of_the_create-sfc.input.";
+ String outPre = "test_name_of_the_module_name_of_the_create-sfc" +
+ ".output.";
+ SvcLogicContext ctx = createAttListRpc(inPre);
+ p.put("dirPath", "src/test/resources");
+ p.put("format", "json");
+ p.put("httpMethod", "post");
+ p.put("restapiUrl", "http://echo.getpostman.com/restconf/operations" +
+ "/test_name_of_the_module:name_of_the_create-sfc");
+ restconf.sendRequest(p, ctx);
+ assertThat(dfCaptor.getResult(), is(ENCODE_TO_JSON_RPC_ID));
+ verifyAttListRpc(ctx, outPre);
+ }
+
+ /**
+ * Verifies encoding of and decoding from, XML respectively for data
+ * format with containers, grouping and augment.
+ *
+ * @throws SvcLogicException when test case fails
+ */
+ @Test
+ public void codecToXmlRpc() throws SvcLogicException {
+ createMockForDecode(DECODE_FROM_XML_RPC_ID);
+ String inPre = "test_name_of_the_module_name_of_the_create-sfc.input.";
+ String outPre = "test_name_of_the_module_name_of_the_create-sfc.output.";
+ SvcLogicContext ctx = createAttListRpc(inPre);
+ p.put("dirPath", "src/test/resources");
+ p.put("format", "xml");
+ p.put("httpMethod", "post");
+ p.put("restapiUrl", "http://echo.getpostman" +
+ ".com/restconf/operations/test_name_of_the_module" +
+ ":name_of_the_create-sfc");
+ restconf.sendRequest(p, ctx);
+ assertThat(dfCaptor.getResult(), is(ENCODE_TO_XML_RPC_ID));
+ verifyAttListRpc(ctx, outPre);
+ }
+
+ /**
+ * Creates attribute list for encoding JSON or XML with container,
+ * grouping and augmented YANG file.
+ *
+ * @param pre prefix
+ * @return service logic context
+ */
+ private SvcLogicContext createAttListYang(String pre) {
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute(pre + "name_of_the_cont3.name_of_the_leaf" +
+ "10", "abc");
+ ctx.setAttribute(pre + "name_of_the_list1[0].name_of_the_leaf1" +
+ "", "true");
+ ctx.setAttribute(pre + "name_of_the_list1[0].name_of_the_leaf2" +
+ "", "abc");
+ ctx.setAttribute(pre + "name_of_the_list1[0].name_of_the_leaf3" +
+ "", "abc");
+ ctx.setAttribute(pre + "name_of_the_list1[0].name_of_the_" +
+ "ll1[0]", "abc");
+ ctx.setAttribute(pre + "name_of_the_list1[0].name_of_the_" +
+ "ll1[1]", "abc");
+ ctx.setAttribute(pre + "name_of_the_list1[0].name_of_the_" +
+ "ll2[0]", "abc");
+ ctx.setAttribute(pre + "name_of_the_list1[0].name_of_the_" +
+ "ll2[1]", "abc");
+ ctx.setAttribute(pre + "name_of_the_list1[0].name_of_the_" +
+ "cont4.name_of_the_leaf11", "abc");
+ ctx.setAttribute(pre + "name_of_the_list1[0].name_of_the_" +
+ "list4[0].name_of_the_leaf8", "abc");
+ ctx.setAttribute(pre + "name_of_the_list1[0].name_of_the_" +
+ "list4[1].name_of_the_leaf8", "abc");
+ ctx.setAttribute(pre + "name_of_the_list1[0].name_of_the_" +
+ "list5[0].name_of_the_leaf9", "abc");
+ ctx.setAttribute(pre + "name_of_the_list1[0].name_of_the_" +
+ "list5[1].name_of_the_leaf9", "abc");
+ ctx.setAttribute(pre + "name_of_the_list1[1].name_of_the_" +
+ "leaf1", "true");
+ ctx.setAttribute(pre + "name_of_the_list1[1].name_of_the_" +
+ "leaf2", "abc");
+ ctx.setAttribute(pre + "name_of_the_list1[1].name_of_the_" +
+ "leaf3", "abc");
+ ctx.setAttribute(pre + "name_of_the_list1[1].name_of_the_" +
+ "ll1[0]", "abc");
+ ctx.setAttribute(pre + "name_of_the_list1[1].name_of_the_" +
+ "ll1[1]", "abc");
+ ctx.setAttribute(pre + "name_of_the_list1[1].name_of_the_" +
+ "ll2[0]", "abc");
+ ctx.setAttribute(pre + "name_of_the_list1[1].name_of_the_" +
+ "ll2[1]", "abc");
+ ctx.setAttribute(pre + "name_of_the_list1[1].name_of_the_" +
+ "cont4.name_of_the_leaf11", "abc");
+ ctx.setAttribute(pre + "name_of_the_list1[1].name_of_the_" +
+ "list4[0].name_of_the_leaf8", "abc");
+ ctx.setAttribute(pre + "name_of_the_list1[1].name_of_the_" +
+ "list4[1].name_of_the_leaf8", "abc");
+ ctx.setAttribute(pre + "name_of_the_list1[1].name_of_the_" +
+ "list5[0].name_of_the_leaf9", "abc");
+ ctx.setAttribute(pre + "name_of_the_list1[1].name_of_the_" +
+ "list5[1].name_of_the_leaf9", "abc");
+ ctx.setAttribute(pre + "name_of_the_list2[0].name_of_the_" +
+ "leaf4", "abc");
+ ctx.setAttribute(pre + "name_of_the_list2[1].name_of_the_" +
+ "leaf4", "abc");
+ ctx.setAttribute(pre + "name_of_the_leaf5", "abc");
+ ctx.setAttribute(pre + "name_of_the_leaf6", "abc");
+ ctx.setAttribute(pre + "name_of_the_ll3[0]", "abc");
+ ctx.setAttribute(pre + "name_of_the_ll3[1]", "abc");
+ ctx.setAttribute(pre + "name_of_the_ll4[0]", "abc");
+ ctx.setAttribute(pre + "name_of_the_ll4[1]", "abc");
+ ctx.setAttribute(pre + "name_of_the_cont4.name_of_the_leaf10",
+ "abc");
+ ctx.setAttribute(pre + "name_of_the_list6[0].name_of_the_leaf11",
+ "abc");
+ ctx.setAttribute(pre + "name_of_the_list6[1].name_of_the_leaf11",
+ "abc");
+ ctx.setAttribute(pre + "name_of_the_leaf12", "abc");
+ ctx.setAttribute(pre + "name_of_the_ll5[0]", "abc");
+ ctx.setAttribute(pre + "name_of_the_ll5[1]", "abc");
+ ctx.setAttribute(pre + "name_of_the_cont4.test_augment_1_for_" +
+ "module_name_of_the_cont5.name_of_the_leaf13",
+ "true");
+ ctx.setAttribute(pre + "name_of_the_cont4.test_augment_1_for_" +
+ "module_name_of_the_list7[0].name_of_the" +
+ "_leaf14", "test");
+ ctx.setAttribute(pre + "name_of_the_cont4.test_augment_1_for_" +
+ "module_name_of_the_list7[1].name_of_the" +
+ "_leaf14", "create");
+ ctx.setAttribute(pre + "name_of_the_cont4.test_augment_1_for_" +
+ "module_name_of_the_leaf15", "abc");
+ ctx.setAttribute(pre + "name_of_the_cont4.test_augment_1_for_" +
+ "module_name_of_the_ll6[0]",
+ "unbounded");
+ ctx.setAttribute(pre + "name_of_the_cont4.test_augment_1_for" +
+ "_module_name_of_the_ll6[1]", "8");
+ ctx.setAttribute(pre + "name_of_the_cont4.test_augment_1_for" +
+ "_module_name_of_the_cont13.name_of_the_" +
+ "cont12.name_of_the_leaf26",
+ "abc");
+ ctx.setAttribute(pre + "name_of_the_cont4.test_augment_1_for_" +
+ "module_name_of_the_cont13.name_of_the_" +
+ "list9[0].name_of_the_leaf27",
+ "abc");
+ ctx.setAttribute(pre + "name_of_the_cont4.test_augment_1_for" +
+ "_module_name_of_the_cont13.name_of_the_" +
+ "list9[1].name_of_the_leaf27",
+ "abc");
+ ctx.setAttribute(pre + "name_of_the_cont4.test_augment_1_for" +
+ "_module_name_of_the_cont13.name_of_the_" +
+ "leaf28", "abc");
+ ctx.setAttribute(pre + "name_of_the_cont4.test_augment_1_for" +
+ "_module_name_of_the_cont13.name_of_the_" +
+ "ll9[0]", "abc");
+ ctx.setAttribute(pre + "name_of_the_cont4.test_augment_1_for" +
+ "_module_name_of_the_cont13.name_of_the_" +
+ "ll9[1]", "abc");
+ return ctx;
+ }
+
+ /**
+ * Creates attribute list for encoding JSON or XML with RPC YANG file.
+ *
+ * @param pre prefix
+ * @return service logic context
+ */
+ private SvcLogicContext createAttListRpc(String pre) {
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute(pre + "name_of_the_cont14.name_of_the_leaf28",
+ "abc");
+ ctx.setAttribute(pre + "name_of_the_list10[0].name_of_the_leaf29",
+ "abc");
+ ctx.setAttribute(pre + "name_of_the_list10[1].name_of_the_leaf29",
+ "abc");
+ ctx.setAttribute(pre + "name_of_the_leaf30", "abc");
+ ctx.setAttribute(pre + "name_of_the_ll10[0]", "abc");
+ ctx.setAttribute(pre + "name_of_the_ll10[1]", "abc");
+ ctx.setAttribute(pre + "name_of_the_cont15.name_of_the_leaf31",
+ "abc");
+ ctx.setAttribute(pre + "name_of_the_cont13.name_of_the_list9[0]" +
+ ".name_of_the_leaf27", "abc");
+ ctx.setAttribute(pre + "name_of_the_cont13.name_of_the_list9[1]" +
+ ".name_of_the_leaf27", "abc");
+ ctx.setAttribute(pre + "name_of_the_cont13.name_of_the_leaf28",
+ "abc");
+ ctx.setAttribute(pre + "name_of_the_cont13.name_of_the_ll9[0]",
+ "abc");
+ ctx.setAttribute(pre + "name_of_the_cont13.name_of_the_ll9[1]",
+ "abc");
+ return ctx;
+ }
+
+ /**
+ * Verifies the attribute list for decoding from JSON or XML with
+ * container, grouping and augmented file.
+ *
+ * @param ctx service logic context
+ * @param pre prefix
+ */
+ private void verifyAttListYang(SvcLogicContext ctx, String pre) {
+ assertThat(ctx.getAttribute(pre + "name_of_the_cont3.name_of" +
+ "_the_leaf10"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_list1[0].name" +
+ "_of_the_leaf1"), is("true"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_list1[0].name" +
+ "_of_the_leaf2"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_list1[0].name" +
+ "_of_the_leaf3"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_list1[0].name" +
+ "_of_the_ll1[0]"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_list1[0].name" +
+ "_of_the_ll1[1]"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_list1[0].name" +
+ "_of_the_ll2[0]"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_list1[0].name" +
+ "_of_the_ll2[1]"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_list1[0].name" +
+ "_of_the_cont4.name_of_the_leaf11"),
+ is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_list1[0].name_of" +
+ "_the_list4[0].name_of_the_leaf8"),
+ is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_list1[0].name_of" +
+ "_the_list4[1].name_of_the_leaf8"),
+ is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_list1[0].name_of" +
+ "_the_list5[0].name_of_the_leaf9"),
+ is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_list1[0].name_of" +
+ "_the_list5[1].name_of_the_leaf9"),
+ is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_list1[1].name_of" +
+ "_the_leaf1"), is("true"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_list1[1].name_of" +
+ "_the_leaf2"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_list1[1].name_of" +
+ "_the_leaf3"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_list1[1].name_of" +
+ "_the_ll1[0]"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_list1[1].name_of" +
+ "_the_ll1[1]"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_list1[1].name_of" +
+ "_the_ll2[0]"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_list1[1].name_of" +
+ "_the_ll2[1]"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_list1[1].name_of" +
+ "_the_cont4.name_of_the_leaf11"),
+ is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_list1[1].name_of" +
+ "_the_list4[0].name_of_the_leaf8"),
+ is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_list1[1].name_of" +
+ "_the_list4[1].name_of_the_leaf8"),
+ is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_list1[1].name_of" +
+ "_the_list5[0].name_of_the_leaf9"),
+ is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_list1[1].name_of" +
+ "_the_list5[1].name_of_the_leaf9"),
+ is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_list2[0].name_of" +
+ "_the_leaf4"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_list2[1].name_of" +
+ "_the_leaf4"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_leaf5"),
+ is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_leaf6"),
+ is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_ll3[0]"),
+ is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_ll3[1]"),
+ is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_ll4[0]"),
+ is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_ll4[1]"),
+ is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_cont4.name_of" +
+ "_the_leaf10"), is( "abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_list6[0].name_of" +
+ "_the_leaf11"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_list6[1].name_of" +
+ "_the_leaf11"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_leaf12"),
+ is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_ll5[0]"),
+ is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_ll5[1]"),
+ is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_cont4.test_" +
+ "augment_1_for_module_name_of_" +
+ "the_cont5.name_of_the_leaf13"),
+ is("true"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_cont4.test_" +
+ "augment_1_for_module_name_of_" +
+ "the_list7[0].name_of_the_leaf14"),
+ is("test"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_cont4.test_" +
+ "augment_1_for_module_name_of_" +
+ "the_list7[1].name_of_the_leaf14"),
+ is("create"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_cont4.test_" +
+ "augment_1_for_module_name_of_" +
+ "the_leaf15"),
+ is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_cont4.test_" +
+ "augment_1_for_module_name_of_" +
+ "the_ll6[0]"),
+ is("unbounded"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_cont4.test_" +
+ "augment_1_for_module_name_of_" +
+ "the_ll6[1]"),
+ is("8"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_cont4.test_" +
+ "augment_1_for_module_name_of_" +
+ "the_cont13" +
+ ".name_of_the_cont12.name_of_" +
+ "the_leaf26"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_cont4.test_" +
+ "augment_1_for_module_name_of_" +
+ "the_cont13.name_of_the_list9[0]" +
+ ".name_of_the_leaf27"),
+ is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_cont4.test_" +
+ "augment_1_for_module_name_of_" +
+ "the_cont13.name_of_the_list9[1]" +
+ ".name_of_the_leaf27"),
+ is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_cont4.test_" +
+ "augment_1_for_module_name_of_" +
+ "the_cont13.name_of_the_leaf28"),
+ is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_cont4.test_" +
+ "augment_1_for_module_name_of_" +
+ "the_cont13.name_of_the_ll9[0]"),
+ is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_cont4.test_" +
+ "augment_1_for_module_name_of_" +
+ "the_cont13.name_of_the_ll9[1]"),
+ is("abc"));
+ }
+
+ /**
+ * Verifies the attribute list for decoding from JSON or XML with
+ * RPC YANG file.
+ *
+ * @param ctx service logic context
+ * @param pre prefix
+ */
+ private void verifyAttListRpc(SvcLogicContext ctx, String pre) {
+ assertThat(ctx.getAttribute(pre + "name_of_the_cont16.name_of_" +
+ "the_leaf32"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_list11[0].name" +
+ "_of_the_leaf33"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_list11[1].name" +
+ "_of_the_leaf33"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_leaf34"),
+ is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_ll11[0]"),
+ is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_ll11[1]"),
+ is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_cont17.name_of_" +
+ "the_leaf35"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_cont13.name_of_" +
+ "the_cont12.name_of_the_leaf26"),
+ is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_cont13.name_of_" +
+ "the_list9[0].name_of_the_leaf27"),
+ is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_cont13.name_of_" +
+ "the_list9[1].name_of_the_leaf27"),
+ is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_cont13.name_of_" +
+ "the_ll9[0]"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_cont13.name_of_" +
+ "the_ll9[1]"), is("abc"));
+ assertThat(ctx.getAttribute(pre + "name_of_the_cont13.name_of_" +
+ "the_leaf28"), is("abc"));
+ }
+
+ /**
+ * Captures the data format messages by mocking it, which can be used in
+ * testing the value.
+ *
+ * @param <String> capturing data format
+ */
+ public class DfCaptor<String> implements Answer {
+
+ private String result;
+
+ /**
+ * Returns the captured data format message.
+ *
+ * @return data format message.
+ */
+ public String getResult() {
+ return result;
+ }
+
+ @Override
+ public String answer(InvocationOnMock invocationOnMock)
+ throws Throwable {
+ result = (String) invocationOnMock.callRealMethod();
+ return result;
+ }
+ }
+
+}
diff --git a/plugins/restconf-client/provider/src/test/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/IdentifierValidationUtilsTest.java b/plugins/restconf-client/provider/src/test/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/IdentifierValidationUtilsTest.java
new file mode 100644
index 000000000..a866f1c4a
--- /dev/null
+++ b/plugins/restconf-client/provider/src/test/java/org/onap/ccsdk/sli/plugins/yangserializers/dfserializer/IdentifierValidationUtilsTest.java
@@ -0,0 +1,469 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - CCSDK
+ * ================================================================================
+ * Copyright (C) 2019 Huawei Technologies Co., Ltd. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.yangserializers.dfserializer;
+
+import static org.onap.ccsdk.sli.plugins.yangserializers.dfserializer.DataFormatUtilsTest.addSpace;
+
+/**
+ * Unit test case utilities for identifier validation and restconf api
+ * call node.
+ */
+public final class IdentifierValidationUtilsTest {
+
+ static final String ENCODE_TO_JSON_YANG_COMMON_ID = "\n " +
+ "\"test_augment_1_for_module:name_of_the_ll6\": [\n" +
+ " \"unbounded\",\n" +
+ " \"8\"\n" +
+ " ],\n" +
+ " \"test_augment_1_for_module:name_of_the_cont13\": {\n" +
+ " \"name_of_the_cont12\": {\n" +
+ " \"name_of_the_leaf26\": \"abc\"\n" +
+ " },\n" +
+ " \"name_of_the_ll9\": [\n" +
+ " \"abc\",\n" +
+ " \"abc\"\n" +
+ " ],\n" +
+ " \"name_of_the_leaf28\": \"abc\",\n" +
+ " \"name_of_the_list9\": [\n" +
+ " {\n" +
+ " \"name_of_the_leaf27\": \"abc\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"name_of_the_leaf27\": \"abc\"\n" +
+ " }\n" +
+ " ]\n" +
+ " },\n" +
+ " \"test_augment_1_for_module:name_of_the_list7\": [\n" +
+ " {\n" +
+ " \"name_of_the_leaf14\": \"test\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"name_of_the_leaf14\": \"create\"\n" +
+ " }\n" +
+ " ],\n" +
+ " \"test_augment_1_for_module:name_of_the_leaf15\": \"abc\",\n" +
+ " \"test_augment_1_for_module:name_of_the_cont5\": {\n" +
+ " \"name_of_the_leaf13\": \"true\"\n" +
+ " }";
+
+ static final String ENCODE_TO_JSON_YANG_AUG_POST_ID = "{\n" +
+ " \"test_name_of_the_module:name_of_the_leaf10\": \"abc\"," +
+ ENCODE_TO_JSON_YANG_COMMON_ID + "\n}";
+
+ static final String ENCODE_TO_JSON_YANG_ID = "{\n" +
+ " \"test_name_of_the_module:name_of_the_cont2\": {\n" +
+ " \"name_of_the_ll4\": [\n" +
+ " \"abc\",\n" +
+ " \"abc\"\n" +
+ " ],\n" +
+ " \"name_of_the_leaf5\": \"abc\",\n" +
+ " \"name_of_the_list6\": [\n" +
+ " {\n" +
+ " \"name_of_the_leaf11\": \"abc\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"name_of_the_leaf11\": \"abc\"\n" +
+ " }\n" +
+ " ],\n" +
+ " \"name_of_the_ll5\": [\n" +
+ " \"abc\",\n" +
+ " \"abc\"\n" +
+ " ],\n" +
+ " \"name_of_the_ll3\": [\n" +
+ " \"abc\",\n" +
+ " \"abc\"\n" +
+ " ],\n" +
+ " \"name_of_the_leaf6\": \"abc\",\n" +
+ " \"name_of_the_cont3\": {\n" +
+ " \"name_of_the_leaf10\": \"abc\"\n" +
+ " },\n" +
+ " \"name_of_the_list2\": [\n" +
+ " {\n" +
+ " \"name_of_the_leaf4\": \"abc\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"name_of_the_leaf4\": \"abc\"\n" +
+ " }\n" +
+ " ],\n" +
+ " \"name_of_the_list1\": [\n" +
+ " {\n" +
+ " \"name_of_the_ll2\": [\n" +
+ " \"abc\",\n" +
+ " \"abc\"\n" +
+ " ],\n" +
+ " \"name_of_the_list5\": [\n" +
+ " {\n" +
+ " \"name_of_the_leaf9\": \"abc\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"name_of_the_leaf9\": \"abc\"\n" +
+ " }\n" +
+ " ],\n" +
+ " \"name_of_the_list4\": [\n" +
+ " {\n" +
+ " \"name_of_the_leaf8\": \"abc\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"name_of_the_leaf8\": \"abc\"\n" +
+ " }\n" +
+ " ],\n" +
+ " \"name_of_the_leaf1\": \"true\",\n" +
+ " \"name_of_the_leaf3\": \"abc\",\n" +
+ " \"name_of_the_leaf2\": \"abc\",\n" +
+ " \"name_of_the_cont4\": {\n" +
+ " \"name_of_the_leaf11\": \"abc\"\n" +
+ " },\n" +
+ " \"name_of_the_ll1\": [\n" +
+ " \"abc\",\n" +
+ " \"abc\"\n" +
+ " ]\n" +
+ " },\n" +
+ " {\n" +
+ " \"name_of_the_ll2\": [\n" +
+ " \"abc\",\n" +
+ " \"abc\"\n" +
+ " ],\n" +
+ " \"name_of_the_list5\": [\n" +
+ " {\n" +
+ " \"name_of_the_leaf9\": \"abc\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"name_of_the_leaf9\": \"abc\"\n" +
+ " }\n" +
+ " ],\n" +
+ " \"name_of_the_list4\": [\n" +
+ " {\n" +
+ " \"name_of_the_leaf8\": \"abc\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"name_of_the_leaf8\": \"abc\"\n" +
+ " }\n" +
+ " ],\n" +
+ " \"name_of_the_leaf1\": \"true\",\n" +
+ " \"name_of_the_leaf3\": \"abc\",\n" +
+ " \"name_of_the_leaf2\": \"abc\",\n" +
+ " \"name_of_the_cont4\": {\n" +
+ " \"name_of_the_leaf11\": \"abc\"\n" +
+ " },\n" +
+ " \"name_of_the_ll1\": [\n" +
+ " \"abc\",\n" +
+ " \"abc\"\n" +
+ " ]\n" +
+ " }\n" +
+ " ],\n" +
+ " \"name_of_the_cont4\": {\n" +
+ " \"name_of_the_leaf10\": \"abc\"," +
+ addSpace(ENCODE_TO_JSON_YANG_COMMON_ID,8) + "\n" +
+ " },\n" +
+ " \"name_of_the_leaf12\": \"abc\"\n" +
+ " }\n" +
+ "}";
+
+ static final String ENCODE_TO_JSON_WITH_AUG_PATH = "{\n" +
+ " \"test_augment_1_for_module:name_of_the_leaf13\": \"true\"\n" +
+ "}";
+
+ static final String ENCODE_TO_JSON_YANG_PUT_ID = "{\n" +
+ " \"test_name_of_the_module:name_of_the_cont4\": {" + addSpace(
+ ENCODE_TO_JSON_YANG_COMMON_ID, 4) + ",\n" +
+ " \"name_of_the_leaf10\": \"abc\"\n" +
+ " }\n" +
+ "}";
+
+ static final String ENCODE_TO_XML_YANG_COMMON_ID = "\n" +
+ "<name_of_the_ll6 xmlns=\"urn:opendaylight:params:xml:ns:yang:" +
+ "test:augment:name\">unbounded</name_of_the_ll6>\n" +
+ "<name_of_the_ll6 xmlns=\"urn:opendaylight:params:xml:ns:yang:" +
+ "test:augment:name\">8</name_of_the_ll6>\n" +
+ "<name_of_the_cont13 xmlns=\"urn:opendaylight:params:xml:ns:ya" +
+ "ng:test:augment:name\">\n" +
+ " <name_of_the_cont12>\n" +
+ " <name_of_the_leaf26>abc</name_of_the_leaf26>\n" +
+ " </name_of_the_cont12>\n" +
+ " <name_of_the_ll9>abc</name_of_the_ll9>\n" +
+ " <name_of_the_ll9>abc</name_of_the_ll9>\n" +
+ " <name_of_the_leaf28>abc</name_of_the_leaf28>\n" +
+ " <name_of_the_list9>\n" +
+ " <name_of_the_leaf27>abc</name_of_the_leaf27>\n" +
+ " </name_of_the_list9>\n" +
+ " <name_of_the_list9>\n" +
+ " <name_of_the_leaf27>abc</name_of_the_leaf27>\n" +
+ " </name_of_the_list9>\n" +
+ "</name_of_the_cont13>\n" +
+ "<name_of_the_list7 xmlns=\"urn:opendaylight:params:xml:ns:yan" +
+ "g:test:augment:name\">\n" +
+ " <name_of_the_leaf14>test</name_of_the_leaf14>\n" +
+ "</name_of_the_list7>\n" +
+ "<name_of_the_list7 xmlns=\"urn:opendaylight:params:xml:ns:yan" +
+ "g:test:augment:name\">\n" +
+ " <name_of_the_leaf14>create</name_of_the_leaf14>\n" +
+ "</name_of_the_list7>\n" +
+ "<name_of_the_leaf15 xmlns=\"urn:opendaylight:params:xml:ns:ya" +
+ "ng:test:augment:name\">abc</name_of_the_leaf15>\n" +
+ "<name_of_the_cont5 xmlns=\"urn:opendaylight:params:xml:ns:yan" +
+ "g:test:augment:name\">\n" +
+ " <name_of_the_leaf13>true</name_of_the_leaf13>\n" +
+ "</name_of_the_cont5>";
+
+ static final String ENCODE_TO_XML_YANG_AUG_POST_ID = "<?xml version=\"1" +
+ ".0\" encoding=\"UTF-8\" standalone=\"no\"?>\n" +
+ "<name_of_the_leaf10 xmlns=\"urn:opendaylight:params:xml:ns:yan" +
+ "g:test:name\">abc</name_of_the_leaf10>" +
+ ENCODE_TO_XML_YANG_COMMON_ID + "\n";
+
+ static final String ENCODE_TO_XML_YANG_PUT_ID = "<?xml version=\"1.0\" " +
+ "encoding=\"UTF-8\" standalone=\"no\"?>\n" +
+ "<name_of_the_cont4 xmlns=\"urn:opendaylight:params:xml:ns:yang" +
+ ":test:name\">\n" +
+ " <name_of_the_leaf10>abc</name_of_the_leaf10>" +
+ addSpace(ENCODE_TO_XML_YANG_COMMON_ID, 4) + "\n</name_of_the_co" +
+ "nt4>\n";
+
+ static final String ENCODE_TO_XML_YANG_ID= "<?xml version=\"1.0\" " +
+ "encoding=\"UTF-8\" standalone=\"no\"?>\n" +
+ "<name_of_the_cont2 xmlns=\"urn:opendaylight:params:xml:ns:yan" +
+ "g:test:name\">\n" +
+ " <name_of_the_ll4>abc</name_of_the_ll4>\n" +
+ " <name_of_the_ll4>abc</name_of_the_ll4>\n" +
+ " <name_of_the_leaf5>abc</name_of_the_leaf5>\n" +
+ " <name_of_the_list6>\n" +
+ " <name_of_the_leaf11>abc</name_of_the_leaf11>\n" +
+ " </name_of_the_list6>\n" +
+ " <name_of_the_list6>\n" +
+ " <name_of_the_leaf11>abc</name_of_the_leaf11>\n" +
+ " </name_of_the_list6>\n" +
+ " <name_of_the_ll5>abc</name_of_the_ll5>\n" +
+ " <name_of_the_ll5>abc</name_of_the_ll5>\n" +
+ " <name_of_the_ll3>abc</name_of_the_ll3>\n" +
+ " <name_of_the_ll3>abc</name_of_the_ll3>\n" +
+ " <name_of_the_leaf6>abc</name_of_the_leaf6>\n" +
+ " <name_of_the_cont3>\n" +
+ " <name_of_the_leaf10>abc</name_of_the_leaf10>\n" +
+ " </name_of_the_cont3>\n" +
+ " <name_of_the_list2>\n" +
+ " <name_of_the_leaf4>abc</name_of_the_leaf4>\n" +
+ " </name_of_the_list2>\n" +
+ " <name_of_the_list2>\n" +
+ " <name_of_the_leaf4>abc</name_of_the_leaf4>\n" +
+ " </name_of_the_list2>\n" +
+ " <name_of_the_list1>\n" +
+ " <name_of_the_ll2>abc</name_of_the_ll2>\n" +
+ " <name_of_the_ll2>abc</name_of_the_ll2>\n" +
+ " <name_of_the_list5>\n" +
+ " <name_of_the_leaf9>abc</name_of_the_leaf9>\n" +
+ " </name_of_the_list5>\n" +
+ " <name_of_the_list5>\n" +
+ " <name_of_the_leaf9>abc</name_of_the_leaf9>\n" +
+ " </name_of_the_list5>\n" +
+ " <name_of_the_list4>\n" +
+ " <name_of_the_leaf8>abc</name_of_the_leaf8>\n" +
+ " </name_of_the_list4>\n" +
+ " <name_of_the_list4>\n" +
+ " <name_of_the_leaf8>abc</name_of_the_leaf8>\n" +
+ " </name_of_the_list4>\n" +
+ " <name_of_the_leaf1>true</name_of_the_leaf1>\n" +
+ " <name_of_the_leaf3>abc</name_of_the_leaf3>\n" +
+ " <name_of_the_leaf2>abc</name_of_the_leaf2>\n" +
+ " <name_of_the_cont4>\n" +
+ " <name_of_the_leaf11>abc</name_of_the_leaf11>\n" +
+ " </name_of_the_cont4>\n" +
+ " <name_of_the_ll1>abc</name_of_the_ll1>\n" +
+ " <name_of_the_ll1>abc</name_of_the_ll1>\n" +
+ " </name_of_the_list1>\n" +
+ " <name_of_the_list1>\n" +
+ " <name_of_the_ll2>abc</name_of_the_ll2>\n" +
+ " <name_of_the_ll2>abc</name_of_the_ll2>\n" +
+ " <name_of_the_list5>\n" +
+ " <name_of_the_leaf9>abc</name_of_the_leaf9>\n" +
+ " </name_of_the_list5>\n" +
+ " <name_of_the_list5>\n" +
+ " <name_of_the_leaf9>abc</name_of_the_leaf9>\n" +
+ " </name_of_the_list5>\n" +
+ " <name_of_the_list4>\n" +
+ " <name_of_the_leaf8>abc</name_of_the_leaf8>\n" +
+ " </name_of_the_list4>\n" +
+ " <name_of_the_list4>\n" +
+ " <name_of_the_leaf8>abc</name_of_the_leaf8>\n" +
+ " </name_of_the_list4>\n" +
+ " <name_of_the_leaf1>true</name_of_the_leaf1>\n" +
+ " <name_of_the_leaf3>abc</name_of_the_leaf3>\n" +
+ " <name_of_the_leaf2>abc</name_of_the_leaf2>\n" +
+ " <name_of_the_cont4>\n" +
+ " <name_of_the_leaf11>abc</name_of_the_leaf11>\n" +
+ " </name_of_the_cont4>\n" +
+ " <name_of_the_ll1>abc</name_of_the_ll1>\n" +
+ " <name_of_the_ll1>abc</name_of_the_ll1>\n" +
+ " </name_of_the_list1>\n" +
+ " <name_of_the_cont4>\n" +
+ " <name_of_the_leaf10>abc</name_of_the_leaf10>" +
+ addSpace(ENCODE_TO_XML_YANG_COMMON_ID, 8) + "\n" +
+ " </name_of_the_cont4>\n" +
+ " <name_of_the_leaf12>abc</name_of_the_leaf12>\n" +
+ "</name_of_the_cont2>\n";
+
+ static final String ENCODE_TO_JSON_RPC_ID = "{\n" +
+ " \"test_name_of_the_module:input\": {\n" +
+ " \"name_of_the_cont14\": {\n" +
+ " \"name_of_the_leaf28\": \"abc\"\n" +
+ " },\n" +
+ " \"name_of_the_cont13\": {\n" +
+ " \"name_of_the_ll9\": [\n" +
+ " \"abc\",\n" +
+ " \"abc\"\n" +
+ " ],\n" +
+ " \"name_of_the_leaf28\": \"abc\",\n" +
+ " \"name_of_the_list9\": [\n" +
+ " {\n" +
+ " \"name_of_the_leaf27\": \"abc\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"name_of_the_leaf27\": \"abc\"\n" +
+ " }\n" +
+ " ]\n" +
+ " },\n" +
+ " \"name_of_the_leaf30\": \"abc\",\n" +
+ " \"name_of_the_ll10\": [\n" +
+ " \"abc\",\n" +
+ " \"abc\"\n" +
+ " ],\n" +
+ " \"name_of_the_list10\": [\n" +
+ " {\n" +
+ " \"name_of_the_leaf29\": \"abc\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"name_of_the_leaf29\": \"abc\"\n" +
+ " }\n" +
+ " ],\n" +
+ " \"name_of_the_cont15\": {\n" +
+ " \"name_of_the_leaf31\": \"abc\"\n" +
+ " }\n" +
+ " }\n" +
+ "}";
+
+ static final String DECODE_FROM_JSON_RPC_ID = "{\n" +
+ " \"test_name_of_the_module:output\": {\n" +
+ " \"name_of_the_cont16\": {\n" +
+ " \"name_of_the_leaf32\": \"abc\"\n" +
+ " },\n" +
+ " \"name_of_the_list11\": [\n" +
+ " {\n" +
+ " \"name_of_the_leaf33\": \"abc\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"name_of_the_leaf33\": \"abc\"\n" +
+ " }\n" +
+ " ],\n" +
+ " \"name_of_the_leaf34\": \"abc\",\n" +
+ " \"name_of_the_ll11\": [\n" +
+ " \"abc\",\n" +
+ " \"abc\"\n" +
+ " ],\n" +
+ " \"name_of_the_cont17\": {\n" +
+ " \"name_of_the_leaf35\": \"abc\"\n" +
+ " },\n" +
+ " \"name_of_the_cont13\": {\n" +
+ " \"name_of_the_cont12\": {\n" +
+ " \"name_of_the_leaf26\": \"abc\"\n" +
+ " },\n" +
+ " \"name_of_the_list9\": [\n" +
+ " {\n" +
+ " \"name_of_the_leaf27\": \"abc\"\n" +
+ " },\n" +
+ " {\n" +
+ " \"name_of_the_leaf27\": \"abc\"\n" +
+ " }\n" +
+ " ],\n" +
+ " \"name_of_the_ll9\": [\n" +
+ " \"abc\",\n" +
+ " \"abc\"\n" +
+ " ],\n" +
+ " \"name_of_the_leaf28\": \"abc\"\n" +
+ " }\n" +
+ " }\n" +
+ "}";
+
+ static final String ENCODE_TO_XML_RPC_ID = "<?xml version=\"1.0\" " +
+ "encoding=\"UTF-8\" standalone=\"no\"?>\n" +
+ "<input xmlns=\"urn:opendaylight:params:xml:ns:yang:test:name\"" +
+ ">\n" +
+ " <name_of_the_cont14>\n" +
+ " <name_of_the_leaf28>abc</name_of_the_leaf28>\n" +
+ " </name_of_the_cont14>\n" +
+ " <name_of_the_cont13>\n" +
+ " <name_of_the_ll9>abc</name_of_the_ll9>\n" +
+ " <name_of_the_ll9>abc</name_of_the_ll9>\n" +
+ " <name_of_the_leaf28>abc</name_of_the_leaf28>\n" +
+ " <name_of_the_list9>\n" +
+ " <name_of_the_leaf27>abc</name_of_the_leaf27>\n" +
+ " </name_of_the_list9>\n" +
+ " <name_of_the_list9>\n" +
+ " <name_of_the_leaf27>abc</name_of_the_leaf27>\n" +
+ " </name_of_the_list9>\n" +
+ " </name_of_the_cont13>\n" +
+ " <name_of_the_leaf30>abc</name_of_the_leaf30>\n" +
+ " <name_of_the_ll10>abc</name_of_the_ll10>\n" +
+ " <name_of_the_ll10>abc</name_of_the_ll10>\n" +
+ " <name_of_the_list10>\n" +
+ " <name_of_the_leaf29>abc</name_of_the_leaf29>\n" +
+ " </name_of_the_list10>\n" +
+ " <name_of_the_list10>\n" +
+ " <name_of_the_leaf29>abc</name_of_the_leaf29>\n" +
+ " </name_of_the_list10>\n" +
+ " <name_of_the_cont15>\n" +
+ " <name_of_the_leaf31>abc</name_of_the_leaf31>\n" +
+ " </name_of_the_cont15>\n" +
+ "</input>\n";
+
+ static final String DECODE_FROM_XML_RPC_ID = "<?xml version=\"1.0\" " +
+ "encoding=\"UTF-8\" standalone=\"no\"?>\n" +
+ "<output xmlns=\"urn:opendaylight:params:xml:ns:yang:test:name" +
+ "\">\n" +
+ " <name_of_the_cont16>\n" +
+ " <name_of_the_leaf32>abc</name_of_the_leaf32>\n" +
+ " </name_of_the_cont16>\n" +
+ " <name_of_the_list11>\n" +
+ " <name_of_the_leaf33>abc</name_of_the_leaf33>\n" +
+ " </name_of_the_list11>\n" +
+ " <name_of_the_list11>\n" +
+ " <name_of_the_leaf33>abc</name_of_the_leaf33>\n" +
+ " </name_of_the_list11>\n" +
+ " <name_of_the_leaf34>abc</name_of_the_leaf34>\n" +
+ " <name_of_the_ll11>abc</name_of_the_ll11>\n" +
+ " <name_of_the_ll11>abc</name_of_the_ll11>\n" +
+ " <name_of_the_cont17>\n" +
+ " <name_of_the_leaf35>abc</name_of_the_leaf35>\n" +
+ " </name_of_the_cont17>\n" +
+ " <name_of_the_cont13>\n" +
+ " <name_of_the_cont12>\n" +
+ " <name_of_the_leaf26>abc</name_of_the_leaf26>\n" +
+ " </name_of_the_cont12>\n" +
+ " <name_of_the_list9>\n" +
+ " <name_of_the_leaf27>abc</name_of_the_leaf27>\n" +
+ " </name_of_the_list9>\n" +
+ " <name_of_the_list9>\n" +
+ " <name_of_the_leaf27>abc</name_of_the_leaf27>\n" +
+ " </name_of_the_list9>\n" +
+ " <name_of_the_ll9>abc</name_of_the_ll9>\n" +
+ " <name_of_the_ll9>abc</name_of_the_ll9>\n" +
+ " <name_of_the_leaf28>abc</name_of_the_leaf28>\n" +
+ " </name_of_the_cont13>\n" +
+ "</output>";
+}
diff --git a/plugins/restconf-client/provider/src/test/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/PropertiesSerializerTest.java b/plugins/restconf-client/provider/src/test/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/PropertiesSerializerTest.java
new file mode 100644
index 000000000..c3a6b4ea8
--- /dev/null
+++ b/plugins/restconf-client/provider/src/test/java/org/onap/ccsdk/sli/plugins/yangserializers/pnserializer/PropertiesSerializerTest.java
@@ -0,0 +1,1144 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP - CCSDK
+ * ================================================================================
+ * Copyright (C) 2018 Huawei Technologies Co., Ltd. All rights reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.ccsdk.sli.plugins.yangserializers.pnserializer;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.opendaylight.restconf.common.context.InstanceIdentifierContext;
+import org.opendaylight.restconf.nb.rfc8040.utils.parser.ParserIdentifier;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.opendaylight.yangtools.yang.test.util.YangParserTestUtils;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertTrue;
+
+public final class PropertiesSerializerTest {
+ private SchemaContext context;
+
+ @Before
+ public void initialization() throws FileNotFoundException {
+ context = compileYangFile();
+ }
+
+ @Test
+ public void testBasicConstructs() throws SvcLogicException {
+ String uri = "test-yang:cont1/cont2";
+ Map<String, String> params = new HashMap<>();
+ params.put("test-yang_cont1.cont2.cont3.leaf10", "abc");
+ params.put("test-yang_cont1.cont2.list1[0].leaf1", "abc");
+ params.put("test-yang_cont1.cont2.list1[0].leaf2", "abc");
+ params.put("test-yang_cont1.cont2.list1[0].leaf3", "abc");
+ params.put("test-yang_cont1.cont2.list1[0].ll1[0]", "abc");
+ params.put("test-yang_cont1.cont2.list1[0].ll1[1]", "abc");
+ params.put("test-yang_cont1.cont2.list1[0].ll2[0]", "abc");
+ params.put("test-yang_cont1.cont2.list1[0].ll2[1]", "abc");
+ params.put("test-yang_cont1.cont2.list1[0].cont4.leaf11", "abc");
+ params.put("test-yang_cont1.cont2.list1[0].list4[0].leaf8", "abc");
+ params.put("test-yang_cont1.cont2.list1[0].list4[1].leaf8", "abc");
+ params.put("test-yang_cont1.cont2.list1[0].list5[0].leaf9", "abc");
+ params.put("test-yang_cont1.cont2.list1[0].list5[1].leaf9", "abc");
+ params.put("test-yang_cont1.cont2.list1[1].leaf1", "abc");
+ params.put("test-yang_cont1.cont2.list1[1].leaf2", "abc");
+ params.put("test-yang_cont1.cont2.list1[1].leaf3", "abc");
+ params.put("test-yang_cont1.cont2.list1[1].ll1[0]", "abc");
+ params.put("test-yang_cont1.cont2.list1[1].ll1[1]", "abc");
+ params.put("test-yang_cont1.cont2.list1[1].ll2[0]", "abc");
+ params.put("test-yang_cont1.cont2.list1[1].ll2[1]", "abc");
+ params.put("test-yang_cont1.cont2.list1[1].cont4.leaf11", "abc");
+ params.put("test-yang_cont1.cont2.list1[1].list4[0].leaf8", "abc");
+ params.put("test-yang_cont1.cont2.list1[1].list4[1].leaf8", "abc");
+ params.put("test-yang_cont1.cont2.list1[1].list5[0].leaf9", "abc");
+ params.put("test-yang_cont1.cont2.list1[1].list5[1].leaf9", "abc");
+ params.put("test-yang_cont1.cont2.list2[0].leaf4", "abc");
+ params.put("test-yang_cont1.cont2.list2[1].leaf4", "abc");
+ params.put("test-yang_cont1.cont2.leaf5", "abc");
+ params.put("test-yang_cont1.cont2.leaf6", "abc");
+ params.put("test-yang_cont1.cont2.ll3[0]", "abc");
+ params.put("test-yang_cont1.cont2.ll3[1]", "abc");
+ params.put("test-yang_cont1.cont2.ll4[0]", "abc");
+ params.put("test-yang_cont1.cont2.ll4[1]", "abc");
+ InstanceIdentifierContext<?> iCtx = ParserIdentifier
+ .toInstanceIdentifier(uri, context, null);
+
+ PropertiesNodeSerializer ser = new MdsalPropertiesNodeSerializer(
+ iCtx.getSchemaNode(), context, uri);
+ PropertiesNode node = ser.encode(params);
+
+ Map<String, PropertiesNode> childNodes = ((RootNode) node).children();
+
+ assertThat(childNodes.containsKey("cont3"), is(true));
+ SingleInstanceNode cont3 = ((SingleInstanceNode) childNodes.get("cont3"));
+ assertThat(cont3.uri(), is("test-yang:cont1.cont2.cont3"));
+ assertThat(cont3.children().containsKey("leaf10"), is(true));
+
+ assertThat(childNodes.containsKey("list1"), is(true));
+ HolderNode list1Holder = ((ListHolderNode) childNodes.get("list1"));
+ assertThat(list1Holder.uri(), is("test-yang:cont1.cont2.list1"));
+ MultiInstanceNode list10 = ((MultiInstanceNode) list1Holder.child("0"));
+ assertThat(list10.uri(), is("test-yang:cont1.cont2.list1[0]"));
+ Map<String, DataNodeChild> list10Child = list10.children();
+ assertThat(list10Child.containsKey("leaf1"), is(true));
+ LeafNode l = ((LeafNode) list10Child.get("leaf1"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.list1[0].leaf1"));
+ assertThat(list10Child.containsKey("leaf2"), is(true));
+ l = ((LeafNode) list10Child.get("leaf2"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.list1[0].leaf2"));
+ assertThat(list10Child.containsKey("leaf2"), is(true));
+ l = ((LeafNode) list10Child.get("leaf3"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.list1[0].leaf3"));
+
+ LeafListHolderNode ll1Holder = ((LeafListHolderNode) list10Child.get("ll1"));
+ assertThat(ll1Holder.uri(), is("test-yang:cont1.cont2.list1[0].ll1"));
+ assertThat(ll1Holder.children().containsKey("0"), is(true));
+ l = ((LeafNode) ll1Holder.child("0"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.list1[0].ll1[0]"));
+ assertThat(ll1Holder.children().containsKey("1"), is(true));
+ l = ((LeafNode) ll1Holder.child("1"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.list1[0].ll1[1]"));
+
+ LeafListHolderNode ll2Holder = ((LeafListHolderNode) list10Child.get("ll2"));
+ assertThat(ll2Holder.uri(), is("test-yang:cont1.cont2.list1[0].ll2"));
+ assertThat(ll2Holder.children().containsKey("0"), is(true));
+ l = ((LeafNode) ll2Holder.child("0"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.list1[0].ll2[0]"));
+ assertThat(ll2Holder.children().containsKey("1"), is(true));
+ l = ((LeafNode) ll2Holder.child("1"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.list1[0].ll2[1]"));
+
+ SingleInstanceNode cont4 = ((SingleInstanceNode) list10Child.get("cont4"));
+ assertThat(cont4.uri(), is("test-yang:cont1.cont2.list1[0].cont4"));
+ assertThat(cont4.children().containsKey("leaf11"), is(true));
+ l = ((LeafNode) cont4.children().get("leaf11"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.list1[0].cont4.leaf11"));
+
+ HolderNode list4Holder = ((HolderNode) list10Child.get("list4"));
+ assertThat(list4Holder.uri(), is("test-yang:cont1.cont2.list1[0].list4"));
+ Map<String, PropertiesNode> c = list4Holder.children();
+ MultiInstanceNode list40 = ((MultiInstanceNode) c.get("0"));
+ assertThat(list40.uri(), is("test-yang:cont1.cont2.list1[0].list4[0]"));
+ assertThat(list40.children().containsKey("leaf8"), is(true));
+ l = ((LeafNode) list40.children().get("leaf8"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.list1[0].list4[0].leaf8"));
+ MultiInstanceNode list41 = ((MultiInstanceNode) c.get("1"));
+ assertThat(list41.uri(), is("test-yang:cont1.cont2.list1[0].list4[1]"));
+ assertThat(list41.children().containsKey("leaf8"), is(true));
+ l = ((LeafNode) list41.children().get("leaf8"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.list1[0].list4[1].leaf8"));
+
+ HolderNode list5Holder = ((HolderNode) list10Child.get("list5"));
+ assertThat(list5Holder.uri(), is("test-yang:cont1.cont2.list1[0].list5"));
+ c = list5Holder.children();
+ MultiInstanceNode list50 = ((MultiInstanceNode) c.get("0"));
+ assertThat(list50.uri(), is("test-yang:cont1.cont2.list1[0].list5[0]"));
+ assertThat(list50.children().containsKey("leaf9"), is(true));
+ l = ((LeafNode) list50.children().get("leaf9"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.list1[0].list5[0].leaf9"));
+ MultiInstanceNode list51 = ((MultiInstanceNode) c.get("1"));
+ assertThat(list51.uri(), is("test-yang:cont1.cont2.list1[0].list5[1]"));
+ assertThat(list51.children().containsKey("leaf9"), is(true));
+ l = ((LeafNode) list51.children().get("leaf9"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.list1[0].list5[1].leaf9"));
+
+ MultiInstanceNode list11 = ((MultiInstanceNode) list1Holder.child("1"));
+ assertThat(list11.uri(), is("test-yang:cont1.cont2.list1[1]"));
+ Map<String, DataNodeChild> list11Child = list11.children();
+ assertThat(list11Child.containsKey("leaf1"), is(true));
+ l = ((LeafNode) list11Child.get("leaf1"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.list1[1].leaf1"));
+ assertThat(list11Child.containsKey("leaf2"), is(true));
+ l = ((LeafNode) list11Child.get("leaf2"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.list1[1].leaf2"));
+ assertThat(list11Child.containsKey("leaf3"), is(true));
+ l = ((LeafNode) list11Child.get("leaf3"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.list1[1].leaf3"));
+
+ ll1Holder = ((LeafListHolderNode) list11Child.get("ll1"));
+ assertThat(ll1Holder.uri(), is("test-yang:cont1.cont2.list1[1].ll1"));
+ assertThat(ll1Holder.children().containsKey("0"), is(true));
+ l = ((LeafNode) ll1Holder.children().get("0"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.list1[1].ll1[0]"));
+ assertThat(ll1Holder.children().containsKey("1"), is(true));
+ l = ((LeafNode) ll1Holder.children().get("1"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.list1[1].ll1[1]"));
+
+ ll2Holder = ((LeafListHolderNode) list11Child.get("ll2"));
+ assertThat(ll2Holder.uri(), is("test-yang:cont1.cont2.list1[1].ll2"));
+ assertThat(ll2Holder.children().containsKey("0"), is(true));
+ l = ((LeafNode) ll2Holder.children().get("0"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.list1[1].ll2[0]"));
+ assertThat(ll2Holder.children().containsKey("1"), is(true));
+ l = ((LeafNode) ll2Holder.children().get("1"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.list1[1].ll2[1]"));
+
+ cont4 = ((SingleInstanceNode) list11Child.get("cont4"));
+ assertThat(cont4.uri(), is("test-yang:cont1.cont2.list1[1].cont4"));
+ assertThat(cont4.children().containsKey("leaf11"), is(true));
+ l = ((LeafNode) cont4.children().get("leaf11"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.list1[1].cont4.leaf11"));
+
+ list4Holder = ((HolderNode) list11Child.get("list4"));
+ assertThat(list4Holder.uri(), is("test-yang:cont1.cont2.list1[1].list4"));
+ c = list4Holder.children();
+ list40 = ((MultiInstanceNode) c.get("0"));
+ assertThat(list40.uri(), is("test-yang:cont1.cont2.list1[1].list4[0]"));
+ assertThat(list40.children().containsKey("leaf8"), is(true));
+ l = ((LeafNode) list40.children().get("leaf8"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.list1[1].list4[0].leaf8"));
+ list41 = ((MultiInstanceNode) c.get("1"));
+ assertThat(list41.uri(), is("test-yang:cont1.cont2.list1[1].list4[1]"));
+ assertThat(list41.children().containsKey("leaf8"), is(true));
+ l = ((LeafNode) list41.children().get("leaf8"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.list1[1].list4[1].leaf8"));
+
+ list5Holder = ((HolderNode) list11Child.get("list5"));
+ assertThat(list5Holder.uri(), is("test-yang:cont1.cont2.list1[1].list5"));
+ c = list5Holder.children();
+ list50 = ((MultiInstanceNode) c.get("0"));
+ assertThat(list50.uri(), is("test-yang:cont1.cont2.list1[1].list5[0]"));
+ assertThat(list50.children().containsKey("leaf9"), is(true));
+ l = ((LeafNode) list50.children().get("leaf9"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.list1[1].list5[0].leaf9"));
+ list51 = ((MultiInstanceNode) c.get("1"));
+ assertThat(list51.uri(), is("test-yang:cont1.cont2.list1[1].list5[1]"));
+ assertThat(list51.children().containsKey("leaf9"), is(true));
+ l = ((LeafNode) list51.children().get("leaf9"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.list1[1].list5[1].leaf9"));
+
+ assertThat(childNodes.containsKey("list2"), is(true));
+ HolderNode list2Holder = ((HolderNode) childNodes.get("list2"));
+ assertThat(list2Holder.uri(), is("test-yang:cont1.cont2.list2"));
+ InnerNode list20 = ((InnerNode) list2Holder.children().get("0"));
+ assertThat(list20.uri(), is("test-yang:cont1.cont2.list2[0]"));
+ assertThat(list20.children().containsKey("leaf4"), is(true));
+ l = ((LeafNode) list20.children().get("leaf4"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.list2[0].leaf4"));
+ InnerNode list21 = ((InnerNode) list2Holder.children().get("1"));
+ assertThat(list21.uri(), is("test-yang:cont1.cont2.list2[1]"));
+ assertThat(list21.children().containsKey("leaf4"), is(true));
+ l = ((LeafNode) list21.children().get("leaf4"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.list2[1].leaf4"));
+
+ assertThat(childNodes.containsKey("leaf5"), is(true));
+ l = ((LeafNode) childNodes.get("leaf5"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.leaf5"));
+ assertThat(childNodes.containsKey("leaf6"), is(true));
+ l = ((LeafNode) childNodes.get("leaf6"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.leaf6"));
+
+ HolderNode ll3Holder = ((HolderNode) childNodes.get("ll3"));
+ assertThat(ll3Holder.uri(), is("test-yang:cont1.cont2.ll3"));
+ assertThat(((LeafNode) ll3Holder.children().get("0")).name(), is("ll3"));
+ l = ((LeafNode) ll3Holder.children().get("0"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.ll3[0]"));
+ assertThat(((LeafNode) ll3Holder.children().get("1")).name(), is("ll3"));
+ l = ((LeafNode) ll3Holder.children().get("1"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.ll3[1]"));
+
+ HolderNode ll4Holder = ((HolderNode) childNodes.get("ll4"));
+ assertThat(ll4Holder.uri(), is("test-yang:cont1.cont2.ll4"));
+ assertThat(((LeafNode) ll4Holder.children().get("0")).name(), is("ll4"));
+ l = ((LeafNode) ll4Holder.children().get("0"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.ll4[0]"));
+ assertThat(((LeafNode) ll4Holder.children().get("1")).name(), is("ll4"));
+ l = ((LeafNode) ll4Holder.children().get("1"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.ll4[1]"));
+
+ Map<String, String> output = ser.decode(node);
+ assertThat(output.size(), is(params.size()));
+ for (Map.Entry<String, String> entry : output.entrySet()) {
+ assertTrue(params.containsKey(entry.getKey()));
+ }
+ }
+
+ @Test
+ public void testAugment() throws SvcLogicException {
+ String uri = "test-yang:cont1/cont2";
+ Map<String, String> params = new HashMap<>();
+ params.put("test-yang_cont1.cont2.cont4.leaf10", "abc");
+ params.put("test-yang_cont1.cont2.cont4.test-augment_cont5.leaf13", "abc");
+ params.put("test-yang_cont1.cont2.cont4.test-augment_list7[0].leaf14", "abc");
+ params.put("test-yang_cont1.cont2.cont4.test-augment_list7[1].leaf14", "abc");
+ params.put("test-yang_cont1.cont2.cont4.test-augment_leaf15", "abc");
+ params.put("test-yang_cont1.cont2.cont4.test-augment_ll6[0]", "abc");
+ params.put("test-yang_cont1.cont2.cont4.test-augment_ll6[1]", "abc");
+ params.put("test-yang_cont1.cont2.list6[0].leaf11", "abc");
+ params.put("test-yang_cont1.cont2.list6[1].leaf11", "abc");
+ params.put("test-yang_cont1.cont2.leaf12", "abc");
+ params.put("test-yang_cont1.cont2.ll5[0]", "abc");
+ params.put("test-yang_cont1.cont2.ll5[1]", "abc");
+
+ InstanceIdentifierContext<?> iCtx = ParserIdentifier
+ .toInstanceIdentifier(uri, context, null);
+ PropertiesNodeSerializer ser = new MdsalPropertiesNodeSerializer(
+ iCtx.getSchemaNode(), context, uri);
+ PropertiesNode node = ser.encode(params);
+
+ Map<String, PropertiesNode> childNodes = ((RootNode) node).children();
+
+ assertThat(childNodes.containsKey("cont4"), is(true));
+ SingleInstanceNode cont4 = ((SingleInstanceNode) childNodes.get("cont4"));
+ for (Map.Entry<Object, Collection<PropertiesNode>> augToChild
+ : cont4.augmentations().asMap().entrySet()) {
+ Collection<PropertiesNode> child = augToChild.getValue();
+ if (!child.isEmpty()) {
+ List<String> expectedNodes = new LinkedList<>();
+ expectedNodes.add("test-yang:cont1.cont2.cont4.test-augment:cont5");
+ expectedNodes.add("test-yang:cont1.cont2.cont4.test-augment:list7");
+ expectedNodes.add("test-yang:cont1.cont2.cont4.test-augment:leaf15");
+ expectedNodes.add("test-yang:cont1.cont2.cont4.test-augment:ll6");
+ assertThat(expectedNodes.size(), is(child.size()));
+ for (PropertiesNode pNode : child) {
+ assertThat(expectedNodes.contains(pNode.uri()), is(true));
+ if (pNode.uri().equals("test-yang:cont1.cont2.cont4.test-augment:cont5")) {
+ assertThat(((SingleInstanceNode) pNode).children().containsKey("leaf13"), is(true));
+ LeafNode l = ((LeafNode) ((SingleInstanceNode) pNode).children().get("leaf13"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.cont4.test-augment:cont5.leaf13"));
+ } else if (pNode.uri().equals("test-yang:cont1.cont2.cont4.test-augment:list7")) {
+ ListHolderNode list7Holder = ((ListHolderNode) pNode);
+ MultiInstanceNode list7 = ((MultiInstanceNode) list7Holder.child("0"));
+ assertThat(list7.uri(), is("test-yang:cont1.cont2.cont4.test-augment:list7[0]"));
+ Map<String, DataNodeChild> list7Child = list7.children();
+ assertThat(list7Child.containsKey("leaf14"), is(true));
+ LeafNode l = ((LeafNode) list7Child.get("leaf14"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.cont4.test-augment:list7[0].leaf14"));
+ list7 = ((MultiInstanceNode) list7Holder.child("1"));
+ assertThat(list7.uri(), is("test-yang:cont1.cont2.cont4.test-augment:list7[1]"));
+ list7Child = list7.children();
+ assertThat(list7Child.containsKey("leaf14"), is(true));
+ l = ((LeafNode) list7Child.get("leaf14"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.cont4.test-augment:list7[1].leaf14"));
+ } else if (pNode.uri().equals("test-yang:cont1.cont2.cont4.test-augment:leaf15")) {
+ LeafNode leaf15 = ((LeafNode) pNode);
+ assertThat(leaf15.name(), is("leaf15"));
+ assertThat(leaf15.uri(), is("test-yang:cont1.cont2.cont4.test-augment:leaf15"));
+ } else if (pNode.uri().equals("test-yang:cont1.cont2.cont4.test-augment:ll6")) {
+ LeafListHolderNode ll6Holder = ((LeafListHolderNode) pNode);
+ assertThat(ll6Holder.children().containsKey("0"), is(true));
+ LeafNode l = ((LeafNode) ll6Holder.children().get("0"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.cont4.test-augment:ll6[0]"));
+ assertThat(ll6Holder.children().containsKey("1"), is(true));
+ l = ((LeafNode) ll6Holder.children().get("1"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.cont4.test-augment:ll6[1]"));
+ }
+ }
+ }
+ }
+ assertThat(cont4.uri(), is("test-yang:cont1.cont2.cont4"));
+ assertThat(cont4.children().containsKey("leaf10"), is(true));
+ LeafNode l = ((LeafNode) cont4.children().get("leaf10"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.cont4.leaf10"));
+
+ assertThat(childNodes.containsKey("list6"), is(true));
+ HolderNode list6Holder = ((ListHolderNode) childNodes.get("list6"));
+ assertThat(list6Holder.uri(), is("test-yang:cont1.cont2.list6"));
+ MultiInstanceNode list6 = ((MultiInstanceNode) list6Holder.child("0"));
+ assertThat(list6.uri(), is("test-yang:cont1.cont2.list6[0]"));
+ Map<String, DataNodeChild> list6Child = list6.children();
+ assertThat(list6Child.containsKey("leaf11"), is(true));
+ l = ((LeafNode) list6Child.get("leaf11"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.list6[0].leaf11"));
+ list6 = ((MultiInstanceNode) list6Holder.child("1"));
+ assertThat(list6.uri(), is("test-yang:cont1.cont2.list6[1]"));
+ list6Child = list6.children();
+ assertThat(list6Child.containsKey("leaf11"), is(true));
+ l = ((LeafNode) list6Child.get("leaf11"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.list6[1].leaf11"));
+
+ assertThat(childNodes.containsKey("leaf12"), is(true));
+ LeafNode leaf12 = ((LeafNode) childNodes.get("leaf12"));
+ assertThat(leaf12.name(), is("leaf12"));
+ assertThat(leaf12.uri(), is("test-yang:cont1.cont2.leaf12"));
+
+ LeafListHolderNode ll5Holder = ((LeafListHolderNode) childNodes.get("ll5"));
+ assertThat(ll5Holder.uri(), is("test-yang:cont1.cont2.ll5"));
+ assertThat(ll5Holder.children().containsKey("0"), is(true));
+ l = ((LeafNode) ll5Holder.children().get("0"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.ll5[0]"));
+ assertThat(ll5Holder.children().containsKey("1"), is(true));
+ l = ((LeafNode) ll5Holder.children().get("1"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.ll5[1]"));
+
+ Map<String, String> output = ser.decode(node);
+ for (Map.Entry<String, String> entry : output.entrySet()) {
+ assertTrue(params.containsKey(entry.getKey()));
+ }
+ }
+
+ @Test
+ public void testChoiceCase1() throws SvcLogicException {
+ String uri = "test-yang:cont8";
+ Map<String, String> params = new HashMap<>();
+ params.put("test-yang_cont8.cont6.leaf16", "abc");
+ params.put("test-yang_cont8.list8[0].leaf18", "abc");
+ params.put("test-yang_cont8.list8[1].leaf18", "abc");
+ params.put("test-yang_cont8.leaf19", "abc");
+ params.put("test-yang_cont8.ll7[0]", "abc");
+ params.put("test-yang_cont8.ll7[1]", "abc");
+
+ InstanceIdentifierContext<?> iCtx = ParserIdentifier
+ .toInstanceIdentifier(uri, context, null);
+ PropertiesNodeSerializer ser = new MdsalPropertiesNodeSerializer(
+ iCtx.getSchemaNode(), context, uri);
+ PropertiesNode node = ser.encode(params);
+
+ Map<String, PropertiesNode> childNodes = ((RootNode) node).children();
+
+ assertThat(childNodes.containsKey("cont6"), is(true));
+ SingleInstanceNode cont6 = ((SingleInstanceNode) childNodes.get("cont6"));
+ assertThat(cont6.uri(), is("test-yang:cont8.cont6"));
+ assertThat(cont6.children().containsKey("leaf16"), is(true));
+ LeafNode l = ((LeafNode) cont6.children().get("leaf16"));
+ assertThat(l.uri(), is("test-yang:cont8.cont6.leaf16"));
+
+ assertThat(childNodes.containsKey("list8"), is(true));
+ HolderNode list6Holder = ((ListHolderNode) childNodes.get("list8"));
+ assertThat(list6Holder.uri(), is("test-yang:cont8.list8"));
+ MultiInstanceNode list6 = ((MultiInstanceNode) list6Holder.child("0"));
+ assertThat(list6.uri(), is("test-yang:cont8.list8[0]"));
+ Map<String, DataNodeChild> list6Child = list6.children();
+ assertThat(list6Child.containsKey("leaf18"), is(true));
+ l = ((LeafNode) list6Child.get("leaf18"));
+ assertThat(l.uri(), is("test-yang:cont8.list8[0].leaf18"));
+ list6 = ((MultiInstanceNode) list6Holder.child("1"));
+ list6Child = list6.children();
+ assertThat(list6Child.containsKey("leaf18"), is(true));
+ l = ((LeafNode) list6Child.get("leaf18"));
+ assertThat(l.uri(), is("test-yang:cont8.list8[1].leaf18"));
+
+ assertThat(childNodes.containsKey("leaf19"), is(true));
+ LeafNode leaf12 = ((LeafNode) childNodes.get("leaf19"));
+ assertThat(leaf12.name(), is("leaf19"));
+ assertThat(leaf12.uri(), is("test-yang:cont8.leaf19"));
+
+ LeafListHolderNode ll5Holder = ((LeafListHolderNode) childNodes.get("ll7"));
+ assertThat(ll5Holder.uri(), is("test-yang:cont8.ll7"));
+ assertThat(ll5Holder.children().containsKey("0"), is(true));
+ l = ((LeafNode) ll5Holder.children().get("0"));
+ assertThat(l.uri(), is("test-yang:cont8.ll7[0]"));
+ assertThat(ll5Holder.children().containsKey("1"), is(true));
+ l = ((LeafNode) ll5Holder.children().get("1"));
+ assertThat(l.uri(), is("test-yang:cont8.ll7[1]"));
+
+ Map<String, String> output = ser.decode(node);
+ assertThat(output.size(), is(params.size()));
+ for (Map.Entry<String, String> entry : output.entrySet()) {
+ assertTrue(params.containsKey(entry.getKey()));
+ }
+ }
+
+ @Test
+ public void testChoiceCase2() throws SvcLogicException {
+ String uri = "test-yang:cont9";
+ Map<String, String> params = new HashMap<>();
+ params.put("test-yang_cont9.leaf20", "abc");
+ params.put("test-yang_cont9.ll8[0]", "abc");
+ params.put("test-yang_cont9.cont11.leaf25", "abc");
+
+ InstanceIdentifierContext<?> iCtx = ParserIdentifier
+ .toInstanceIdentifier(uri, context, null);
+ PropertiesNodeSerializer ser = new MdsalPropertiesNodeSerializer(
+ iCtx.getSchemaNode(), context, uri);
+ PropertiesNode node = ser.encode(params);
+
+ Map<String, PropertiesNode> childNodes = ((RootNode) node).children();
+
+ assertThat(childNodes.containsKey("cont11"), is(true));
+ SingleInstanceNode cont4 = ((SingleInstanceNode) childNodes.get("cont11"));
+ assertThat(cont4.uri(), is("test-yang:cont9.cont11"));
+ assertThat(cont4.children().containsKey("leaf25"), is(true));
+ LeafNode l = ((LeafNode) cont4.children().get("leaf25"));
+ assertThat(l.uri(), is("test-yang:cont9.cont11.leaf25"));
+
+ assertThat(childNodes.containsKey("leaf20"), is(true));
+ l = ((LeafNode) childNodes.get("leaf20"));
+ assertThat(l.uri(), is("test-yang:cont9.leaf20"));
+
+ LeafListHolderNode ll5Holder = ((LeafListHolderNode) childNodes.get("ll8"));
+ assertThat(ll5Holder.uri(), is("test-yang:cont9.ll8"));
+ assertThat(ll5Holder.children().containsKey("0"), is(true));
+ l = ((LeafNode) ll5Holder.children().get("0"));
+ assertThat(l.uri(), is("test-yang:cont9.ll8[0]"));
+
+ Map<String, String> output = ser.decode(node);
+ assertThat(output.size(), is(params.size()));
+ for (Map.Entry<String, String> entry : output.entrySet()) {
+ assertTrue(params.containsKey(entry.getKey()));
+ }
+ }
+
+ @Test
+ public void testChoiceCase3() throws SvcLogicException {
+ String uri = "test-yang:cont8/cont6";
+ Map<String, String> params = new HashMap<>();
+ params.put("test-yang_cont8.cont6.test-augment_leaf21", "abc");
+
+ InstanceIdentifierContext<?> iCtx = ParserIdentifier
+ .toInstanceIdentifier(uri, context, null);
+ PropertiesNodeSerializer ser = new MdsalPropertiesNodeSerializer(
+ iCtx.getSchemaNode(), context, uri);
+ PropertiesNode node = ser.encode(params);
+
+ for (Map.Entry<Object, Collection<PropertiesNode>> augToChild
+ : node.augmentations().asMap().entrySet()) {
+ Collection<PropertiesNode> child = augToChild.getValue();
+ if (!child.isEmpty()) {
+ List<String> expectedNodes = new LinkedList<>();
+ expectedNodes.add("test-yang:cont8.cont6.test-augment:leaf21");
+ assertThat(expectedNodes.size(), is(child.size()));
+ for (PropertiesNode pNode : child) {
+ assertThat(expectedNodes.contains(pNode.uri()), is(true));
+ }
+ }
+ }
+
+ Map<String, PropertiesNode> childNodes = ((RootNode) node).children();
+
+ assertThat(childNodes.containsKey("leaf21"), is(true));
+ LeafNode leaf12 = ((LeafNode) childNodes.get("leaf21"));
+ assertThat(leaf12.name(), is("leaf21"));
+ assertThat(leaf12.uri(), is("test-yang:cont8.cont6.test-augment:leaf21"));
+
+ Map<String, String> output = ser.decode(node);
+ assertThat(output.size(), is(params.size()));
+ for (Map.Entry<String, String> entry : output.entrySet()) {
+ assertTrue(params.containsKey(entry.getKey()));
+ }
+ }
+
+ @Test
+ public void testGrouping() throws SvcLogicException {
+ String uri = "test-yang:cont13";
+ Map<String, String> params = new HashMap<>();
+ params.put("test-yang_cont13.cont12.leaf26", "abc");
+ params.put("test-yang_cont13.list9[0].leaf27", "abc");
+ params.put("test-yang_cont13.leaf28", "abc");
+ params.put("test-yang_cont13.ll9[0]", "abc");
+
+ InstanceIdentifierContext<?> iCtx = ParserIdentifier
+ .toInstanceIdentifier(uri, context, null);
+ PropertiesNodeSerializer ser = new MdsalPropertiesNodeSerializer(
+ iCtx.getSchemaNode(), context, uri);
+ PropertiesNode node = ser.encode(params);
+
+ Map<String, PropertiesNode> childNodes = ((RootNode) node).children();
+
+ assertThat(childNodes.containsKey("cont12"), is(true));
+ SingleInstanceNode cont4 = ((SingleInstanceNode) childNodes.get("cont12"));
+ assertThat(cont4.uri(), is("test-yang:cont13.cont12"));
+ assertThat(cont4.children().containsKey("leaf26"), is(true));
+ LeafNode l = ((LeafNode) cont4.children().get("leaf26"));
+ assertThat(l.uri(), is("test-yang:cont13.cont12.leaf26"));
+
+ assertThat(childNodes.containsKey("list9"), is(true));
+ HolderNode list6Holder = ((ListHolderNode) childNodes.get("list9"));
+ assertThat(list6Holder.uri(), is("test-yang:cont13.list9"));
+ MultiInstanceNode list6 = ((MultiInstanceNode) list6Holder.child("0"));
+ assertThat(list6.uri(), is("test-yang:cont13.list9[0]"));
+ Map<String, DataNodeChild> list6Child = list6.children();
+ assertThat(list6Child.containsKey("leaf27"), is(true));
+ l = ((LeafNode) list6Child.get("leaf27"));
+ assertThat(l.uri(), is("test-yang:cont13.list9[0].leaf27"));
+
+ assertThat(childNodes.containsKey("leaf28"), is(true));
+ LeafNode leaf12 = ((LeafNode) childNodes.get("leaf28"));
+ assertThat(leaf12.name(), is("leaf28"));
+ assertThat(leaf12.uri(), is("test-yang:cont13.leaf28"));
+
+ LeafListHolderNode ll5Holder = ((LeafListHolderNode) childNodes.get("ll9"));
+ assertThat(ll5Holder.children().containsKey("0"), is(true));
+
+ Map<String, String> output = ser.decode(node);
+ assertThat(output.size(), is(params.size()));
+ for (Map.Entry<String, String> entry : output.entrySet()) {
+ assertTrue(params.containsKey(entry.getKey()));
+ }
+ }
+
+ @Test
+ public void testGrouping2() throws SvcLogicException {
+ String uri = "test-yang:cont9/cont11";
+ Map<String, String> params = new HashMap<>();
+ params.put("test-yang_cont9.cont11.leaf25", "abc");
+ params.put("test-yang_cont9.cont11.cont13.cont12.leaf26", "abc");
+ params.put("test-yang_cont9.cont11.cont13.list9[0].leaf27", "abc");
+ params.put("test-yang_cont9.cont11.cont13.leaf28", "abc");
+ params.put("test-yang_cont9.cont11.cont13.ll9[0]", "abc");
+ InstanceIdentifierContext<?> iCtx = ParserIdentifier
+ .toInstanceIdentifier(uri, context, null);
+ PropertiesNodeSerializer ser = new MdsalPropertiesNodeSerializer(
+ iCtx.getSchemaNode(), context, uri);
+ PropertiesNode node = ser.encode(params);
+
+ Map<String, PropertiesNode> childNodes = ((RootNode) node).children();
+
+ assertThat(childNodes.containsKey("cont13"), is(true));
+ SingleInstanceNode cont13 = ((SingleInstanceNode) childNodes.get("cont13"));
+ assertThat(cont13.uri(), is("test-yang:cont9.cont11.cont13"));
+ SingleInstanceNode cont12 = ((SingleInstanceNode) cont13.children().get("cont12"));
+ assertThat(cont12.children().containsKey("leaf26"), is(true));
+ assertThat(cont12.uri(), is("test-yang:cont9.cont11.cont13.cont12"));
+ assertThat(cont12.children().containsKey("leaf26"), is(true));
+ LeafNode l = ((LeafNode) cont12.children().get("leaf26"));
+ assertThat(l.uri(), is("test-yang:cont9.cont11.cont13.cont12.leaf26"));
+
+ assertThat(cont13.children().containsKey("list9"), is(true));
+ HolderNode list6Holder = ((ListHolderNode) cont13.children().get("list9"));
+ assertThat(list6Holder.uri(), is("test-yang:cont9.cont11.cont13.list9"));
+ MultiInstanceNode list6 = ((MultiInstanceNode) list6Holder.child("0"));
+ assertThat(list6.uri(), is("test-yang:cont9.cont11.cont13.list9[0]"));
+ Map<String, DataNodeChild> list6Child = list6.children();
+ assertThat(list6Child.containsKey("leaf27"), is(true));
+ l = ((LeafNode) list6Child.get("leaf27"));
+ assertThat(l.uri(), is("test-yang:cont9.cont11.cont13.list9[0].leaf27"));
+
+ assertThat(cont13.children().containsKey("leaf28"), is(true));
+ LeafNode leaf12 = ((LeafNode) cont13.children().get("leaf28"));
+ assertThat(leaf12.name(), is("leaf28"));
+ assertThat(leaf12.uri(), is("test-yang:cont9.cont11.cont13.leaf28"));
+
+ LeafListHolderNode ll5Holder = ((LeafListHolderNode) cont13.children().get("ll9"));
+ assertThat(ll5Holder.uri(), is("test-yang:cont9.cont11.cont13.ll9"));
+ assertThat(ll5Holder.children().containsKey("0"), is(true));
+ l = ((LeafNode) ll5Holder.children().get("0"));
+ assertThat(l.uri(), is("test-yang:cont9.cont11.cont13.ll9[0]"));
+
+ Map<String, String> output = ser.decode(node);
+ assertThat(output.size(), is(params.size()));
+ for (Map.Entry<String, String> entry : output.entrySet()) {
+ assertTrue(params.containsKey(entry.getKey()));
+ }
+ }
+
+ @Test
+ public void testGrouping3() throws SvcLogicException {
+ String uri = "test-augment:cont13";
+ Map<String, String> params = new HashMap<>();
+ params.put("test-augment_cont13.cont12.leaf26", "abc");
+ params.put("test-augment_cont13.list9[0].leaf27", "abc");
+ params.put("test-augment_cont13.leaf28", "abc");
+ params.put("test-augment_cont13.ll9[0]", "abc");
+ InstanceIdentifierContext<?> iCtx = ParserIdentifier
+ .toInstanceIdentifier(uri, context, null);
+ PropertiesNodeSerializer ser = new MdsalPropertiesNodeSerializer(
+ iCtx.getSchemaNode(), context, uri);
+ PropertiesNode node = ser.encode(params);
+
+ Map<String, PropertiesNode> childNodes = ((RootNode) node).children();
+
+ assertThat(childNodes.containsKey("cont12"), is(true));
+ SingleInstanceNode cont12 = ((SingleInstanceNode) childNodes.get("cont12"));
+ assertThat(cont12.uri(), is("test-augment:cont13.cont12"));
+ assertThat(cont12.children().containsKey("leaf26"), is(true));
+ LeafNode l = ((LeafNode) cont12.children().get("leaf26"));
+ assertThat(l.uri(), is("test-augment:cont13.cont12.leaf26"));
+
+ assertThat(childNodes.containsKey("list9"), is(true));
+ HolderNode list6Holder = ((ListHolderNode) childNodes.get("list9"));
+ assertThat(list6Holder.uri(), is("test-augment:cont13.list9"));
+ MultiInstanceNode list6 = ((MultiInstanceNode) list6Holder.child("0"));
+ assertThat(list6.uri(), is("test-augment:cont13.list9[0]"));
+ Map<String, DataNodeChild> list6Child = list6.children();
+ assertThat(list6Child.containsKey("leaf27"), is(true));
+ l = ((LeafNode) list6Child.get("leaf27"));
+ assertThat(l.uri(), is("test-augment:cont13.list9[0].leaf27"));
+
+ assertThat(childNodes.containsKey("leaf28"), is(true));
+ LeafNode leaf12 = ((LeafNode) childNodes.get("leaf28"));
+ assertThat(leaf12.name(), is("leaf28"));
+ assertThat(leaf12.uri(), is("test-augment:cont13.leaf28"));
+
+ LeafListHolderNode ll5Holder = ((LeafListHolderNode) childNodes.get("ll9"));
+ assertThat(ll5Holder.uri(), is("test-augment:cont13.ll9"));
+ assertThat(ll5Holder.children().containsKey("0"), is(true));
+ l = ((LeafNode) ll5Holder.children().get("0"));
+ assertThat(l.uri(), is("test-augment:cont13.ll9[0]"));
+
+ Map<String, String> output = ser.decode(node);
+ assertThat(output.size(), is(params.size()));
+ for (Map.Entry<String, String> entry : output.entrySet()) {
+ assertTrue(params.containsKey(entry.getKey()));
+ }
+ }
+
+ @Test
+ public void testGrouping4() throws SvcLogicException {
+ String uri = "test-yang:cont1/cont2/cont4";
+ Map<String, String> params = new HashMap<>();
+ params.put("test-yang_cont1.cont2.cont4.test-augment_cont13.cont12.leaf26", "abc");
+ params.put("test-yang_cont1.cont2.cont4.test-augment_cont13.list9[0].leaf27", "abc");
+ params.put("test-yang_cont1.cont2.cont4.test-augment_cont13.leaf28", "abc");
+ params.put("test-yang_cont1.cont2.cont4.test-augment_cont13.ll9[0]", "abc");
+
+ InstanceIdentifierContext<?> iCtx = ParserIdentifier
+ .toInstanceIdentifier(uri, context, null);
+ PropertiesNodeSerializer ser = new MdsalPropertiesNodeSerializer(
+ iCtx.getSchemaNode(), context, uri);
+ PropertiesNode node = ser.encode(params);
+
+ for (Map.Entry<Object, Collection<PropertiesNode>> augToChild
+ : node.augmentations().asMap().entrySet()) {
+ Collection<PropertiesNode> child = augToChild.getValue();
+ if (!child.isEmpty()) {
+ List<String> expectedNodes = new LinkedList<>();
+ expectedNodes.add("test-yang:cont1.cont2.cont4.test-augment:cont13");
+ assertThat(expectedNodes.size(), is(child.size()));
+ for (PropertiesNode pNode : child) {
+ assertThat(expectedNodes.contains(pNode.uri()), is(true));
+ SingleInstanceNode cont13 = ((SingleInstanceNode) pNode);
+ assertThat(cont13.uri(), is("test-yang:cont1.cont2.cont4.test-augment:cont13"));
+ SingleInstanceNode cont12 = ((SingleInstanceNode) cont13.children().get("cont12"));
+ assertThat(cont12.children().containsKey("leaf26"), is(true));
+ LeafNode l = ((LeafNode) cont12.children().get("leaf26"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.cont4.test-augment:cont13.cont12.leaf26"));
+
+ assertThat(cont13.children().containsKey("list9"), is(true));
+ HolderNode list6Holder = ((ListHolderNode) cont13.children().get("list9"));
+ assertThat(list6Holder.uri(), is("test-yang:cont1.cont2.cont4.test-augment:cont13.list9"));
+ MultiInstanceNode list6 = ((MultiInstanceNode) list6Holder.child("0"));
+ assertThat(list6.uri(), is("test-yang:cont1.cont2.cont4.test-augment:cont13.list9[0]"));
+ Map<String, DataNodeChild> list6Child = list6.children();
+ assertThat(list6Child.containsKey("leaf27"), is(true));
+ l = ((LeafNode) list6Child.get("leaf27"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.cont4.test-augment:cont13.list9[0].leaf27"));
+
+ assertThat(cont13.children().containsKey("leaf28"), is(true));
+ LeafNode leaf12 = ((LeafNode) cont13.children().get("leaf28"));
+ assertThat(leaf12.name(), is("leaf28"));
+ assertThat(leaf12.uri(), is("test-yang:cont1.cont2.cont4.test-augment:cont13.leaf28"));
+
+ LeafListHolderNode ll5Holder = ((LeafListHolderNode) cont13.children().get("ll9"));
+ assertThat(ll5Holder.uri(), is("test-yang:cont1.cont2.cont4.test-augment:cont13.ll9"));
+ assertThat(ll5Holder.children().containsKey("0"), is(true));
+ l = ((LeafNode) ll5Holder.children().get("0"));
+ assertThat(l.uri(), is("test-yang:cont1.cont2.cont4.test-augment:cont13.ll9[0]"));
+ }
+ }
+ }
+
+ Map<String, String> output = ser.decode(node);
+ assertThat(output.size(), is(params.size()));
+ for (Map.Entry<String, String> entry : output.entrySet()) {
+ assertTrue(params.containsKey(entry.getKey()));
+ }
+ }
+
+ @Test
+ public void testRpcInput() throws SvcLogicException {
+ String uri = "test-yang:create-sfc";
+ Map<String, String> params = new HashMap<>();
+ params.put("test-yang_create-sfc.input.cont14.leaf28", "abc");
+ params.put("test-yang_create-sfc.input.list10[0].leaf29", "abc");
+ params.put("test-yang_create-sfc.input.leaf30", "abc");
+ params.put("test-yang_create-sfc.input.ll10[0]", "abc");
+ params.put("test-yang_create-sfc.input.cont15.leaf31", "abc");
+ params.put("test-yang_create-sfc.input.cont13.cont12.leaf26", "abc");
+ params.put("test-yang_create-sfc.input.cont13.list9[0].leaf27", "abc");
+ params.put("test-yang_create-sfc.input.cont13.leaf28", "abc");
+ params.put("test-yang_create-sfc.input.cont13.ll9[0]", "abc");
+ params.put("test-yang_create-sfc.input.test-augment_leaf36", "abc");
+
+ InstanceIdentifierContext<?> iCtx = ParserIdentifier
+ .toInstanceIdentifier(uri, context, null);
+ PropertiesNodeSerializer ser = new MdsalPropertiesNodeSerializer(
+ iCtx.getSchemaNode(), context, uri);
+ PropertiesNode node = ser.encode(params);
+
+ Map<String, PropertiesNode> childNodes = ((RootNode) node).children();
+
+ PropertiesNode input = childNodes.get("input");
+ assertThat(input.uri(), is("test-yang:create-sfc.input"));
+ for (Map.Entry<Object, Collection<PropertiesNode>> augToChild
+ : node.augmentations().asMap().entrySet()) {
+ Collection<PropertiesNode> child = augToChild.getValue();
+ if (!child.isEmpty()) {
+ List<String> expectedNodes = new LinkedList<>();
+ expectedNodes.add("test-yang:create-sfc.input.test-augment:leaf36");
+ assertThat(expectedNodes.size(), is(child.size()));
+ for (PropertiesNode pNode : child) {
+ assertThat(expectedNodes.contains(pNode.uri()), is(true));
+ LeafNode leaf37 = ((LeafNode) pNode);
+ assertThat(leaf37.name(), is("leaf36"));
+ assertThat(leaf37.uri(), is("test-yang:create-sfc.input.test-augment:leaf36"));
+ }
+ }
+ }
+ childNodes = ((InnerNode) input).children();
+
+ assertThat(childNodes.containsKey("cont14"), is(true));
+ SingleInstanceNode cont14 = ((SingleInstanceNode) childNodes.get("cont14"));
+ assertThat(cont14.uri(), is("test-yang:create-sfc.input.cont14"));
+ assertThat(cont14.children().containsKey("leaf28"), is(true));
+ LeafNode l = ((LeafNode) cont14.children().get("leaf28"));
+ assertThat(l.uri(), is("test-yang:create-sfc.input.cont14.leaf28"));
+
+ assertThat(childNodes.containsKey("list10"), is(true));
+ HolderNode list10Holder = ((ListHolderNode) childNodes.get("list10"));
+ assertThat(list10Holder.uri(), is("test-yang:create-sfc.input.list10"));
+ MultiInstanceNode list10 = ((MultiInstanceNode) list10Holder.child("0"));
+ assertThat(list10.uri(), is("test-yang:create-sfc.input.list10[0]"));
+ Map<String, DataNodeChild> list10Child = list10.children();
+ assertThat(list10Child.containsKey("leaf29"), is(true));
+ l = ((LeafNode) list10Child.get("leaf29"));
+ assertThat(l.uri(), is("test-yang:create-sfc.input.list10[0].leaf29"));
+
+ assertThat(childNodes.containsKey("leaf30"), is(true));
+ LeafNode leaf30 = ((LeafNode) childNodes.get("leaf30"));
+ assertThat(leaf30.name(), is("leaf30"));
+ assertThat(leaf30.uri(), is("test-yang:create-sfc.input.leaf30"));
+
+ LeafListHolderNode ll10Holder = ((LeafListHolderNode) childNodes.get("ll10"));
+ assertThat(ll10Holder.uri(), is("test-yang:create-sfc.input.ll10"));
+ assertThat(ll10Holder.children().containsKey("0"), is(true));
+ l = ((LeafNode) ll10Holder.children().get("0"));
+ assertThat(l.uri(), is("test-yang:create-sfc.input.ll10[0]"));
+
+ assertThat(childNodes.containsKey("cont15"), is(true));
+ SingleInstanceNode cont15 = ((SingleInstanceNode) childNodes.get("cont15"));
+ assertThat(cont15.uri(), is("test-yang:create-sfc.input.cont15"));
+ assertThat(cont15.children().containsKey("leaf31"), is(true));
+ l = ((LeafNode) cont15.children().get("leaf31"));
+ assertThat(l.uri(), is("test-yang:create-sfc.input.cont15.leaf31"));
+
+ assertThat(childNodes.containsKey("cont13"), is(true));
+ SingleInstanceNode cont13 = ((SingleInstanceNode) childNodes.get("cont13"));
+ assertThat(cont13.uri(), is("test-yang:create-sfc.input.cont13"));
+ SingleInstanceNode cont12 = ((SingleInstanceNode) cont13.children().get("cont12"));
+ assertThat(cont12.uri(), is("test-yang:create-sfc.input.cont13.cont12"));
+ assertThat(cont12.children().containsKey("leaf26"), is(true));
+ l = ((LeafNode) cont12.children().get("leaf26"));
+ assertThat(l.uri(), is("test-yang:create-sfc.input.cont13.cont12.leaf26"));
+
+ assertThat(cont13.children().containsKey("list9"), is(true));
+ HolderNode list9Holder = ((ListHolderNode) cont13.children().get("list9"));
+ assertThat(list9Holder.uri(), is("test-yang:create-sfc.input.cont13.list9"));
+ MultiInstanceNode list9 = ((MultiInstanceNode) list9Holder.child("0"));
+ assertThat(list9.uri(), is("test-yang:create-sfc.input.cont13.list9[0]"));
+ Map<String, DataNodeChild> list6Child = list9.children();
+ assertThat(list6Child.containsKey("leaf27"), is(true));
+ l = ((LeafNode) list6Child.get("leaf27"));
+ assertThat(l.uri(), is("test-yang:create-sfc.input.cont13.list9[0].leaf27"));
+
+ assertThat(cont13.children().containsKey("leaf28"), is(true));
+ LeafNode leaf12 = ((LeafNode) cont13.children().get("leaf28"));
+ assertThat(leaf12.name(), is("leaf28"));
+ assertThat(leaf12.uri(), is("test-yang:create-sfc.input.cont13.leaf28"));
+
+ LeafListHolderNode ll5Holder = ((LeafListHolderNode) cont13.children().get("ll9"));
+ assertThat(ll5Holder.uri(), is("test-yang:create-sfc.input.cont13.ll9"));
+ assertThat(ll5Holder.children().containsKey("0"), is(true));
+ l = ((LeafNode) ll5Holder.children().get("0"));
+ assertThat(l.uri(), is("test-yang:create-sfc.input.cont13.ll9[0]"));
+
+ Map<String, String> output = ser.decode(node);
+ assertThat(output.size(), is(params.size()));
+ for (Map.Entry<String, String> entry : output.entrySet()) {
+ assertTrue(params.containsKey(entry.getKey()));
+ }
+ }
+
+ @Test
+ public void testRpcOutput() throws SvcLogicException {
+ String uri = "test-yang:create-sfc";
+ Map<String, String> params = new HashMap<>();
+ params.put("test-yang_create-sfc.output.cont16.leaf32", "abc");
+ params.put("test-yang_create-sfc.output.list11[0].leaf33", "abc");
+ params.put("test-yang_create-sfc.output.leaf34", "abc");
+ params.put("test-yang_create-sfc.output.ll11[0]", "abc");
+ params.put("test-yang_create-sfc.output.cont17.leaf35", "abc");
+ params.put("test-yang_create-sfc.output.cont13.cont12.leaf26", "abc");
+ params.put("test-yang_create-sfc.output.cont13.list9[0].leaf27", "abc");
+ params.put("test-yang_create-sfc.output.cont13.leaf28", "abc");
+ params.put("test-yang_create-sfc.output.cont13.ll9[0]", "abc");
+ params.put("test-yang_create-sfc.output.test-augment_leaf37", "abc");
+
+ InstanceIdentifierContext<?> iCtx = ParserIdentifier
+ .toInstanceIdentifier(uri, context, null);
+ PropertiesNodeSerializer ser = new MdsalPropertiesNodeSerializer(
+ iCtx.getSchemaNode(), context, uri);
+ PropertiesNode node = ser.encode(params);
+
+ Map<String, PropertiesNode> childNodes = ((RootNode) node).children();
+
+ PropertiesNode output = childNodes.get("output");
+ assertThat(output.uri(), is("test-yang:create-sfc.output"));
+ for (Map.Entry<Object, Collection<PropertiesNode>> augmentationToChild :
+ node.augmentations().asMap().entrySet()) {
+ Collection<PropertiesNode> c = augmentationToChild.getValue();
+ if(!c.isEmpty()) {
+ List<String> expectedNodes = new LinkedList<>();
+ expectedNodes.add("test-yang:create-sfc.output.test-augment:leaf37");
+ assertThat(expectedNodes.size(), is(expectedNodes));
+ for (PropertiesNode pNode : c) {
+ assertThat(expectedNodes.contains(pNode.uri()), is(true));
+ LeafNode leaf37 = ((LeafNode) pNode);
+ assertThat(leaf37.name(), is("leaf37"));
+ assertThat(leaf37.uri(), is("test-yang:create-sfc.output.test-augment:leaf37"));
+ }
+ }
+ }
+ childNodes = ((InnerNode) output).children();
+
+ assertThat(childNodes.containsKey("cont16"), is(true));
+ SingleInstanceNode cont16 = ((SingleInstanceNode) childNodes.get("cont16"));
+ assertThat(cont16.uri(), is("test-yang:create-sfc.output.cont16"));
+ assertThat(cont16.children().containsKey("leaf32"), is(true));
+ LeafNode l = ((LeafNode) cont16.children().get("leaf32"));
+ assertThat(l.uri(), is("test-yang:create-sfc.output.cont16.leaf32"));
+
+ assertThat(childNodes.containsKey("list11"), is(true));
+ HolderNode list11Holder = ((ListHolderNode) childNodes.get("list11"));
+ assertThat(list11Holder.uri(), is("test-yang:create-sfc.output.list11"));
+ MultiInstanceNode list11 = ((MultiInstanceNode) list11Holder.child("0"));
+ assertThat(list11.uri(), is("test-yang:create-sfc.output.list11[0]"));
+ Map<String, DataNodeChild> list11Child = list11.children();
+ assertThat(list11Child.containsKey("leaf33"), is(true));
+ l = ((LeafNode) list11Child.get("leaf33"));
+ assertThat(l.uri(), is("test-yang:create-sfc.output.list11[0].leaf33"));
+
+ assertThat(childNodes.containsKey("leaf34"), is(true));
+ LeafNode leaf34 = ((LeafNode) childNodes.get("leaf34"));
+ assertThat(leaf34.name(), is("leaf34"));
+ assertThat(leaf34.uri(), is("test-yang:create-sfc.output.leaf34"));
+
+ LeafListHolderNode ll10Holder = ((LeafListHolderNode) childNodes.get("ll11"));
+ assertThat(ll10Holder.uri(), is("test-yang:create-sfc.output.ll11"));
+ assertThat(ll10Holder.children().containsKey("0"), is(true));
+ l = ((LeafNode) ll10Holder.children().get("0"));
+ assertThat(l.uri(), is("test-yang:create-sfc.output.ll11[0]"));
+
+ assertThat(childNodes.containsKey("cont17"), is(true));
+ SingleInstanceNode cont17 = ((SingleInstanceNode) childNodes.get("cont17"));
+ assertThat(cont17.uri(), is("test-yang:create-sfc.output.cont17"));
+ assertThat(cont17.children().containsKey("leaf35"), is(true));
+ l = ((LeafNode) cont17.children().get("leaf35"));
+ assertThat(l.uri(), is("test-yang:create-sfc.output.cont17.leaf35"));
+
+ assertThat(childNodes.containsKey("cont13"), is(true));
+ SingleInstanceNode cont13 = ((SingleInstanceNode) childNodes.get("cont13"));
+ assertThat(cont13.uri(), is("test-yang:create-sfc.output.cont13"));
+ SingleInstanceNode cont12 = ((SingleInstanceNode) cont13.children().get("cont12"));
+ assertThat(cont12.uri(), is("test-yang:create-sfc.output.cont13.cont12"));
+ assertThat(cont12.children().containsKey("leaf26"), is(true));
+ l = ((LeafNode) cont12.children().get("leaf26"));
+ assertThat(l.uri(), is("test-yang:create-sfc.output.cont13.cont12.leaf26"));
+
+ assertThat(cont13.children().containsKey("list9"), is(true));
+ HolderNode list9Holder = ((ListHolderNode) cont13.children().get("list9"));
+ assertThat(list9Holder.uri(), is("test-yang:create-sfc.output.cont13.list9"));
+ MultiInstanceNode list9 = ((MultiInstanceNode) list9Holder.child("0"));
+ assertThat(list9.uri(), is("test-yang:create-sfc.output.cont13.list9[0]"));
+ Map<String, DataNodeChild> list6Child = list9.children();
+ assertThat(list6Child.containsKey("leaf27"), is(true));
+ l = ((LeafNode) list6Child.get("leaf27"));
+ assertThat(l.uri(), is("test-yang:create-sfc.output.cont13.list9[0].leaf27"));
+
+ assertThat(cont13.children().containsKey("leaf28"), is(true));
+ LeafNode leaf12 = ((LeafNode) cont13.children().get("leaf28"));
+ assertThat(leaf12.name(), is("leaf28"));
+ assertThat(leaf12.uri(), is("test-yang:create-sfc.output.cont13.leaf28"));
+
+ LeafListHolderNode ll5Holder = ((LeafListHolderNode) cont13.children().get("ll9"));
+ assertThat(ll5Holder.uri(), is("test-yang:create-sfc.output.cont13.ll9"));
+ assertThat(ll5Holder.children().containsKey("0"), is(true));
+ l = ((LeafNode) ll5Holder.children().get("0"));
+ assertThat(l.uri(), is("test-yang:create-sfc.output.cont13.ll9[0]"));
+
+ Map<String, String> output1 = ser.decode(node);
+ assertThat(output1.size(), is(params.size()));
+ for (Map.Entry<String, String> entry : output1.entrySet()) {
+ assertTrue(params.containsKey(entry.getKey()));
+ }
+ }
+
+ @Test
+ public void testContainerSameName() throws SvcLogicException {
+ String uri = "test-yang:cont18";
+ Map<String, String> params = new HashMap<>();
+ params.put("test-yang_cont18.cont18.list12[0].list12[0].leaf36", "abc");
+ params.put("test-yang_cont18.cont18.list12[0].leaf36", "hi");
+ params.put("test-yang_cont18.cont18.list12[1].list12[0].leaf36", "xyz");
+ params.put("test-yang_cont18.cont18.list12[1].list12[1].leaf36", "hey!");
+
+ InstanceIdentifierContext<?> iCtx = ParserIdentifier
+ .toInstanceIdentifier(uri, context, null);
+ PropertiesNodeSerializer ser = new MdsalPropertiesNodeSerializer(
+ iCtx.getSchemaNode(), context, uri);
+ PropertiesNode node = ser.encode(params);
+
+ Map<String, PropertiesNode> childNodes = ((RootNode) node).children();
+
+ assertThat(childNodes.containsKey("cont18"), is(true));
+ node = childNodes.get("cont18");
+ assertThat(node.uri(), is("test-yang:cont18.cont18"));
+ childNodes = ((InnerNode) node).children();
+
+ assertThat(childNodes.containsKey("list12"), is(true));
+ HolderNode holder = ((ListHolderNode) childNodes.get("list12"));
+ assertThat(holder.uri(), is("test-yang:cont18.cont18.list12"));
+ MultiInstanceNode node1 = ((MultiInstanceNode) holder.child("0"));
+ assertThat(node1.uri(), is("test-yang:cont18.cont18.list12[0]"));
+ Map<String, DataNodeChild> list12Child = node1.children();
+
+ assertThat(list12Child.containsKey("leaf36"), is(true));
+ LeafNode leaf = ((LeafNode) list12Child.get("leaf36"));
+ assertThat(leaf.value(), is("hi"));
+ assertThat(leaf.uri(), is("test-yang:cont18.cont18.list12[0].leaf36"));
+
+ assertThat(list12Child.containsKey("list12"), is(true));
+ HolderNode holder1 = ((ListHolderNode) list12Child.get("list12"));
+ assertThat(holder1.uri(), is("test-yang:cont18.cont18.list12[0].list12"));
+ node1 = ((MultiInstanceNode) holder1.child("0"));
+ assertThat(node1.uri(), is("test-yang:cont18.cont18.list12[0].list12[0]"));
+ list12Child = node1.children();
+ assertThat(list12Child.containsKey("leaf36"), is(true));
+ leaf = ((LeafNode) list12Child.get("leaf36"));
+ assertThat(leaf.value(), is("abc"));
+ assertThat(leaf.uri(), is("test-yang:cont18.cont18.list12[0].list12[0].leaf36"));
+
+ node1 = ((MultiInstanceNode) holder.child("1"));
+ assertThat(node1.uri(), is("test-yang:cont18.cont18.list12[1]"));
+ list12Child = node1.children();
+ assertThat(list12Child.containsKey("list12"), is(true));
+ holder = ((ListHolderNode) list12Child.get("list12"));
+ assertThat(holder.uri(), is("test-yang:cont18.cont18.list12[1].list12"));
+ node1 = ((MultiInstanceNode) holder.child("0"));
+ assertThat(node1.uri(), is("test-yang:cont18.cont18.list12[1].list12[0]"));
+ assertThat(node1.children().containsKey("leaf36"), is(true));
+ leaf = ((LeafNode) node1.children().get("leaf36"));
+ assertThat(leaf.value(), is("xyz"));
+ assertThat(leaf.uri(), is("test-yang:cont18.cont18.list12[1].list12[0].leaf36"));
+
+ node1 = ((MultiInstanceNode) holder.child("1"));
+ assertThat(node1.uri(), is("test-yang:cont18.cont18.list12[1].list12[1]"));
+ assertThat(node1.children().containsKey("leaf36"), is(true));
+ leaf = ((LeafNode) node1.children().get("leaf36"));
+ assertThat(leaf.value(), is("hey!"));
+ assertThat(leaf.uri(), is("test-yang:cont18.cont18.list12[1].list12[1].leaf36"));
+
+ Map<String, String> output1 = ser.decode(node);
+ assertThat(output1.size(), is(params.size()));
+ for (Map.Entry<String, String> entry : output1.entrySet()) {
+ assertTrue(params.containsKey(entry.getKey()));
+ }
+ }
+
+ @Test
+ public void testPropertiesWithoutSchema() throws SvcLogicException {
+ String uri = "test-yang:cont18";
+ Map<String, String> params = new HashMap<>();
+ params.put("test-yang_cont18.leaf40", "abc");
+ params.put("leaf41", "hi");
+ params.put("test-yang_cont18.leaf41", "abc");
+
+ InstanceIdentifierContext<?> iCtx = ParserIdentifier
+ .toInstanceIdentifier(uri, context, null);
+ PropertiesNodeSerializer ser = new MdsalPropertiesNodeSerializer(
+ iCtx.getSchemaNode(), context, uri);
+ PropertiesNode node = ser.encode(params);
+
+ Map<String, PropertiesNode> childNodes = ((RootNode) node).children();
+ assertThat(childNodes.containsKey("leaf40"), is(true));
+ node = childNodes.get("leaf40");
+ assertThat(node.uri(), is("test-yang:cont18.leaf40"));
+ }
+
+ @Test
+ public void testIdentityRef() throws SvcLogicException {
+ String uri = "identity-test:test";
+ Map<String, String> params = new HashMap<>();
+ params.put("identity-test_test.con1.interface", "identity-types" +
+ ":physical");
+ params.put("identity-test_test.con1.interfaces.int-list[0].iden", "identity-test:Giga");
+ params.put("identity-test_test.con1.interfaces.int-list[0].available.ll[0]", "identity-types:Loopback");
+ params.put("identity-test_test.con1.interfaces.int-list[0].available.leaf1", "identity-types-second:Ethernet");
+ params.put("identity-test_test.con1.interfaces.int-list[0].available.leaf2", "identity-types-second:iden2");
+ InstanceIdentifierContext<?> iCtx = ParserIdentifier
+ .toInstanceIdentifier(uri, context, null);
+
+ PropertiesNodeSerializer ser = new MdsalPropertiesNodeSerializer(
+ iCtx.getSchemaNode(), context, uri);
+ PropertiesNode node = ser.encode(params);
+ Map<String, PropertiesNode> childNodes = ((RootNode) node).children();
+ assertThat(childNodes.containsKey("con1"), is(true));
+ node = childNodes.get("con1");
+ assertThat(node.uri(), is("identity-test:test.con1"));
+ LeafNode l = ((LeafNode) ((SingleInstanceNode) node).children().get("interface"));
+ assertThat(l.uri(), is("identity-test:test.con1.interface"));
+ assertThat(l.valueNs().moduleName(), is("identity-types"));
+ assertThat(l.valueNs().moduleNs().toString(), is("identity:list:ns:test:json:ser"));
+
+ // identity type inside union
+ node = ((SingleInstanceNode) ((SingleInstanceNode) node).children().get("interfaces"));
+ node = ((ListHolderNode) ((SingleInstanceNode) node).children().get("int-list"));
+ node = ((MultiInstanceNode) ((ListHolderNode) node).children().get("0"));
+ l = ((LeafNode) ((MultiInstanceNode) node).children().get("iden"));
+ assertThat(l.uri(), is("identity-test:test.con1.interfaces.int-list[0].iden"));
+ assertThat(l.valueNs().moduleName(), is("identity-test"));
+ assertThat(l.valueNs().moduleNs().toString(), is("identity:ns:test:json:ser"));
+
+ // leaf-list test
+ node = (SingleInstanceNode) ((MultiInstanceNode) node).children().get("available");
+ LeafListHolderNode holder = (LeafListHolderNode) ((SingleInstanceNode) node).children().get("ll");
+ l = ((LeafNode) holder.children().get("0"));
+ assertThat(l.uri(), is("identity-test:test.con1.interfaces.int-list[0].available.ll[0]"));
+ assertThat(l.valueNs().moduleName(), is("identity-types"));
+ assertThat(l.valueNs().moduleNs().toString(), is("identity:list:ns:test:json:ser"));
+
+ // leaf-ref test
+ l = ((LeafNode) ((SingleInstanceNode) node).children().get("leaf1"));
+ assertThat(l.uri(), is("identity-test:test.con1.interfaces.int-list[0].available.leaf1"));
+ assertThat(l.valueNs().moduleName(), is("identity-types-second"));
+ assertThat(l.valueNs().moduleNs().toString(), is("identity:list:second:ns:test:json:ser"));
+
+ // list of base identity test
+ l = ((LeafNode) ((SingleInstanceNode) node).children().get("leaf2"));
+ assertThat(l.uri(), is("identity-test:test.con1.interfaces.int-list[0].available.leaf2"));
+ assertThat(l.valueNs().moduleName(), is("identity-types-second"));
+ assertThat(l.valueNs().moduleNs().toString(), is("identity:list:second:ns:test:json:ser"));
+ }
+
+ public static SchemaContext compileYangFile() throws FileNotFoundException {
+ String path = PropertiesSerializerTest.class.getResource("/yang").getPath();
+ File dir = new File(path);
+ String[] fileList = dir.list();
+ List<File> yangFiles = new ArrayList<File>();
+ if (fileList == null) {
+ throw new FileNotFoundException("/yang");
+ }
+ for (int i = 0; i < fileList.length; i++) {
+ final String fileName = fileList[i];
+ if (new File(dir, fileName).isDirectory() == false) {
+ yangFiles.add(new File(dir, fileName));
+ }
+ }
+ return YangParserTestUtils.parseYangFiles(yangFiles);
+ }
+} \ No newline at end of file
diff --git a/plugins/restconf-client/provider/src/test/resources/yang/execution-service.yang b/plugins/restconf-client/provider/src/test/resources/yang/execution-service.yang
new file mode 100644
index 000000000..d7cf68f12
--- /dev/null
+++ b/plugins/restconf-client/provider/src/test/resources/yang/execution-service.yang
@@ -0,0 +1,43 @@
+module execution-service {
+ yang-version 1.1;
+ namespace "cds:workflow:rest";
+ prefix "cds";
+
+ revision "2019-05-21";
+
+ container process {
+ container commonHeader {
+ leaf originatorId {
+ type string;
+ }
+ leaf requestId {
+ type string;
+ }
+ leaf subRequestId {
+ type string;
+ }
+ }
+ container actionIdentifiers {
+ leaf blueprintName {
+ type string;
+ }
+ leaf blueprintVersion {
+ type string;
+ }
+ leaf actionName {
+ type string;
+ }
+ leaf mode {
+ type string;
+ }
+ }
+ container payload {
+ leaf-list template-prefix {
+ type string;
+ }
+ container resource-assignment-request {
+ anyxml resource-assignment-properties;
+ }
+ }
+ }
+}
diff --git a/plugins/restconf-client/provider/src/test/resources/yang/identity-test.yang b/plugins/restconf-client/provider/src/test/resources/yang/identity-test.yang
new file mode 100644
index 000000000..12ef717f6
--- /dev/null
+++ b/plugins/restconf-client/provider/src/test/resources/yang/identity-test.yang
@@ -0,0 +1,77 @@
+module identity-test {
+ yang-version 1.1;
+ namespace "identity:ns:test:json:ser";
+ prefix "id";
+
+ import identity-types {
+ prefix "type";
+ }
+
+ import identity-types-second {
+ prefix "sec";
+ }
+
+ revision "2013-07-15";
+
+ identity optical {
+ base type:int-type;
+ }
+
+ identity Giga {
+ base type:physical;
+ }
+
+ typedef available {
+ type identityref {
+ base "type:physical";
+ }
+ }
+
+ typedef typed{
+ type union {
+ type int32;
+ type int8;
+ type identityref {
+ base type:int-type;
+ }
+ }
+ }
+
+ container test {
+ leaf l {
+ type string;
+ }
+ container con1 {
+ leaf interface {
+ type identityref {
+ base "type:int-type";
+ }
+ }
+ container interfaces {
+ list int-list {
+ key "iden";
+ leaf iden {
+ type "id:typed";
+ }
+ container available {
+ leaf-list ll {
+ type available;
+ }
+ leaf leaf1 {
+ type leafref {
+ path "../../iden";
+ }
+ }
+
+ leaf leaf2 {
+ type identityref {
+ base type:int-type;
+ base sec:iden1;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/plugins/restconf-client/provider/src/test/resources/yang/identity-types-second.yang b/plugins/restconf-client/provider/src/test/resources/yang/identity-types-second.yang
new file mode 100644
index 000000000..98d6a6e60
--- /dev/null
+++ b/plugins/restconf-client/provider/src/test/resources/yang/identity-types-second.yang
@@ -0,0 +1,25 @@
+module identity-types-second {
+ yang-version 1;
+ namespace "identity:list:second:ns:test:json:ser";
+ prefix "sec";
+
+ import identity-types {
+ prefix "type";
+ }
+
+ revision "2013-07-15";
+
+ identity virtual {
+ base type:int-type;
+ }
+
+ identity Ethernet {
+ base type:physical;
+ }
+
+ identity iden1;
+
+ identity iden2 {
+ base iden1;
+ }
+}
diff --git a/plugins/restconf-client/provider/src/test/resources/yang/identity-types.yang b/plugins/restconf-client/provider/src/test/resources/yang/identity-types.yang
new file mode 100644
index 000000000..25c8fa54f
--- /dev/null
+++ b/plugins/restconf-client/provider/src/test/resources/yang/identity-types.yang
@@ -0,0 +1,17 @@
+module identity-types {
+ yang-version 1;
+ namespace "identity:list:ns:test:json:ser";
+ prefix "type";
+ revision "2013-07-15";
+
+ identity int-type {
+ }
+
+ identity physical {
+ base int-type;
+ }
+
+ identity Loopback {
+ base physical;
+ }
+}
diff --git a/plugins/restconf-client/provider/src/test/resources/yang/test-augment.yang b/plugins/restconf-client/provider/src/test/resources/yang/test-augment.yang
new file mode 100644
index 000000000..795000d39
--- /dev/null
+++ b/plugins/restconf-client/provider/src/test/resources/yang/test-augment.yang
@@ -0,0 +1,106 @@
+module test-augment {
+ yang-version 1;
+ namespace "urn:opendaylight:params:xml:ns:yang:augment";
+ prefix "hello";
+
+ import test-yang {
+ prefix t;
+ }
+
+ revision "2015-01-05" {
+ description "Initial revision of hello model";
+ }
+
+ augment "/t:cont1/t:cont2/t:cont4" {
+ container cont5 {
+ leaf leaf13 {
+ type empty;
+ }
+ }
+ list list7 {
+ leaf leaf14 {
+ type instance-identifier;
+ }
+ }
+ leaf leaf15 {
+ type string;
+ }
+ leaf-list ll6 {
+ type union {
+ type int32;
+ type enumeration {
+ enum "unbounded";
+ }
+ }
+ }
+ uses "t:g1";
+ }
+
+ uses "t:g1";
+ augment "/t:ch1/t:c1/t:cont8/t:cont6" {
+ choice ch2 {
+ case c3 {
+ leaf leaf21 {
+ type string;
+ }
+ }
+ case c4 {
+ leaf leaf22 {
+ type enumeration {
+ enum zero;
+ enum one;
+ enum seven {
+ value 7;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ augment "/t:ch1" {
+ case c5 {
+ container cont10 {
+ leaf leaf23 {
+ type string;
+ }
+ }
+ }
+ }
+
+ augment "/t:ch1/t:c1" {
+ container cont7 {
+ leaf leaf24 {
+ type string;
+ }
+ }
+ }
+
+ augment "/t:cont13/t:cont12" {
+ leaf leaf29 {
+ type string;
+ }
+ }
+
+ augment "/t:create-sfc/t:input" {
+ leaf leaf36 {
+ type bits {
+ bit angle {
+ position 0;
+ }
+ bit degree {
+ position 1;
+ }
+ bit movement {
+ position 2;
+ }
+ }
+ }
+ }
+
+ augment "/t:create-sfc/t:output" {
+ leaf leaf37 {
+ type boolean;
+ }
+ }
+} \ No newline at end of file
diff --git a/plugins/restconf-client/provider/src/test/resources/yang/test-yang.yang b/plugins/restconf-client/provider/src/test/resources/yang/test-yang.yang
new file mode 100644
index 000000000..b2bf06003
--- /dev/null
+++ b/plugins/restconf-client/provider/src/test/resources/yang/test-yang.yang
@@ -0,0 +1,231 @@
+module test-yang {
+ yang-version 1;
+ namespace "urn:opendaylight:params:xml:ns:yang:test";
+ prefix "hello";
+
+ revision "2015-01-05" {
+ description "Initial revision of hello model";
+ }
+
+ container cont1 {
+ container cont2 {
+ container cont3 {
+ leaf leaf10 {
+ type string;
+ }
+ }
+ list list1 {
+ key "leaf1 leaf2";
+ leaf leaf1 {
+ type empty;
+ }
+ leaf leaf2 {
+ type string;
+ }
+ leaf leaf3 {
+ type string;
+ }
+ leaf-list ll1 {
+ type string;
+ }
+ leaf-list ll2 {
+ type string;
+ }
+ container cont4 {
+ leaf leaf11 {
+ type string;
+ }
+ }
+ list list4 {
+ leaf leaf8 {
+ type string;
+ }
+ }
+ list list5 {
+ leaf leaf9 {
+ type string;
+ }
+ }
+ }
+ list list2 {
+ leaf leaf4 {
+ type string;
+ }
+ }
+ leaf leaf5 {
+ type string;
+ }
+ leaf leaf6 {
+ type string;
+ }
+ leaf-list ll3 {
+ type string;
+ }
+ leaf-list ll4 {
+ type string;
+ }
+ }
+ }
+
+ augment "/cont1/cont2" {
+ container cont4 {
+ leaf leaf10 {
+ type string;
+ }
+ }
+ list list6 {
+ leaf leaf11 {
+ type string;
+ }
+ }
+ leaf leaf12 {
+ type string;
+ }
+ leaf-list ll5 {
+ type string;
+ }
+ }
+
+ choice ch1 {
+ case c1 {
+ container cont8 {
+ container cont6 {
+ leaf leaf16 {
+ type string;
+ }
+ }
+ list list8 {
+ leaf leaf18 {
+ type string;
+ }
+ }
+ leaf leaf19 {
+ type string;
+ }
+ leaf-list ll7 {
+ type string;
+ }
+ }
+ }
+ case c2 {
+ container cont9 {
+ leaf leaf20 {
+ type string;
+ }
+ leaf-list ll8 {
+ type string;
+ }
+ container cont11 {
+ choice ch3 {
+ case c1 {
+ leaf leaf25 {
+ type string;
+ }
+ uses g1;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ grouping g1 {
+ container cont13 {
+ container cont12 {
+ leaf leaf26 {
+ type string;
+ }
+ }
+ list list9 {
+ leaf leaf27 {
+ type string;
+ }
+ }
+ leaf leaf28 {
+ type string;
+ }
+ leaf-list ll9 {
+ type string;
+ }
+ }
+ }
+
+ uses g1;
+
+ rpc create-sfc {
+ input {
+ container cont14 {
+ leaf leaf28 {
+ type string;
+ }
+ }
+ list list10 {
+ leaf leaf29 {
+ type string;
+ }
+ }
+ leaf leaf30 {
+ type string;
+ }
+ leaf-list ll10 {
+ type string;
+ }
+ choice ch3 {
+ case c1 {
+ container cont15 {
+ leaf leaf31 {
+ type string;
+ }
+ }
+ }
+ }
+ uses g1;
+ }
+ output {
+ container cont16 {
+ leaf leaf32 {
+ type string;
+ }
+ }
+ list list11 {
+ leaf leaf33 {
+ type string;
+ }
+ }
+ leaf leaf34 {
+ type string;
+ }
+ leaf-list ll11 {
+ type string;
+ }
+ choice ch4 {
+ case c1 {
+ container cont17 {
+ leaf leaf35 {
+ type string;
+ }
+ }
+ }
+ }
+ uses g1;
+ }
+ }
+
+ container cont18 {
+ container cont18 {
+ list list12 {
+ list list12 {
+ leaf leaf36 {
+ type string;
+ }
+ }
+ leaf leaf36 {
+ type string;
+ }
+ }
+ }
+ leaf leaf40 {
+ type string;
+ }
+ }
+} \ No newline at end of file
diff --git a/plugins/restconf-client/provider/src/test/resources/yang/test_augment_1_for_module.yang b/plugins/restconf-client/provider/src/test/resources/yang/test_augment_1_for_module.yang
new file mode 100644
index 000000000..d2eeea7d1
--- /dev/null
+++ b/plugins/restconf-client/provider/src/test/resources/yang/test_augment_1_for_module.yang
@@ -0,0 +1,108 @@
+module test_augment_1_for_module {
+ yang-version 1;
+ namespace "urn:opendaylight:params:xml:ns:yang:test:augment:name";
+ prefix "augment-name";
+
+ import test_name_of_the_module {
+ prefix aug;
+ }
+
+ revision "2015-01-05" {
+ description "Initial revision of hello model";
+ }
+
+ augment "/aug:name_of_the_cont1/aug:name_of_the_cont2/aug:name_of_the_cont4" {
+ container name_of_the_cont5 {
+ leaf name_of_the_leaf13 {
+ type empty;
+ }
+ }
+ list name_of_the_list7 {
+ leaf name_of_the_leaf14 {
+ type instance-identifier;
+ }
+ }
+ leaf name_of_the_leaf15 {
+ type string;
+ }
+ leaf-list name_of_the_ll6 {
+ type union {
+ type int32;
+ type enumeration {
+ enum "unbounded";
+ }
+ }
+ }
+ uses "aug:name_of_the_g1";
+ }
+
+ uses "aug:name_of_the_g1";
+
+ augment "/aug:name_of_the_cont1/aug:name_of_the_cont2/aug:name_of_the_cont3" {
+ choice name_of_the_ch2 {
+ case name_of_the_c3 {
+ leaf name_of_the_leaf21 {
+ type string;
+ }
+ }
+ case name_of_the_c4 {
+ leaf name_of_the_leaf22 {
+ type enumeration {
+ enum zero;
+ enum one;
+ enum seven {
+ value 7;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ augment "/aug:name_of_the_ch1" {
+ case name_of_the_c5 {
+ container name_of_the_cont10 {
+ leaf name_of_the_leaf23 {
+ type string;
+ }
+ }
+ }
+ }
+
+ augment "/aug:name_of_the_ch1/aug:name_of_the_c1" {
+ container name_of_the_cont7 {
+ leaf name_of_the_leaf24 {
+ type string;
+ }
+ }
+ }
+
+ augment "/aug:name_of_the_cont13/aug:name_of_the_cont12" {
+ leaf name_of_the_leaf29 {
+ type string;
+ }
+ }
+
+ augment "/aug:name_of_the_create-sfc/aug:input" {
+ leaf name_of_the_leaf36 {
+ type bits {
+ bit angle {
+ position 0;
+ }
+ bit degree {
+ position 1;
+ }
+ bit movement {
+ position 2;
+ }
+ }
+ }
+ }
+
+ augment "/aug:name_of_the_create-sfc/aug:output" {
+ leaf leaf37 {
+ type boolean;
+ }
+ }
+
+} \ No newline at end of file
diff --git a/plugins/restconf-client/provider/src/test/resources/yang/test_name_of_the_module.yang b/plugins/restconf-client/provider/src/test/resources/yang/test_name_of_the_module.yang
new file mode 100644
index 000000000..973475ee7
--- /dev/null
+++ b/plugins/restconf-client/provider/src/test/resources/yang/test_name_of_the_module.yang
@@ -0,0 +1,231 @@
+module test_name_of_the_module {
+ yang-version 1;
+ namespace "urn:opendaylight:params:xml:ns:yang:test:name";
+ prefix "name";
+
+ revision "2015-01-05" {
+ description "Initial revision of hello model";
+ }
+
+ container name_of_the_cont1 {
+ container name_of_the_cont2 {
+ container name_of_the_cont3 {
+ leaf name_of_the_leaf10 {
+ type string;
+ }
+ }
+ list name_of_the_list1 {
+ key "name_of_the_leaf1 name_of_the_leaf2";
+ leaf name_of_the_leaf1 {
+ type empty;
+ }
+ leaf name_of_the_leaf2 {
+ type string;
+ }
+ leaf name_of_the_leaf3 {
+ type string;
+ }
+ leaf-list name_of_the_ll1 {
+ type string;
+ }
+ leaf-list name_of_the_ll2 {
+ type string;
+ }
+ container name_of_the_cont4 {
+ leaf name_of_the_leaf11 {
+ type string;
+ }
+ }
+ list name_of_the_list4 {
+ leaf name_of_the_leaf8 {
+ type string;
+ }
+ }
+ list name_of_the_list5 {
+ leaf name_of_the_leaf9 {
+ type string;
+ }
+ }
+ }
+ list name_of_the_list2 {
+ leaf name_of_the_leaf4 {
+ type string;
+ }
+ }
+ leaf name_of_the_leaf5 {
+ type string;
+ }
+ leaf name_of_the_leaf6 {
+ type string;
+ }
+ leaf-list name_of_the_ll3 {
+ type string;
+ }
+ leaf-list name_of_the_ll4 {
+ type string;
+ }
+ }
+ }
+
+ augment "/name_of_the_cont1/name_of_the_cont2" {
+ container name_of_the_cont4 {
+ leaf name_of_the_leaf10 {
+ type string;
+ }
+ }
+ list name_of_the_list6 {
+ leaf name_of_the_leaf11 {
+ type string;
+ }
+ }
+ leaf name_of_the_leaf12 {
+ type string;
+ }
+ leaf-list name_of_the_ll5 {
+ type string;
+ }
+ }
+
+ choice name_of_the_ch1 {
+ case name_of_the_c1 {
+ container name_of_the_cont8 {
+ container name_of_the_cont6 {
+ leaf name_of_the_leaf16 {
+ type string;
+ }
+ }
+ list name_of_the_list8 {
+ leaf name_of_the_leaf18 {
+ type string;
+ }
+ }
+ leaf name_of_the_leaf19 {
+ type string;
+ }
+ leaf-list name_of_the_ll7 {
+ type string;
+ }
+ }
+ }
+ case name_of_the_c2 {
+ container name_of_the_cont9 {
+ leaf name_of_the_leaf20 {
+ type string;
+ }
+ leaf-list name_of_the_ll8 {
+ type string;
+ }
+ container name_of_the_cont11 {
+ choice name_of_the_ch3 {
+ case name_of_the_c1 {
+ leaf name_of_the_leaf25 {
+ type string;
+ }
+ uses name_of_the_g1;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ grouping name_of_the_g1 {
+ container name_of_the_cont13 {
+ container name_of_the_cont12 {
+ leaf name_of_the_leaf26 {
+ type string;
+ }
+ }
+ list name_of_the_list9 {
+ leaf name_of_the_leaf27 {
+ type string;
+ }
+ }
+ leaf name_of_the_leaf28 {
+ type string;
+ }
+ leaf-list name_of_the_ll9 {
+ type string;
+ }
+ }
+ }
+
+ uses name_of_the_g1;
+
+ rpc name_of_the_create-sfc {
+ input {
+ container name_of_the_cont14 {
+ leaf name_of_the_leaf28 {
+ type string;
+ }
+ }
+ list name_of_the_list10 {
+ leaf name_of_the_leaf29 {
+ type string;
+ }
+ }
+ leaf name_of_the_leaf30 {
+ type string;
+ }
+ leaf-list name_of_the_ll10 {
+ type string;
+ }
+ choice name_of_the_ch3 {
+ case name_of_the_c1 {
+ container name_of_the_cont15 {
+ leaf name_of_the_leaf31 {
+ type string;
+ }
+ }
+ }
+ }
+ uses name_of_the_g1;
+ }
+ output {
+ container name_of_the_cont16 {
+ leaf name_of_the_leaf32 {
+ type string;
+ }
+ }
+ list name_of_the_list11 {
+ leaf name_of_the_leaf33 {
+ type string;
+ }
+ }
+ leaf name_of_the_leaf34 {
+ type string;
+ }
+ leaf-list name_of_the_ll11 {
+ type string;
+ }
+ choice name_of_the_ch4 {
+ case name_of_the_c1 {
+ container name_of_the_cont17 {
+ leaf name_of_the_leaf35 {
+ type string;
+ }
+ }
+ }
+ }
+ uses name_of_the_g1;
+ }
+ }
+
+ container name_of_the_cont18 {
+ container name_of_the_cont18 {
+ list name_of_the_list12 {
+ list name_of_the_list12 {
+ leaf name_of_the_leaf36 {
+ type string;
+ }
+ }
+ leaf name_of_the_leaf36 {
+ type string;
+ }
+ }
+ }
+ leaf name_of_the_leaf40 {
+ type string;
+ }
+ }
+} \ No newline at end of file
diff --git a/plugins/sshapi-call-node/.gitignore b/plugins/sshapi-call-node/.gitignore
new file mode 100755
index 000000000..3c30c3505
--- /dev/null
+++ b/plugins/sshapi-call-node/.gitignore
@@ -0,0 +1,35 @@
+#####standard .git ignore entries#####
+
+## IDE Specific Files ##
+org.eclipse.core.resources.prefs
+.classpath
+.project
+.settings
+.idea
+.externalToolBuilders
+maven-eclipse.xml
+workspace
+
+## Compilation Files ##
+*.class
+**/target
+target
+target-ide
+MANIFEST.MF
+
+## Misc Ignores (OS specific etc) ##
+bin/
+dist
+*~
+*.ipr
+*.iml
+*.iws
+classes
+out/
+.DS_STORE
+.metadata
+*.log
+
+## Folders which contain auto generated source code ##
+yang-gen-config
+yang-gen-sal
diff --git a/plugins/sshapi-call-node/installer/pom.xml b/plugins/sshapi-call-node/installer/pom.xml
new file mode 100755
index 000000000..de7509dbc
--- /dev/null
+++ b/plugins/sshapi-call-node/installer/pom.xml
@@ -0,0 +1,126 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>odlparent-lite</artifactId>
+ <version>2.1.0</version>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.plugins</groupId>
+ <artifactId>sshapi-call-node-installer</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>pom</packaging>
+
+ <name>ccsdk-sli-plugins :: sshapi-call-node :: ${project.artifactId}</name>
+
+ <properties>
+ <application.name>ccsdk-sshapi-call-node</application.name>
+ <features.boot>${application.name}</features.boot>
+ <features.repositories>mvn:org.onap.ccsdk.sli.plugins/${features.boot}/${project.version}/xml/features</features.repositories>
+ <include.transitive.dependencies>false</include.transitive.dependencies>
+ </properties>
+
+ <dependencies>
+
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.plugins</groupId>
+ <artifactId>sshapi-call-node-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <version>2.6</version>
+ <executions>
+ <execution>
+ <id>maven-repo-zip</id>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ <phase>package</phase>
+ <configuration>
+ <attach>true</attach>
+ <finalName>stage/${application.name}-${project.version}</finalName>
+ <descriptors>
+ <descriptor>src/assembly/assemble_mvnrepo_zip.xml</descriptor>
+ </descriptors>
+ <appendAssemblyId>true</appendAssemblyId>
+ </configuration>
+ </execution>
+ <execution>
+ <id>installer-zip</id>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ <phase>package</phase>
+ <configuration>
+ <attach>true</attach>
+ <finalName>${application.name}-${project.version}-installer</finalName>
+ <descriptors>
+ <descriptor>src/assembly/assemble_installer_zip.xml</descriptor>
+ </descriptors>
+ <appendAssemblyId>false</appendAssemblyId>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>copy-dependencies</id>
+ <goals>
+ <goal>copy-dependencies</goal>
+ </goals>
+ <phase>prepare-package</phase>
+ <configuration>
+ <transitive>false</transitive>
+ <outputDirectory>${project.build.directory}/assembly/system</outputDirectory>
+ <overWriteReleases>false</overWriteReleases>
+ <overWriteSnapshots>true</overWriteSnapshots>
+ <overWriteIfNewer>true</overWriteIfNewer>
+ <useRepositoryLayout>true</useRepositoryLayout>
+ <addParentPoms>false</addParentPoms>
+ <copyPom>false</copyPom>
+ <includeGroupIds>org.onap.ccsdk.sli.plugins</includeGroupIds>
+ <scope>provided</scope>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <artifactId>maven-resources-plugin</artifactId>
+ <version>2.6</version>
+ <executions>
+ <execution>
+ <id>copy-version</id>
+ <goals>
+ <goal>copy-resources</goal>
+ </goals><!-- here the phase you need -->
+ <phase>validate</phase>
+ <configuration>
+ <outputDirectory>${basedir}/target/stage</outputDirectory>
+ <resources>
+ <resource>
+ <directory>src/main/resources/scripts</directory>
+ <includes>
+ <include>install-feature.sh</include>
+ </includes>
+ <filtering>true</filtering>
+ </resource>
+ </resources>
+ </configuration>
+ </execution>
+
+ </executions>
+ </plugin>
+
+ </plugins>
+ </build>
+</project>
diff --git a/plugins/sshapi-call-node/installer/src/assembly/assemble_installer_zip.xml b/plugins/sshapi-call-node/installer/src/assembly/assemble_installer_zip.xml
new file mode 100644
index 000000000..b2e792123
--- /dev/null
+++ b/plugins/sshapi-call-node/installer/src/assembly/assemble_installer_zip.xml
@@ -0,0 +1,59 @@
+<!--
+ ============LICENSE_START=======================================================
+ openECOMP : SDN-C
+ ================================================================================
+ Copyright (C) 2018 Samsung Electronics. All rights
+ reserved.
+ ================================================================================
+ 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.
+ ============LICENSE_END=========================================================
+ -->
+
+<!-- Defines how we build the .zip file which is our distribution. -->
+
+<assembly
+ xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
+ <id>installer_zip</id>
+ <formats>
+ <format>zip</format>
+ </formats>
+
+ <!-- we want "system" and related files right at the root level
+ as this file is suppose to be unzip on top of a karaf
+ distro. -->
+ <includeBaseDirectory>false</includeBaseDirectory>
+
+ <fileSets>
+ <fileSet>
+ <directory>target/stage/</directory>
+ <outputDirectory>${application.name}</outputDirectory>
+ <fileMode>755</fileMode>
+ <includes>
+ <include>*.sh</include>
+ </includes>
+ </fileSet>
+ <fileSet>
+ <directory>target/stage/</directory>
+ <outputDirectory>${application.name}</outputDirectory>
+ <fileMode>644</fileMode>
+ <excludes>
+ <exclude>*.sh</exclude>
+ </excludes>
+ </fileSet>
+ </fileSets>
+
+
+
+</assembly>
diff --git a/plugins/sshapi-call-node/installer/src/assembly/assemble_mvnrepo_zip.xml b/plugins/sshapi-call-node/installer/src/assembly/assemble_mvnrepo_zip.xml
new file mode 100644
index 000000000..2a6344697
--- /dev/null
+++ b/plugins/sshapi-call-node/installer/src/assembly/assemble_mvnrepo_zip.xml
@@ -0,0 +1,49 @@
+<!--
+ ============LICENSE_START=======================================================
+ openECOMP : SDN-C
+ ================================================================================
+ Copyright (C) 2018 Samsung Electronics. All rights
+ reserved.
+ ================================================================================
+ 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.
+ ============LICENSE_END=========================================================
+ -->
+
+<!-- Defines how we build the .zip file which is our distribution. -->
+
+<assembly
+ xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
+ <id>repo</id>
+ <formats>
+ <format>zip</format>
+ </formats>
+
+ <!-- we want "system" and related files right at the root level
+ as this file is suppose to be unzip on top of a karaf
+ distro. -->
+ <includeBaseDirectory>false</includeBaseDirectory>
+
+ <fileSets>
+ <fileSet>
+ <directory>target/assembly/</directory>
+ <outputDirectory>.</outputDirectory>
+ <excludes>
+ </excludes>
+ </fileSet>
+ </fileSets>
+
+
+
+</assembly>
diff --git a/plugins/sshapi-call-node/installer/src/main/resources/scripts/install-feature.sh b/plugins/sshapi-call-node/installer/src/main/resources/scripts/install-feature.sh
new file mode 100644
index 000000000..8e516a247
--- /dev/null
+++ b/plugins/sshapi-call-node/installer/src/main/resources/scripts/install-feature.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+
+###
+# ============LICENSE_START=======================================================
+# openECOMP : SDN-C
+# ================================================================================
+# Copyright (C) 2018 Samsung Electronics. All rights
+# reserved.
+# ================================================================================
+# 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.
+# ============LICENSE_END=========================================================
+###
+
+ODL_HOME=${ODL_HOME:-/opt/opendaylight/current}
+ODL_KARAF_CLIENT=${ODL_KARAF_CLIENT:-${ODL_HOME}/bin/client}
+INSTALLERDIR=$(dirname $0)
+
+REPOZIP=${INSTALLERDIR}/${features.boot}-${project.version}.zip
+
+if [ -f ${REPOZIP} ]
+then
+ unzip -nd ${ODL_HOME} ${REPOZIP}
+else
+ echo "ERROR : repo zip ($REPOZIP) not found"
+ exit 1
+fi
+
+${ODL_KARAF_CLIENT} feature:repo-add ${features.repositories}
+${ODL_KARAF_CLIENT} feature:install ${features.boot}
diff --git a/plugins/sshapi-call-node/pom.xml b/plugins/sshapi-call-node/pom.xml
new file mode 100755
index 000000000..a9dc52e4b
--- /dev/null
+++ b/plugins/sshapi-call-node/pom.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>odlparent-lite</artifactId>
+ <version>2.1.0</version>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.plugins</groupId>
+ <artifactId>sshapi-call-node</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>pom</packaging>
+
+ <name>ccsdk-sli-plugins :: sshapi-call-node</name>
+ <description>This is an implementation of DG Execute Node that makes a call to an external REST API</description>
+
+ <modules>
+ <module>provider</module>
+ <module>installer</module>
+ </modules>
+</project>
diff --git a/plugins/sshapi-call-node/provider/ReadMe.md b/plugins/sshapi-call-node/provider/ReadMe.md
new file mode 100644
index 000000000..beaadcda8
--- /dev/null
+++ b/plugins/sshapi-call-node/provider/ReadMe.md
@@ -0,0 +1,32 @@
+SSHApi-Call-Node Plugin:
+
+Parameters List that managed in from Directed Graphs:
+
+Input:
+Url -> Mandatory -> url to make the SSH connection request to.
+Port -> Mandatory -> port to make the SSH connection request to.
+AuthType -> Optional -> Type of authentiation to be used BASIC or sshKey based -> true or false
+User -> Optional -> user name to use for ssh basic authentication -> sdnc_ws
+Password -> Optional -> unencrypted password to use for ssh basic authentication -> plain_password
+SshKey -> Optional -> Consumer SSH key to use for ssh authentication -> plain_key
+ExecTimeout -> Optional -> SSH command execution timeout -> plain_key
+Retry -> Optional -> Make ssh connection with default retry policy -> plain_key
+Cmd -> Mandatory -> ssh command to be executed on the server. -> get post put delete patch
+EnvParameters -> Optional -> A JSON dictionary which should list key value pairs to be passed to the command execution. These values would correspond to instance specific parameters that a command may need to execute an action.
+FileParameters -> Optional -> A JSON dictionary where keys are filenames and values are contents of files. The SSH Server will utilize this feature to generate files with keys as filenames and values as content. This attribute can be used to generate files that a command may require as part of execution.
+ConvertResponse -> Optional -> whether the response should be converted to properties -> true or false
+ResponseType -> Optional -> If we know the response is to be in a specific format (supported are JSON, XML and NONE)
+ResponsePrefix -> Optional -> location the response will be written to in context memory
+listName[i] -> Optional -> Used for processing XML responses with repeating elements.</td>vpn-information.vrf-details
+
+Output:
+"sshApi.call.node.status" -> SSH Exit status code is set in here.
+"sshApi.call.node.stdout" -> SSH command execution result is put in here.
+"sshApi.call.node.stderr" -> SSH execution failure message is put in here.
+
+
+
+API methods that are exposed:
+1) execCommand
+2) execWithStatusCheck: Throws exception if the exit status is not successful.
+3) execCommandWithPty \ No newline at end of file
diff --git a/plugins/sshapi-call-node/provider/pom.xml b/plugins/sshapi-call-node/provider/pom.xml
new file mode 100755
index 000000000..49bceb122
--- /dev/null
+++ b/plugins/sshapi-call-node/provider/pom.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>binding-parent</artifactId>
+ <version>2.1.0</version>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.plugins</groupId>
+ <artifactId>sshapi-call-node-provider</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>bundle</packaging>
+
+ <name>ccsdk-sli-plugins :: sshapi-call-node :: ${project.artifactId}</name>
+
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sli-core-artifacts</artifactId>
+ <version>${ccsdk.sli.core.version}</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sli-common</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <!-- ILLEGAL DEPENDENCY : creates circular dependency between CCSDK and APPC -->
+ <dependency>
+ <groupId>org.onap.appc</groupId>
+ <artifactId>appc-ssh-adapter-api</artifactId>
+ <version>1.3.0</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.json</groupId>
+ <artifactId>json</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.codehaus.jettison</groupId>
+ <artifactId>jettison</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.att.eelf</groupId>
+ <artifactId>eelf-core</artifactId>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/plugins/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/SshApiCallNode.java b/plugins/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/SshApiCallNode.java
new file mode 100644
index 000000000..146188fb9
--- /dev/null
+++ b/plugins/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/SshApiCallNode.java
@@ -0,0 +1,283 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * ONAP : APPC
+ * ================================================================================
+ * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * =============================================================================
+ * Copyright (C) 2018 Samsung Electronics. All rights
+ reserved.
+ * ================================================================================
+ * Modifications Copyright © 2018 IBM
+ * ================================================================================
+ * 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.
+ *
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.sshapicall;
+
+import java.io.ByteArrayOutputStream;
+import java.util.Map;
+
+import org.onap.appc.adapter.ssh.SshAdapter;
+import org.onap.appc.adapter.ssh.SshConnection;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import com.att.eelf.configuration.EELFLogger;
+import com.att.eelf.configuration.EELFManager;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicJavaPlugin;
+import org.onap.ccsdk.sli.plugins.sshapicall.model.AuthType;
+import org.onap.ccsdk.sli.plugins.sshapicall.model.Parameters;
+import org.onap.ccsdk.sli.plugins.sshapicall.model.ParseParam;
+
+
+public class SshApiCallNode implements SvcLogicJavaPlugin {
+
+ private static final EELFLogger logger = EELFManager.getInstance().getApplicationLogger();
+
+ /**
+ * Output parameter - SSH command execution status.
+ */
+ private String PARAM_OUT_status = "sshApi.call.node.status";
+
+ /**
+ * Output parameter - content of SSH command stdout.
+ */
+ private String PARAM_OUT_stdout = "sshApi.call.node.stdout";
+
+ /**
+ * Output parameter - content of SSH command stderr.
+ */
+ private String PARAM_OUT_stderr = "sshApi.call.node.stderr";
+
+ /**
+ * Testing parameter - content of mocked SSH.
+ */
+ private boolean PARAM_TEST_MODE = false;
+ private String PARAM_OUT_MESSAGE = "TestOut";
+
+
+ /**
+ * Default success status.
+ */
+ private int DEF_SUCCESS_STATUS = 0;
+
+
+
+ private SshAdapter sshAdapter;
+
+ /**
+ * Used for jUnit test and testing interface
+ */
+ public SshApiCallNode(boolean mode) {
+ PARAM_TEST_MODE = mode;
+ }
+
+ public SshApiCallNode() {
+ PARAM_TEST_MODE = false;
+ }
+
+ public void setSshAdapter(SshAdapter sshAdapter) {
+ this.sshAdapter = sshAdapter;
+ }
+
+ /**
+ * Allows Directed Graphs the ability to interact with SSH APIs.
+ * @param params HashMap<String,String> of parameters passed by the DG to this function
+ * <table border="1">
+ * <thead><th>parameter</th><th>Mandatory/Optional</th><th>description</th><th>example values</th></thead>
+ * <tbody>
+ * <tr><td>Url</td><td>Mandatory</td><td>url to make the SSH connection request to.</td></tr>
+ * <tr><td>Port</td><td>Mandatory</td><td>port to make the SSH connection request to.</td></tr>
+ * <tr><td>User</td><td>Optional</td><td>user name to use for ssh basic authentication</td><td>sdnc_ws</td></tr>
+ * <tr><td>Password</td><td>Optional</td><td>unencrypted password to use for ssh basic authentication</td><td>plain_password</td></tr>
+ * <tr><td>SshKey</td><td>Optional</td><td>Consumer SSH key to use for ssh authentication</td><td>plain_key</td></tr>
+ * <tr><td>ExecTimeout</td><td>Optional</td><td>SSH command execution timeout</td><td>plain_key</td></tr>
+ * <tr><td>Retry</td><td>Optional</td><td>Make ssh connection with default retry policy</td><td>plain_key</td></tr>
+ * <tr><td>Cmd</td><td>Mandatory</td><td>ssh command to be executed on the server.</td><td>get post put delete patch</td></tr>
+ * <tr><td>ResponsePrefix</td><td>Optional</td><td>location the response will be written to in context memory</td></tr>
+ * <tr><td>ResponseType</td><td>Optional</td><td>If we know the response is to be in a specific format (supported are JSON, XML and NONE) </td></tr>
+ * <tr><td>listName[i]</td><td>Optional</td><td>Used for processing XML responses with repeating elements.</td>vpn-information.vrf-details<td></td></tr>
+ * <tr><td>ConvertResponse </td><td>Optional</td><td>whether the response should be converted</td><td>true or false</td></tr>
+ * <tr><td>AuthType</td><td>Optional</td><td>Type of authentiation to be used BASIC or sshKey based</td><td>true or false</td></tr>
+ * <tr><td>EnvParameters</td><td>Optional</td><td>A JSON dictionary which should list key value pairs to be passed to the command execution.
+ * These values would correspond to instance specific parameters that a command may need to execute an action.</td></tr>
+ * <tr><td>FileParameters</td><td>Optional</td><td>A JSON dictionary where keys are filenames and values are contents of files.
+ * The SSH Server will utilize this feature to generate files with keys as filenames and values as content.
+ * This attribute can be used to generate files that a command may require as part of execution.</td></tr>
+ * </tbody>
+ * </table>
+ * Exec remote command over SSH. Return command execution status.
+ * Command output is written to out or err stream.
+ *
+ * @param ctx Reference to context memory
+ */
+
+ public void execCommand(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException {
+ execSshCommand(params, ctx, false);
+ }
+
+ private void execSshCommand(Map<String, String> params, SvcLogicContext ctx, boolean withPty) throws SvcLogicException {
+ ParseParam parser = new ParseParam();
+ Parameters p = parser.getParameters(params);
+ logger.debug("=> Connecting to SSH server...");
+ SshConnection sshConnection = null;
+ int status = -1;
+ ByteArrayOutputStream stdout = new ByteArrayOutputStream();
+ ByteArrayOutputStream stderr = new ByteArrayOutputStream();
+ String stdoutRes = "";
+ String stderrRes = "";
+ try {
+ if (!PARAM_TEST_MODE) {
+ sshConnection = getSshConnection(p);
+ sshConnection.connect();
+ logger.debug("=> Connected to SSH server...");
+ logger.debug("=> Running SSH command...");
+ sshConnection.setExecTimeout(p.sshExecTimeout);
+ if (withPty) {
+ status = sshConnection.execCommandWithPty(parser.makeCommand(params), stdout);
+ stderr = stdout;
+ }
+ else
+ status = sshConnection.execCommand(parser.makeCommand(params), stdout, stderr);
+ stdoutRes = stdout.toString();
+ stderrRes = stderr.toString();
+
+ } else {
+ if (("true").equalsIgnoreCase(params.get("TestFail")))
+ status = 202;
+ else
+ status = DEF_SUCCESS_STATUS;
+ stdoutRes = params.get(PARAM_OUT_MESSAGE);
+ }
+ logger.debug("=> executed SSH command");
+
+ if(status == DEF_SUCCESS_STATUS) {
+ parser.parseOutput(ctx, stdoutRes);
+ }
+ ctx.setAttribute(PARAM_OUT_status, String.format("%01d", status));
+ ctx.setAttribute(PARAM_OUT_stdout, stdoutRes);
+ ctx.setAttribute(PARAM_OUT_stderr, stderrRes);
+ } catch (Exception e){
+ throw new SvcLogicException("Exception in SSH adaptor : " + e.getMessage());
+ } finally {
+ if (sshConnection != null)
+ sshConnection.disconnect();
+ }
+ }
+
+ private SshConnection getSshConnection(Parameters p) throws SvcLogicException {
+ if (p.authtype == AuthType.BASIC)
+ return sshAdapter.getConnection(p.sshapiUrl, p.sshapiPort, p.sshapiUser, p.sshapiPassword);
+ // This is not supported yet in the API, patch has already been added to APPC
+ else if (p.authtype == AuthType.KEY){
+ throw new SvcLogicException("SSH Key based Auth method not supported");
+ }
+ else if (p.authtype == AuthType.NONE){
+ throw new SvcLogicException("SSH Auth type required, BASIC auth in support");
+ }
+ else if (p.authtype == AuthType.UNSPECIFIED){
+ if (p.sshapiUser != null && p.sshapiPassword != null)
+ return sshAdapter.getConnection(p.sshapiUrl, p.sshapiPort, p.sshapiUser, p.sshapiPassword);
+ else if (p.sshKey != null)
+ throw new SvcLogicException("SSH Key based Auth method not supported");
+ }
+ throw new SvcLogicException("SSH Auth type required, BASIC auth in support");
+ }
+
+
+ /**
+ * Allows Directed Graphs the ability to interact with SSH APIs.
+ * @param params HashMap<String,String> of parameters passed by the DG to this function
+ * <table border="1">
+ * <thead><th>parameter</th><th>Mandatory/Optional</th><th>description</th><th>example values</th></thead>
+ * <tbody>
+ * <tr><td>Url</td><td>Mandatory</td><td>url to make the SSH connection request to.</td></tr>
+ * <tr><td>Port</td><td>Mandatory</td><td>port to make the SSH connection request to.</td></tr>
+ * <tr><td>User</td><td>Optional</td><td>user name to use for ssh basic authentication</td><td>sdnc_ws</td></tr>
+ * <tr><td>Password</td><td>Optional</td><td>unencrypted password to use for ssh basic authentication</td><td>plain_password</td></tr>
+ * <tr><td>SshKey</td><td>Optional</td><td>Consumer SSH key to use for ssh authentication</td><td>plain_key</td></tr>
+ * <tr><td>ExecTimeout</td><td>Optional</td><td>SSH command execution timeout</td><td>plain_key</td></tr>
+ * <tr><td>Retry</td><td>Optional</td><td>Make ssh connection with default retry policy</td><td>plain_key</td></tr>
+ * <tr><td>Cmd</td><td>Mandatory</td><td>ssh command to be executed on the server.</td><td>get post put delete patch</td></tr>
+ * <tr><td>ResponsePrefix</td><td>Optional</td><td>location the response will be written to in context memory</td></tr>
+ * <tr><td>ResponseType</td><td>Optional</td><td>If we know the response is to be in a specific format (supported are JSON, XML and NONE) </td></tr>
+ * <tr><td>listName[i]</td><td>Optional</td><td>Used for processing XML responses with repeating elements.</td>vpn-information.vrf-details<td></td></tr>
+ * <tr><td>ConvertResponse </td><td>Optional</td><td>whether the response should be converted</td><td>true or false</td></tr>
+ * <tr><td>AuthType</td><td>Optional</td><td>Type of authentiation to be used BASIC or sshKey based</td><td>true or false</td></tr>
+ * <tr><td>EnvParameters</td><td>Optional</td><td>A JSON dictionary which should list key value pairs to be passed to the command execution.
+ * These values would correspond to instance specific parameters that a command may need to execute an action.</td></tr>
+ * <tr><td>FileParameters</td><td>Optional</td><td>A JSON dictionary where keys are filenames and values are contents of files.
+ * The SSH Server will utilize this feature to generate files with keys as filenames and values as content.
+ * This attribute can be used to generate files that a command may require as part of execution.</td></tr>
+ * </tbody>
+ * </table>
+ * Exec remote command over SSH. Return command execution status.
+ * Command output is written to out or err stream.
+ *
+ * @param ctx Reference to context memory
+ */
+
+ public void execWithStatusCheck(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException {
+ execCommand(params, ctx);
+ parseResponse(ctx);
+ }
+
+ private void parseResponse (SvcLogicContext ctx) throws SvcLogicException {
+ int status = Integer.parseInt(ctx.getAttribute(PARAM_OUT_status));
+ if(status != DEF_SUCCESS_STATUS) {
+ StringBuilder errmsg = new StringBuilder();
+ errmsg.append("SSH command returned error status [").append(status).append(']');
+ String stderr = ctx.getAttribute(PARAM_OUT_stderr);
+ if((stderr != null) && !stderr.isEmpty()) {
+ errmsg.append(". Error: [").append(stderr).append(']');
+ }
+ throw new SvcLogicException(errmsg.toString());
+ }
+ }
+
+ /**
+ * Allows Directed Graphs the ability to interact with SSH APIs.
+ * @param params HashMap<String,String> of parameters passed by the DG to this function
+ * <table border="1">
+ * <thead><th>parameter</th><th>Mandatory/Optional</th><th>description</th><th>example values</th></thead>
+ * <tbody>
+ * <tr><td>Url</td><td>Mandatory</td><td>url to make the SSH connection request to.</td></tr>
+ * <tr><td>Port</td><td>Mandatory</td><td>port to make the SSH connection request to.</td></tr>
+ * <tr><td>User</td><td>Optional</td><td>user name to use for ssh basic authentication</td><td>sdnc_ws</td></tr>
+ * <tr><td>Password</td><td>Optional</td><td>unencrypted password to use for ssh basic authentication</td><td>plain_password</td></tr>
+ * <tr><td>SshKey</td><td>Optional</td><td>Consumer SSH key to use for ssh authentication</td><td>plain_key</td></tr>
+ * <tr><td>ExecTimeout</td><td>Optional</td><td>SSH command execution timeout</td><td>plain_key</td></tr>
+ * <tr><td>Retry</td><td>Optional</td><td>Make ssh connection with default retry policy</td><td>plain_key</td></tr>
+ * <tr><td>Cmd</td><td>Mandatory</td><td>ssh command to be executed on the server.</td><td>get post put delete patch</td></tr>
+ * <tr><td>ResponsePrefix</td><td>Optional</td><td>location the response will be written to in context memory</td></tr>
+ * <tr><td>ResponseType</td><td>Optional</td><td>If we know the response is to be in a specific format (supported are JSON, XML and NONE) </td></tr>
+ * <tr><td>listName[i]</td><td>Optional</td><td>Used for processing XML responses with repeating elements.</td>vpn-information.vrf-details<td></td></tr>
+ * <tr><td>ConvertResponse </td><td>Optional</td><td>whether the response should be converted</td><td>true or false</td></tr>
+ * <tr><td>AuthType</td><td>Optional</td><td>Type of authentiation to be used BASIC or sshKey based</td><td>true or false</td></tr>
+ * <tr><td>EnvParameters</td><td>Optional</td><td>A JSON dictionary which should list key value pairs to be passed to the command execution.
+ * These values would correspond to instance specific parameters that a command may need to execute an action.</td></tr>
+ * <tr><td>FileParameters</td><td>Optional</td><td>A JSON dictionary where keys are filenames and values are contents of files.
+ * The SSH Server will utilize this feature to generate files with keys as filenames and values as content.
+ * This attribute can be used to generate files that a command may require as part of execution.</td></tr>
+ * </tbody>
+ * </table>
+ * Exec remote command over SSH. Return command execution status.
+ * Command output is written to out or err stream.
+ *
+ * @param ctx Reference to context memory
+ */
+ public void execCommandWithPty(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException {
+ execSshCommand(params, ctx, true);
+ }
+}
diff --git a/plugins/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/AuthType.java b/plugins/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/AuthType.java
new file mode 100644
index 000000000..806c80890
--- /dev/null
+++ b/plugins/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/AuthType.java
@@ -0,0 +1,41 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Copyright (C) 2018 Samsung Electronics. All rights
+ * reserved.
+ * ================================================================================
+ *
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.sshapicall.model;
+
+public enum AuthType {
+ NONE, BASIC, KEY, UNSPECIFIED;
+
+ public static AuthType fromString(String s) {
+ if ("basic".equalsIgnoreCase(s))
+ return BASIC;
+ if ("key".equalsIgnoreCase(s))
+ return KEY;
+ if ("unspecified".equalsIgnoreCase(s))
+ return UNSPECIFIED;
+ if ("none".equalsIgnoreCase(s))
+ return NONE;
+ throw new IllegalArgumentException("Invalid value for format: " + s);
+ }
+}
diff --git a/plugins/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/Format.java b/plugins/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/Format.java
new file mode 100644
index 000000000..43c3c38d6
--- /dev/null
+++ b/plugins/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/Format.java
@@ -0,0 +1,39 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Copyright (C) 2018 Samsung Electronics. All rights
+ * reserved.
+ * ================================================================================
+ *
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.sshapicall.model;
+
+public enum Format {
+ JSON, XML, NONE;
+
+ public static Format fromString(String s) {
+ if ("json".equalsIgnoreCase(s))
+ return JSON;
+ if ("xml".equalsIgnoreCase(s))
+ return XML;
+ if ("none".equalsIgnoreCase(s))
+ return NONE;
+ throw new IllegalArgumentException("Invalid value for format: " + s);
+ }
+}
diff --git a/plugins/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/JsonParser.java b/plugins/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/JsonParser.java
new file mode 100644
index 000000000..3d48a790f
--- /dev/null
+++ b/plugins/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/JsonParser.java
@@ -0,0 +1,93 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Copyright (C) 2018 Samsung Electronics. All rights
+ * reserved.
+ * ================================================================================
+ * Modifications Copyright © 2018 IBM
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.sshapicall.model;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.codehaus.jettison.json.JSONArray;
+import org.codehaus.jettison.json.JSONException;
+import org.codehaus.jettison.json.JSONObject;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public final class JsonParser {
+
+ private static final Logger log = LoggerFactory.getLogger(JsonParser.class);
+
+ private JsonParser() {
+ // Preventing instantiation of the same.
+ }
+
+ @SuppressWarnings("unchecked")
+ public static Map<String, String> convertToProperties(String s)
+ throws JSONException {
+
+ checkNotNull(s, "Input should not be null.");
+
+ JSONObject json = new JSONObject(s);
+ Map<String, Object> wm = new HashMap<>();
+ Iterator<String> ii = json.keys();
+ while (ii.hasNext()) {
+ String key1 = ii.next();
+ wm.put(key1, json.get(key1));
+ }
+
+ Map<String, String> mm = new HashMap<>();
+
+ while (!wm.isEmpty())
+ for (String key : new ArrayList<>(wm.keySet())) {
+ Object o = wm.get(key);
+ wm.remove(key);
+
+ if (o instanceof Boolean || o instanceof Number || o instanceof String) {
+ mm.put(key, o.toString());
+
+ log.info("Added property: {} : {}", key, o.toString());
+ } else if (o instanceof JSONObject) {
+ JSONObject jo = (JSONObject) o;
+ Iterator<String> i = jo.keys();
+ while (i.hasNext()) {
+ String key1 = i.next();
+ wm.put(key + "." + key1, jo.get(key1));
+ }
+ } else if (o instanceof JSONArray) {
+ JSONArray ja = (JSONArray) o;
+ mm.put(key + "_length", String.valueOf(ja.length()));
+
+ log.info("Added property: {}_length: {}", key, String.valueOf(ja.length()));
+
+ for (int i = 0; i < ja.length(); i++)
+ wm.put(key + '[' + i + ']', ja.get(i));
+ }
+ }
+ return mm;
+ }
+}
diff --git a/plugins/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/Parameters.java b/plugins/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/Parameters.java
new file mode 100644
index 000000000..fa2371e88
--- /dev/null
+++ b/plugins/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/Parameters.java
@@ -0,0 +1,45 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Copyright (C) 2018 Samsung Electronics. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.sshapicall.model;
+
+import java.util.Set;
+
+public class Parameters {
+ public String sshapiUrl;
+ public int sshapiPort;
+ public String sshapiUser;
+ public String sshapiPassword;
+ public String sshKey;
+ public long sshExecTimeout;
+ public String sshFileParameters;
+ public String sshEnvParameters;
+ public boolean sshWithRetry;
+ public String cmd;
+ public String responsePrefix;
+ public Format responseType;
+
+ public Set<String> listNameList;
+ public boolean convertResponse;
+ public AuthType authtype;
+}
diff --git a/plugins/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/ParseParam.java b/plugins/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/ParseParam.java
new file mode 100644
index 000000000..35c1087d8
--- /dev/null
+++ b/plugins/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/ParseParam.java
@@ -0,0 +1,275 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Copyright (C) 2018 Samsung Electronics. All rights
+ * reserved.
+ * ================================================================================
+ * Modifications Copyright © 2018 IBM
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.sshapicall.model;
+
+import com.google.common.base.Strings;
+import org.json.JSONException;
+import org.json.JSONObject;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.ByteArrayInputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+
+public class ParseParam {
+ private static final Logger log = LoggerFactory.getLogger(ParseParam.class);
+ /**
+ * Default SSH command timeout
+ */
+ private long dEF_timeout = 12000;
+ /**
+ * Default SSH connection port.
+ */
+ private int dEF_port = 22;
+ /**
+ * Default SSH command timeout
+ */
+ private final String FILE_PARAMETERS_OPT_KEY = "FileParameters";
+ public final String SSH_ResponsePrefix = "ResponsePrefix";
+ /**
+ * Default SSH connection port.
+ */
+ private final String ENV_PARAMETERS_OPT_KEY = "EnvParameters";
+ private Parameters p = new Parameters();
+
+ public Parameters getParameters(Map<String, String> paramMap) throws SvcLogicException {
+ p.sshapiUrl = parseParam(paramMap, "Url", true, null);
+ p.sshapiPort = Integer.parseInt(parseParam(paramMap, "Port", true, Integer.toString(dEF_port)));
+ p.sshapiUser = parseParam(paramMap, "User", false, null);
+ p.sshapiPassword = parseParam(paramMap, "Password", false, null);
+ p.sshKey = parseParam(paramMap, "SshKey", false, null);
+ p.sshExecTimeout = Long.parseLong(parseParam(paramMap, "ExecTimeout", false, Long.toString(dEF_timeout)));
+ p.sshWithRetry = Boolean.valueOf(parseParam(paramMap, "Retry", false, "false"));
+ p.cmd = parseParam(paramMap, "Cmd", true, null);
+ p.responsePrefix = parseParam(paramMap, SSH_ResponsePrefix, false, null);
+ p.responseType = Format.fromString(parseParam(paramMap, "ResponseType", false, "none"));
+ p.listNameList = getListNameList(paramMap);
+ p.convertResponse = Boolean.valueOf(parseParam(paramMap, "ConvertResponse", false, "true"));
+ p.authtype = AuthType.fromString(parseParam(paramMap, "AuthType", false, "unspecified"));
+
+ return p;
+ }
+
+ public String getStringParameters(Map<String, String> paramMap, String paramName) throws SvcLogicException {
+ return parseParam(paramMap, SSH_ResponsePrefix, false, null);
+ }
+
+ public void parseOutput (SvcLogicContext ctx, String outMessage) throws SvcLogicException {
+ if (p.convertResponse) {
+ if (p.responseType == Format.NONE) {
+ classifyOutput(ctx, outMessage);
+ } else if (p.responseType == Format.JSON) {
+ classifyOutput(ctx, outMessage);
+ } else if (p.responseType == Format.XML) {
+ classifyOutput(ctx, outMessage, p.listNameList);
+ }
+ }
+ }
+
+ private void classifyOutput(SvcLogicContext ctx, String outMessage, Set<String> listNameList) throws SvcLogicException {
+ Map<String, String> mm = XmlParser.convertToProperties(outMessage, p.listNameList);
+ toCtx (ctx, mm);
+ }
+
+ private void toCtx (SvcLogicContext ctx, Map<String, String> mm) {
+ if (mm != null) {
+ for (Map.Entry<String, String> entry : mm.entrySet()) {
+ if (p.responsePrefix != null) {
+ ctx.setAttribute(p.responsePrefix + "." + entry.getKey(), entry.getValue());
+ log.info("+++ " + p.responsePrefix + "." + entry.getKey() + ": [" + entry.getValue() + "]");
+ } else {
+ ctx.setAttribute(entry.getKey(), entry.getValue());
+ log.info("+++ " + entry.getKey() + ": [" + entry.getValue() + "]");
+ }
+ }
+ }
+ }
+
+ private void classifyOutput(SvcLogicContext ctx, String outMessage) throws SvcLogicException {
+ try {
+ Map<String, String> mm = JsonParser.convertToProperties(outMessage);
+ toCtx (ctx, mm);
+ } catch (org.codehaus.jettison.json.JSONException e) {
+ log.info("Output not in JSON format");
+ putToProperties(ctx, p.responsePrefix);
+ } catch (Exception e) {
+ throw new SvcLogicException("error parsing response file");
+ }
+ }
+
+ private void putToProperties(SvcLogicContext ctx, String outMessage) throws SvcLogicException {
+
+ try {
+ Properties prop = new Properties();
+ prop.load(new ByteArrayInputStream(outMessage.getBytes(StandardCharsets.UTF_8)));
+ for (Object key : prop.keySet()) {
+ String name = (String) key;
+ String value = prop.getProperty(name);
+ if (value != null && value.trim().length() > 0) {
+ if (p.responsePrefix != null) {
+ ctx.setAttribute(p.responsePrefix + "." + name, value.trim());
+ log.info("+++ " + p.responsePrefix + "." + name + ": [" + value + "]");
+ } else {
+ ctx.setAttribute(name, value.trim());
+ log.info("+++ " + name + ": [" + value + "]");
+ }
+ }
+ }
+ } catch (Exception e) {
+ throw new SvcLogicException( "Error parsing response file.");
+ }
+ }
+
+ public String makeCommand (Map<String, String> params) {
+ JSONObject jsonPayload = new JSONObject();
+ final String[] optionalTestParams = {ENV_PARAMETERS_OPT_KEY, FILE_PARAMETERS_OPT_KEY};
+ parseParam(params, optionalTestParams, jsonPayload);
+ JSONObject envParams = (JSONObject) jsonPayload.remove(ENV_PARAMETERS_OPT_KEY);
+ JSONObject fileParams = (JSONObject) jsonPayload.remove(FILE_PARAMETERS_OPT_KEY);
+
+ StringBuilder constructedCommand = new StringBuilder();
+ constructedCommand.append(parseFileParam(fileParams)).append(p.cmd).append(" ").append(parseEnvParam(envParams));
+
+ return constructedCommand.toString();
+ }
+
+ private String parseEnvParam(JSONObject envParams) {
+ StringBuilder envParamBuilder = new StringBuilder();
+ if (envParams != null) {
+ for (Object key : envParams.keySet()) {
+ if (envParamBuilder.length() > 0) {
+ envParamBuilder.append(", ");
+ }
+ envParamBuilder.append(key + "=" + envParams.get((String) key));
+ }
+ }
+ return envParamBuilder.toString();
+ }
+
+ private String parseFileParam(JSONObject fileParams) {
+ StringBuilder fileParamBuilder = new StringBuilder();
+ if (fileParams != null) {
+ for (Object key : fileParams.keySet()) {
+ fileParamBuilder.append("echo -e \"" + fileParams.get((String) key) + "\" > /srv/salt/" + key).append("; ");
+ }
+ }
+ return fileParamBuilder.toString();
+ }
+
+ private void parseParam(Map<String, String> params, String[] optionalTestParams, JSONObject jsonPayload)
+ throws JSONException {
+
+ Set<String> optionalParamsSet = new HashSet<>();
+ Collections.addAll(optionalParamsSet, optionalTestParams);
+
+ //@formatter:off
+ params.entrySet()
+ .stream()
+ .filter(entry -> optionalParamsSet.contains(entry.getKey()))
+ .filter(entry -> !Strings.isNullOrEmpty(entry.getValue()))
+ .forEach(entry -> parseParam(entry, jsonPayload));
+ //@formatter:on
+ }
+
+ private void parseParam(Map.Entry<String, String> params, JSONObject jsonPayload)
+ throws JSONException {
+ String key = params.getKey();
+ String payload = params.getValue();
+
+ switch (key) {
+ case ENV_PARAMETERS_OPT_KEY:
+ JSONObject paramsJson = new JSONObject(payload);
+ jsonPayload.put(key, paramsJson);
+ break;
+
+ case FILE_PARAMETERS_OPT_KEY:
+ jsonPayload.put(key, getFilePayload(payload));
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ /**
+ * Return payload with escaped newlines
+ */
+ private JSONObject getFilePayload(String payload) {
+ String formattedPayload = payload.replace("\n", "\\n").replace("\r", "\\r");
+ return new JSONObject(formattedPayload);
+ }
+
+ private Set<String> getListNameList(Map<String, String> paramMap) {
+ Set<String> ll = new HashSet<>();
+ for (Map.Entry<String,String> entry : paramMap.entrySet())
+ if (entry.getKey().startsWith("listName"))
+ ll.add(entry.getValue());
+ return ll;
+ }
+
+ private String parseParam(Map<String, String> paramMap, String name, boolean required, String def)
+ throws SvcLogicException {
+ String s = paramMap.get(name);
+
+ if (s == null || s.trim().length() == 0) {
+ if (!required)
+ return def;
+ throw new SvcLogicException("Parameter " + name + " is required in sshapiCallNode");
+ }
+
+ s = s.trim();
+ StringBuilder value = new StringBuilder();
+ int i = 0;
+ int i1 = s.indexOf('%');
+ while (i1 >= 0) {
+ int i2 = s.indexOf('%', i1 + 1);
+ if (i2 < 0)
+ break;
+
+ String varName = s.substring(i1 + 1, i2);
+ String varValue = System.getenv(varName);
+ if (varValue == null)
+ varValue = "%" + varName + "%";
+
+ value.append(s.substring(i, i1));
+ value.append(varValue);
+
+ i = i2 + 1;
+ i1 = s.indexOf('%', i);
+ }
+ value.append(s.substring(i));
+
+ log.info("Parameter {}: [{}]", name, value);
+ return value.toString();
+ }
+}
diff --git a/plugins/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/XmlJsonUtil.java b/plugins/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/XmlJsonUtil.java
new file mode 100644
index 000000000..d68fbc6ac
--- /dev/null
+++ b/plugins/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/XmlJsonUtil.java
@@ -0,0 +1,389 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Copyright (C) 2018 Samsung Electronics. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.sshapicall.model;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public final class XmlJsonUtil {
+
+ private static final Logger log = LoggerFactory.getLogger(XmlJsonUtil.class);
+
+ private XmlJsonUtil() {
+ // Preventing instantiation of the same.
+ }
+
+ public static String getXml(Map<String, String> varmap, String var) {
+ boolean escape = true;
+ if (var.startsWith("'")) {
+ var = var.substring(1);
+ escape = false;
+ }
+
+ Object o = createStructure(varmap, var);
+ return generateXml(o, 0, escape);
+ }
+
+ public static String getJson(Map<String, String> varmap, String var) {
+ boolean escape = true;
+ if (var.startsWith("'")) {
+ var = var.substring(1);
+ escape = false;
+ }
+
+ boolean quotes = true;
+ if (var.startsWith("\"")) {
+ var = var.substring(1);
+ quotes = false;
+ }
+
+ Object o = createStructure(varmap, var);
+ return generateJson(o, escape, quotes);
+ }
+
+ private static Object createStructure(Map<String, String> flatmap, String var) {
+ if (flatmap.containsKey(var)) {
+ if (var.endsWith("_length") || var.endsWith("].key"))
+ return null;
+ return flatmap.get(var);
+ }
+
+ Map<String, Object> mm = new HashMap<>();
+ for (String k : flatmap.keySet())
+ if (k.startsWith(var + ".")) {
+ int i1 = k.indexOf('.', var.length() + 1);
+ int i2 = k.indexOf('[', var.length() + 1);
+ int i3 = k.length();
+ if (i1 > 0 && i1 < i3)
+ i3 = i1;
+ if (i2 > 0 && i2 < i3)
+ i3 = i2;
+ String k1 = k.substring(var.length() + 1, i3);
+ String var1 = k.substring(0, i3);
+ if (!mm.containsKey(k1)) {
+ Object str = createStructure(flatmap, var1);
+ if (str != null && (!(str instanceof String) || ((String) str).trim().length() > 0))
+ mm.put(k1, str);
+ }
+ }
+ if (!mm.isEmpty())
+ return mm;
+
+ boolean arrayFound = false;
+ for (String k : flatmap.keySet())
+ if (k.startsWith(var + "[")) {
+ arrayFound = true;
+ break;
+ }
+
+ if (arrayFound) {
+ List<Object> ll = new ArrayList<>();
+
+ int length = Integer.MAX_VALUE;
+ String lengthStr = flatmap.get(var + "_length");
+ if (lengthStr != null) {
+ try {
+ length = Integer.parseInt(lengthStr);
+ } catch (Exception e) {
+ log.warn("Invalid number for {}_length:{}", var, lengthStr, e);
+ }
+ }
+
+ for (int i = 0; i < length; i++) {
+ Object v = createStructure(flatmap, var + '[' + i + ']');
+ if (v == null)
+ break;
+ ll.add(v);
+ }
+
+ if (!ll.isEmpty())
+ return ll;
+ }
+
+ return null;
+ }
+
+ @SuppressWarnings("unchecked")
+ private static String generateXml(Object o, int indent, boolean escape) {
+ if (o == null)
+ return null;
+
+ if (o instanceof String)
+ return escape ? escapeXml((String) o) : (String) o;;
+
+ if (o instanceof Map) {
+ StringBuilder ss = new StringBuilder();
+ Map<String, Object> mm = (Map<String, Object>) o;
+ for (Map.Entry<String, Object> entry: mm.entrySet()) {
+ Object v = entry.getValue();
+ String key = entry.getKey();
+ if (v instanceof String) {
+ String s = escape ? escapeXml((String) v) : (String) v;
+ ss.append(pad(indent)).append('<').append(key).append('>');
+ ss.append(s);
+ ss.append("</").append(key).append('>').append('\n');
+ } else if (v instanceof Map) {
+ ss.append(pad(indent)).append('<').append(key).append('>').append('\n');
+ ss.append(generateXml(v, indent + 1, escape));
+ ss.append(pad(indent)).append("</").append(key).append('>').append('\n');
+ } else if (v instanceof List) {
+ List<Object> ll = (List<Object>) v;
+ for (Object o1 : ll) {
+ ss.append(pad(indent)).append('<').append(key).append('>').append('\n');
+ ss.append(generateXml(o1, indent + 1, escape));
+ ss.append(pad(indent)).append("</").append(key).append('>').append('\n');
+ }
+ }
+ }
+ return ss.toString();
+ }
+
+ return null;
+ }
+
+ private static String generateJson(Object o, boolean escape, boolean quotes) {
+ if (o == null)
+ return null;
+
+ StringBuilder ss = new StringBuilder();
+ generateJson(ss, o, 0, false, escape, quotes);
+ return ss.toString();
+ }
+
+ @SuppressWarnings("unchecked")
+ private static void generateJson(StringBuilder ss, Object o, int indent, boolean padFirst, boolean escape, boolean quotes) {
+ if (o instanceof String) {
+ String s = escape ? escapeJson((String) o) : (String) o;
+ if (padFirst)
+ ss.append(pad(indent));
+ if (quotes) {
+ ss.append('"').append(s).append('"');
+ } else {
+ ss.append(s);
+ }
+ return;
+ }
+
+ if (o instanceof Map) {
+ Map<String, Object> mm = (Map<String, Object>) o;
+
+ if (padFirst)
+ ss.append(pad(indent));
+ ss.append("{\n");
+
+ boolean first = true;
+ for (Map.Entry<String, Object> entry : mm.entrySet()) {
+ if (!first)
+ ss.append(",\n");
+ first = false;
+ Object v = entry.getValue();
+ String key = entry.getKey();
+ ss.append(pad(indent + 1)).append('"').append(key).append("\": ");
+ generateJson(ss, v, indent + 1, false, escape, true);
+ }
+
+ ss.append("\n");
+ ss.append(pad(indent)).append('}');
+
+ return;
+ }
+
+ if (o instanceof List) {
+ List<Object> ll = (List<Object>) o;
+
+ if (padFirst)
+ ss.append(pad(indent));
+ ss.append("[\n");
+
+ boolean first = true;
+ for (Object o1 : ll) {
+ if (!first)
+ ss.append(",\n");
+ first = false;
+
+ generateJson(ss, o1, indent + 1, true, escape, quotes);
+ }
+
+ ss.append("\n");
+ ss.append(pad(indent)).append(']');
+ }
+ }
+
+ public static String removeLastCommaJson(String s) {
+ StringBuilder sb = new StringBuilder();
+ int k = 0;
+ int start = 0;
+ while (k < s.length()) {
+ int i11 = s.indexOf('}', k);
+ int i12 = s.indexOf(']', k);
+ int i1 = -1;
+ if (i11 < 0)
+ i1 = i12;
+ else if (i12 < 0)
+ i1 = i11;
+ else
+ i1 = i11 < i12 ? i11 : i12;
+ if (i1 < 0)
+ break;
+
+ int i2 = s.lastIndexOf(',', i1);
+ if (i2 < 0) {
+ k = i1 + 1;
+ continue;
+ }
+
+ String between = s.substring(i2 + 1, i1);
+ if (between.trim().length() > 0) {
+ k = i1 + 1;
+ continue;
+ }
+
+ sb.append(s.substring(start, i2));
+ start = i2 + 1;
+ k = i1 + 1;
+ }
+
+ sb.append(s.substring(start, s.length()));
+
+ return sb.toString();
+ }
+
+ public static String removeEmptyStructJson(String s) {
+ int k = 0;
+ while (k < s.length()) {
+ boolean curly = true;
+ int i11 = s.indexOf('{', k);
+ int i12 = s.indexOf('[', k);
+ int i1 = -1;
+ if (i11 < 0) {
+ i1 = i12;
+ curly = false;
+ } else if (i12 < 0)
+ i1 = i11;
+ else
+ if (i11 < i12)
+ i1 = i11;
+ else {
+ i1 = i12;
+ curly = false;
+ }
+
+ if (i1 >= 0) {
+ int i2 = curly ? s.indexOf('}', i1) : s.indexOf(']', i1);
+ if (i2 > 0) {
+ String value = s.substring(i1 + 1, i2);
+ if (value.trim().length() == 0) {
+ int i4 = s.lastIndexOf('\n', i1);
+ if (i4 < 0)
+ i4 = 0;
+ int i5 = s.indexOf('\n', i2);
+ if (i5 < 0)
+ i5 = s.length();
+
+ s = s.substring(0, i4) + s.substring(i5);
+ k = 0;
+ } else
+ k = i1 + 1;
+ } else
+ break;
+ } else
+ break;
+ }
+
+ return s;
+ }
+
+ public static String removeEmptyStructXml(String s) {
+ int k = 0;
+ while (k < s.length()) {
+ int i1 = s.indexOf('<', k);
+ if (i1 < 0 || i1 == s.length() - 1)
+ break;
+
+ char c1 = s.charAt(i1 + 1);
+ if (c1 == '?' || c1 == '!') {
+ k = i1 + 2;
+ continue;
+ }
+
+ int i2 = s.indexOf('>', i1);
+ if (i2 < 0) {
+ k = i1 + 1;
+ continue;
+ }
+
+ String closingTag = "</" + s.substring(i1 + 1, i2 + 1);
+ int i3 = s.indexOf(closingTag, i2 + 1);
+ if (i3 < 0) {
+ k = i2 + 1;
+ continue;
+ }
+
+ String value = s.substring(i2 + 1, i3);
+ if (value.trim().length() > 0) {
+ k = i2 + 1;
+ continue;
+ }
+
+ int i4 = s.lastIndexOf('\n', i1);
+ if (i4 < 0)
+ i4 = 0;
+ int i5 = s.indexOf('\n', i3);
+ if (i5 < 0)
+ i5 = s.length();
+
+ s = s.substring(0, i4) + s.substring(i5);
+ k = 0;
+ }
+
+ return s;
+ }
+
+ private static String escapeXml(String v) {
+ String s = v.replaceAll("&", "&amp;");
+ s = s.replaceAll("<", "&lt;");
+ s = s.replaceAll("'", "&apos;");
+ s = s.replaceAll("\"", "&quot;");
+ s = s.replaceAll(">", "&gt;");
+ return s;
+ }
+
+ private static String escapeJson(String v) {
+ String s = v.replaceAll("\\\\", "\\\\\\\\");
+ s = s.replaceAll("\"", "\\\\\"");
+ return s;
+ }
+
+ private static String pad(int n) {
+ StringBuilder s = new StringBuilder();
+ for (int i = 0; i < n; i++)
+ s.append(Character.toString('\t'));
+ return s.toString();
+ }
+}
diff --git a/plugins/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/XmlParser.java b/plugins/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/XmlParser.java
new file mode 100644
index 000000000..6ea770ad9
--- /dev/null
+++ b/plugins/sshapi-call-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/sshapicall/model/XmlParser.java
@@ -0,0 +1,176 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
+ *
+ * Modifications Copyright © 2018 IBM.
+ * ================================================================================
+ * Copyright (C) 2018 Samsung Electronics. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.sshapicall.model;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.parsers.SAXParser;
+import javax.xml.parsers.SAXParserFactory;
+
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+public final class XmlParser {
+
+ private static final Logger log = LoggerFactory.getLogger(XmlParser.class);
+
+ private XmlParser() {
+ // Preventing instantiation of the same.
+ }
+
+ public static Map<String, String> convertToProperties(String s, Set<String> listNameList)
+ throws SvcLogicException {
+
+ checkNotNull(s, "Input should not be null.");
+
+ Handler handler = new Handler(listNameList);
+ try {
+ SAXParserFactory factory = SAXParserFactory.newInstance();
+ SAXParser saxParser = factory.newSAXParser();
+ InputStream in = new ByteArrayInputStream(s.getBytes());
+ saxParser.parse(in, handler);
+ } catch (ParserConfigurationException | IOException | SAXException | NumberFormatException e) {
+ throw new SvcLogicException("Unable to convert XML to properties" + e.getLocalizedMessage(), e);
+ }
+ return handler.getProperties();
+ }
+
+ private static class Handler extends DefaultHandler {
+
+ private Set<String> listNameList;
+
+ private Map<String, String> properties = new HashMap<>();
+
+ StringBuilder currentName = new StringBuilder();
+ StringBuilder currentValue = new StringBuilder();
+
+ public Handler(Set<String> listNameList) {
+ super();
+ this.listNameList = listNameList;
+ if (this.listNameList == null)
+ this.listNameList = new HashSet<>();
+ }
+
+ public Map<String, String> getProperties() {
+ return properties;
+ }
+
+ @Override
+ public void startElement(String uri, String localName, String qName, Attributes attributes)
+ throws SAXException {
+ super.startElement(uri, localName, qName, attributes);
+
+ String name = localName;
+ if (name == null || name.trim().length() == 0)
+ name = qName;
+ int i2 = name.indexOf(':');
+ if (i2 >= 0)
+ name = name.substring(i2 + 1);
+
+ if (currentName.length() > 0)
+ currentName.append(Character.toString('.'));
+ currentName.append(name);
+
+ String listName = removeIndexes(currentName.toString());
+
+ if (listNameList.contains(listName)) {
+ String n = currentName.toString() + "_length";
+ int len = getInt(properties, n);
+ properties.put(n, String.valueOf(len + 1));
+ currentName.append("[").append(len).append("]");
+ }
+ }
+
+ @Override
+ public void endElement(String uri, String localName, String qName) throws SAXException {
+ super.endElement(uri, localName, qName);
+
+ String name = localName;
+ if (name == null || name.trim().length() == 0)
+ name = qName;
+ int i2 = name.indexOf(':');
+ if (i2 >= 0)
+ name = name.substring(i2 + 1);
+
+ String s = currentValue.toString().trim();
+ if (s.length() > 0) {
+ properties.put(currentName.toString(), s);
+
+ log.info("Added property: {} : {}", currentName, s);
+ currentValue = new StringBuilder();
+ }
+
+ int i1 = currentName.lastIndexOf("." + name);
+ if (i1 <= 0)
+ currentName = new StringBuilder();
+ else
+ currentName = new StringBuilder(currentName.substring(0, i1));
+ }
+
+ @Override
+ public void characters(char[] ch, int start, int length) throws SAXException {
+ super.characters(ch, start, length);
+
+ String value = new String(ch, start, length);
+ currentValue.append(value);
+ }
+
+ private static int getInt(Map<String, String> mm, String name) {
+ String s = mm.get(name);
+ if (s == null)
+ return 0;
+ return Integer.parseInt(s);
+ }
+
+ private String removeIndexes(String currentName) {
+ StringBuilder b = new StringBuilder();
+ boolean add = true;
+ for (int i = 0; i < currentName.length(); i++) {
+ char c = currentName.charAt(i);
+ if (c == '[')
+ add = false;
+ else if (c == ']')
+ add = true;
+ else if (add)
+ b.append(Character.toString(c));
+ }
+ return b.toString();
+ }
+ }
+}
diff --git a/plugins/sshapi-call-node/provider/src/main/resources/META-INF/spring/sshapi-call-node-context.xml b/plugins/sshapi-call-node/provider/src/main/resources/META-INF/spring/sshapi-call-node-context.xml
new file mode 100644
index 000000000..50c9b2aa3
--- /dev/null
+++ b/plugins/sshapi-call-node/provider/src/main/resources/META-INF/spring/sshapi-call-node-context.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ============LICENSE_START=======================================================
+ openECOMP : SDN-C
+ ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property.
+ * ================================================================================
+ * Copyright (C) 2018 Samsung Electronics. All rights
+ reserved.
+ ================================================================================
+ 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.
+ ============LICENSE_END=========================================================
+ -->
+
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.springframework.org/schema/beans
+ http://www.springframework.org/schema/beans/spring-beans.xsd">
+
+ <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
+ <property name="locations">
+ <list>
+ <value>file:${SDNC_CONFIG_DIR}/ueb.properties</value>
+ <value>file:${SDNC_CONFIG_DIR}/dme2.properties</value>
+ </list>
+ </property>
+ <property name="ignoreResourceNotFound" value="true" />
+ <property name="ignoreUnresolvablePlaceholders" value="true" />
+ </bean>
+
+ <!-- context:property-placeholder location="file:${SDNC_CONFIG_DIR}/ueb.properties" /-->
+
+ <bean id="sshapiCallNode" class="org.onap.ccsdk.sli.plugins.sshapicall.SshApiCallNode">
+ <property name="uebServers" value="${servers}" />
+ </bean>
+
+</beans>
diff --git a/plugins/sshapi-call-node/provider/src/main/resources/META-INF/spring/sshapi-call-node-osgi-context.xml b/plugins/sshapi-call-node/provider/src/main/resources/META-INF/spring/sshapi-call-node-osgi-context.xml
new file mode 100644
index 000000000..25631d6af
--- /dev/null
+++ b/plugins/sshapi-call-node/provider/src/main/resources/META-INF/spring/sshapi-call-node-osgi-context.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ============LICENSE_START=======================================================
+ openECOMP : SDN-C
+ ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property.
+ * ================================================================================
+ * Copyright (C) 2018 Samsung Electronics. All rights
+ reserved.
+ ================================================================================
+ 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.
+ ============LICENSE_END=========================================================
+ -->
+
+<beans:beans xmlns="http://www.springframework.org/schema/osgi"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:beans="http://www.springframework.org/schema/beans"
+ xsi:schemaLocation="http://www.springframework.org/schema/osgi
+ http://www.springframework.org/schema/osgi/spring-osgi.xsd
+ http://www.springframework.org/schema/beans
+ http://www.springframework.org/schema/beans/spring-beans.xsd">
+
+ <service ref="sshapiCallNode" interface="org.onap.ccsdk.sli.plugins.sshapicall.SshApiCallNode" />
+
+</beans:beans>
diff --git a/plugins/sshapi-call-node/provider/src/main/resources/OSGI-INF/blueprint/sshapi-call-node-blueprint.xml b/plugins/sshapi-call-node/provider/src/main/resources/OSGI-INF/blueprint/sshapi-call-node-blueprint.xml
new file mode 100755
index 000000000..7a5424329
--- /dev/null
+++ b/plugins/sshapi-call-node/provider/src/main/resources/OSGI-INF/blueprint/sshapi-call-node-blueprint.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+ xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0"
+ odl:use-default-for-reference-types="true">
+
+ <bean id="sshapiCallNodeProvider" class="org.onap.ccsdk.sli.plugins.sshapicall.SshApiCallNode" />
+
+
+
+ <service ref="sshapiCallNodeProvider">
+ <interfaces>
+ <value>org.onap.ccsdk.sli.plugins.sshapicall.SshApiCallNode</value>
+ </interfaces>
+ </service>
+
+</blueprint> \ No newline at end of file
diff --git a/plugins/sshapi-call-node/provider/src/main/resources/org/opendaylight/blueprint/sshapi-call-node-blueprint.xml b/plugins/sshapi-call-node/provider/src/main/resources/org/opendaylight/blueprint/sshapi-call-node-blueprint.xml
new file mode 100755
index 000000000..7a5424329
--- /dev/null
+++ b/plugins/sshapi-call-node/provider/src/main/resources/org/opendaylight/blueprint/sshapi-call-node-blueprint.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+ xmlns:odl="http://opendaylight.org/xmlns/blueprint/v1.0.0"
+ odl:use-default-for-reference-types="true">
+
+ <bean id="sshapiCallNodeProvider" class="org.onap.ccsdk.sli.plugins.sshapicall.SshApiCallNode" />
+
+
+
+ <service ref="sshapiCallNodeProvider">
+ <interfaces>
+ <value>org.onap.ccsdk.sli.plugins.sshapicall.SshApiCallNode</value>
+ </interfaces>
+ </service>
+
+</blueprint> \ No newline at end of file
diff --git a/plugins/sshapi-call-node/provider/src/test/java/jtest/org/onap/ccsdk/sli/plugins/restapicall/TestJsonParser.java b/plugins/sshapi-call-node/provider/src/test/java/jtest/org/onap/ccsdk/sli/plugins/restapicall/TestJsonParser.java
new file mode 100644
index 000000000..78f20e327
--- /dev/null
+++ b/plugins/sshapi-call-node/provider/src/test/java/jtest/org/onap/ccsdk/sli/plugins/restapicall/TestJsonParser.java
@@ -0,0 +1,85 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Copyright (C) 2018 Samsung Electronics. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package jtest.org.onap.ccsdk.sli.plugins.restapicall;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+import org.codehaus.jettison.json.JSONException;
+import org.junit.Test;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.plugins.sshapicall.model.JsonParser;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class TestJsonParser {
+
+ private static final Logger log = LoggerFactory.getLogger(TestJsonParser.class);
+
+ @Test
+ public void test() throws SvcLogicException, IOException {
+ BufferedReader in = new BufferedReader(
+ new InputStreamReader(ClassLoader.getSystemResourceAsStream("test.json"))
+ );
+ StringBuilder b = new StringBuilder();
+ String line;
+ while ((line = in.readLine()) != null)
+ b.append(line).append('\n');
+ Map<String, String> mm = null;
+ try {
+ mm = JsonParser.convertToProperties(b.toString());
+ } catch (JSONException e){
+ throw new SvcLogicException(e.getMessage());
+ }
+
+ logProperties(mm);
+
+ in.close();
+ }
+
+ @Test(expected = NullPointerException.class)
+ public void testNullString() throws SvcLogicException {
+ Map<String, String> mm = null;
+ try {
+ mm = JsonParser.convertToProperties(null);
+ } catch (JSONException e){
+ throw new SvcLogicException(e.getMessage());
+ }
+ }
+
+ private void logProperties(Map<String, String> mm) {
+ List<String> ll = new ArrayList<>();
+ for (Object o : mm.keySet())
+ ll.add((String) o);
+ Collections.sort(ll);
+ log.info("Properties:");
+ for (String name : ll)
+ log.info("--- {}: {}", name, mm.get(name));
+ }
+}
diff --git a/plugins/sshapi-call-node/provider/src/test/java/jtest/org/onap/ccsdk/sli/plugins/restapicall/TestSshApiCallNode.java b/plugins/sshapi-call-node/provider/src/test/java/jtest/org/onap/ccsdk/sli/plugins/restapicall/TestSshApiCallNode.java
new file mode 100644
index 000000000..c0bcdb82a
--- /dev/null
+++ b/plugins/sshapi-call-node/provider/src/test/java/jtest/org/onap/ccsdk/sli/plugins/restapicall/TestSshApiCallNode.java
@@ -0,0 +1,330 @@
+package jtest.org.onap.ccsdk.sli.plugins.restapicall;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.plugins.sshapicall.SshApiCallNode;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.junit.Assert.assertEquals;
+
+public class TestSshApiCallNode {
+
+ private static final Logger log = LoggerFactory.getLogger(TestSshApiCallNode.class);
+
+ private SshApiCallNode adapter;
+ private String TestId;
+ private boolean testMode = true;
+ private Map<String, String> params;
+ private SvcLogicContext svcContext;
+
+
+ @Before
+ public void setup() throws IllegalArgumentException {
+ testMode = true;
+ svcContext = new SvcLogicContext();
+ adapter = new SshApiCallNode();
+
+ params = new HashMap<>();
+ params.put("AgentUrl", "https://192.168.1.1");
+ params.put("User", "test");
+ params.put("Password", "test");
+ }
+
+ @After
+ public void tearDown() {
+ testMode = false;
+ adapter = null;
+ params = null;
+ svcContext = null;
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void testExecCommand_noUrlFailed() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("HostName", "test");
+ params.put("Port", "10");
+ params.put("User", "test");
+ params.put("Password", "test");
+ params.put("Test", "fail");
+ adapter.execCommand(params, svcContext);
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void testExecCommandPty_noUrlFailed() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("HostName", "test");
+ params.put("Port", "10");
+ params.put("User", "test");
+ params.put("Password", "test");
+ params.put("Test", "fail");
+ adapter.execCommandWithPty(params, svcContext);
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void testExecCommandResponse_noUrlFailed() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("HostName", "test");
+ params.put("Port", "10");
+ params.put("User", "test");
+ params.put("Password", "test");
+ params.put("Test", "fail");
+ adapter.execWithStatusCheck(params, svcContext);
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void testExecCommand_noPortFailed() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("Url", "test");
+ params.put("User", "test");
+ params.put("Password", "test");
+ params.put("Test", "fail");
+ adapter.execCommand(params, svcContext);
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void testExecCommandPty_noPortFailed() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("Url", "test");
+ params.put("User", "test");
+ params.put("Password", "test");
+ params.put("Test", "fail");
+ adapter.execCommandWithPty(params, svcContext);
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void testExecCommandResponse_noPortFailed() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("Url", "test");
+ params.put("User", "test");
+ params.put("Password", "test");
+ params.put("Test", "fail");
+ adapter.execWithStatusCheck(params, svcContext);
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void testExecCommand_noCmdFailed() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("Url", "test");
+ params.put("Port", "10");
+ adapter.execCommand(params, svcContext);
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void testExecCommandPty_noCmdFailed() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("Url", "test");
+ params.put("Port", "10");
+ adapter.execCommandWithPty(params, svcContext);
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void testExecCommandResponse_noCmdFailed() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("Url", "test");
+ params.put("Port", "10");
+ adapter.execWithStatusCheck(params, svcContext);
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void testExecCommandResponse_noSSHBasicFailed() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("Url", "test");
+ params.put("Port", "10");
+ params.put("User", "test");
+ params.put("Password", "test");
+ params.put("AuthType", "basic");
+ params.put("Cmd", "test");
+ adapter.execWithStatusCheck(params, svcContext);
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void testExecCommandResponse_noSSHKeyFailed() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("Url", "test");
+ params.put("Port", "10");
+ params.put("User", "test");
+ params.put("Password", "test");
+ params.put("AuthType", "key");
+ params.put("Cmd", "test");
+ adapter.execWithStatusCheck(params, svcContext);
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void testExecCommandResponse_noSSHNoneFailed() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("Url", "test");
+ params.put("Port", "10");
+ params.put("User", "test");
+ params.put("Password", "test");
+ params.put("AuthType", "none");
+ params.put("Cmd", "test");
+ params.put("ResponseType", "xml");
+ adapter.execWithStatusCheck(params, svcContext);
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void testExecCommandResponse_noSSHFailed() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("Url", "test");
+ params.put("Port", "10");
+ params.put("User", "test");
+ params.put("Password", "test");
+ params.put("Cmd", "test");
+ params.put("ResponseType", "json");
+ adapter.execWithStatusCheck(params, svcContext);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testExecCommandResponse_noSSHInvalidParam() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("Url", "test");
+ params.put("Port", "10");
+ params.put("User", "test");
+ params.put("Password", "test");
+ params.put("Cmd", "test");
+ params.put("ResponseType", "txt");
+ adapter.execWithStatusCheck(params, svcContext);
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testExecCommandResponse_noSSHInvalidAuthParam() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("Url", "test");
+ params.put("Port", "10");
+ params.put("User", "test");
+ params.put("Password", "test");
+ params.put("Cmd", "test");
+ params.put("AuthType", "spring");
+ params.put("ResponseType", "json");
+ adapter.execWithStatusCheck(params, svcContext);
+ }
+
+ @Test
+ public void testExecCommandResponse_validJSON() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("Url", "test");
+ params.put("Port", "10");
+ params.put("User", "test");
+ params.put("Password", "test");
+ params.put("Cmd", "test");
+ params.put("AuthType", "basic");
+ params.put("ResponseType", "json");
+ params.put("TestOut", "{\"equipment-data\":\"boo\"}");
+ params.put("TestFail", "false");
+ adapter = new SshApiCallNode(true);
+ adapter.execWithStatusCheck(params, svcContext);
+ assertEquals("boo", svcContext.getAttribute("equipment-data"));
+ }
+
+ @Test
+ public void testExecCommandResponse_validXML() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("Url", "test");
+ params.put("Port", "10");
+ params.put("User", "test");
+ params.put("Password", "test");
+ params.put("Cmd", "test");
+ params.put("AuthType", "basic");
+ params.put("ResponseType", "xml");
+ params.put("TestOut", "<modelVersion>4.0.0</modelVersion>");
+ params.put("TestFail", "false");
+ adapter = new SshApiCallNode(true);
+ adapter.execWithStatusCheck(params, svcContext);
+ assertEquals("4.0.0", svcContext.getAttribute("modelVersion"));
+ }
+
+ @Test
+ public void testExecCommandResponse_validJSONPrefix() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("Url", "test");
+ params.put("Port", "10");
+ params.put("User", "test");
+ params.put("Password", "test");
+ params.put("Cmd", "test");
+ params.put("AuthType", "basic");
+ params.put("ResponseType", "json");
+ params.put("TestOut", "{\"equipment-data\":\"boo\"}");
+ params.put("ResponsePrefix", "test");
+ params.put("TestFail", "false");
+ adapter = new SshApiCallNode(true);
+ adapter.execWithStatusCheck(params, svcContext);
+ assertEquals("boo", svcContext.getAttribute("test.equipment-data"));
+ }
+
+ @Test
+ public void testExecCommandResponse_validXMLPrefix() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("Url", "test");
+ params.put("Port", "10");
+ params.put("User", "test");
+ params.put("Password", "test");
+ params.put("Cmd", "test");
+ params.put("AuthType", "basic");
+ params.put("ResponseType", "xml");
+ params.put("TestOut", "<modelVersion>4.0.0</modelVersion>");
+ params.put("ResponsePrefix", "test");
+ params.put("TestFail", "false");
+ adapter = new SshApiCallNode(true);
+ adapter.execWithStatusCheck(params, svcContext);
+ assertEquals("4.0.0", svcContext.getAttribute("test.modelVersion"));
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void testExecCommandResponse_validXMLFail() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+
+ params.put("Url", "test");
+ params.put("Port", "10");
+ params.put("User", "test");
+ params.put("Password", "test");
+ params.put("Cmd", "test");
+ params.put("AuthType", "basic");
+ params.put("ResponseType", "xml");
+ params.put("TestOut", "<modelVersion>4.0.0</modelVersion>");
+ params.put("TestFail", "true");
+ params.put("ResponsePrefix", "test");
+ adapter = new SshApiCallNode(true);
+ adapter.execWithStatusCheck(params, svcContext);
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void testExecCommandResponse_validXMLPrefixKey() throws SvcLogicException,
+ IllegalStateException, IllegalArgumentException {
+ params = new HashMap<>();
+ params.put("Url", "test");
+ params.put("Port", "10");
+ params.put("SshKey", "test");
+ params.put("Cmd", "test");
+ params.put("ResponseType", "xml");
+ params.put("TestOut", "<modelVersion>4.0.0</modelVersion>");
+ params.put("ResponsePrefix", "test");
+ adapter.execWithStatusCheck(params, svcContext);
+ assertEquals("4.0.0", svcContext.getAttribute("test.modelVersion"));
+ }
+}
diff --git a/plugins/sshapi-call-node/provider/src/test/java/jtest/org/onap/ccsdk/sli/plugins/restapicall/TestXmlJsonUtil.java b/plugins/sshapi-call-node/provider/src/test/java/jtest/org/onap/ccsdk/sli/plugins/restapicall/TestXmlJsonUtil.java
new file mode 100644
index 000000000..33e0f24dd
--- /dev/null
+++ b/plugins/sshapi-call-node/provider/src/test/java/jtest/org/onap/ccsdk/sli/plugins/restapicall/TestXmlJsonUtil.java
@@ -0,0 +1,264 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Copyright (C) 2018 Samsung Electronics. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package jtest.org.onap.ccsdk.sli.plugins.restapicall;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.onap.ccsdk.sli.plugins.sshapicall.model.XmlJsonUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+public class TestXmlJsonUtil {
+
+ private static final Logger log = LoggerFactory.getLogger(TestXmlJsonUtil.class);
+
+ @Test
+ public void test() {
+ Map<String, String> mm = new HashMap<>();
+ mm.put("service-data.vnf-config-parameters-list.vnf-config-parameters[0].vnf-type", "N-SBG");
+ mm.put("service-data.service-information.service-instance-id", "someinstance001");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].dns-server-ip-address", "10.11.12.13");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].escf-domain-name", "hclab.atttest.com");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].snmp-target-v3_length", "2");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].snmp-target-v3[0].snmp-target-v3-id", "1");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].snmp-target-v3[0].snmp-target-ip-address", "127.0.0.1");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].snmp-target-v3[0].snmp-security-level", "NO_AUTH_NO_PRIV");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].snmp-target-v3[1].snmp-target-v3-id", "2");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].snmp-target-v3[1].snmp-target-ip-address", "192.168.1.8");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].snmp-target-v3[1].snmp-security-level", "NO_AUTH_NO_PRIV");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].dns-ip-address-1", "2001:1890:1001:2224::1");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].dns-ip-address-2", "2001:1890:1001:2424::1");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].diameter-rf-realm-name", "uvp.els-an.att.net");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].diameter-rf-peer-ip-address", "192.168.1.66");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].bgf-controller-ip-address", "192.168.1.186");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].bgf-control-link-name", "mg3/69@192.168.1.226");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].rf-interface-nexthop-ip-address", "10.111.108.150");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].rf-mated-pair-ip-address", "10.111.108.146");
+
+ mm.put("service-data.vnf-config-parameters-list.vnf-config-parameters[0].access-net-pcscf_length", "4");
+
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].access-net-pcscf[0].network-name", "UvpbUgnAccess1");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].access-net-pcscf[0].sip-pa-termination-ip-address", "10.111.108.146");
+
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].access-net-pcscf[1].network-name", "MIS");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].access-net-pcscf[1].proactive-transcoding-profile",
+ "trinity-transcodingProfile");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].access-net-pcscf[1].next-hop-ip-address", "10.111.108.158");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].access-net-pcscf[1].subnet-mask-length", "10.111.108.154");
+
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].access-net-pcscf[2].network-name", "AVPN1");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].access-net-pcscf[2].proactive-transcoding-profile",
+ "trinity-transcodingProfile");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].access-net-pcscf[2].next-hop-ip-address", "10.111.108.166");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].access-net-pcscf[2].subnet-mask-length", "10.111.108.162");
+
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].access-net-pcscf[3].network-name", "AVPN1");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].access-net-pcscf[3].proactive-transcoding-profile",
+ "trinity-transcodingProfile");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].access-net-pcscf[3].next-hop-ip-address", "10.129.108.166");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].access-net-pcscf[3].subnet-mask-length", "10.129.108.162");
+
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].core-net-pcscf_length", "1");
+
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].core-net-pcscf[0].network-name", "Core");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].core-net-pcscf[0].next-hop-ip-address", "10.111.108.142");
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].core-net-pcscf[0].sip-pa-termination-ip-address", "10.111.108.138");
+
+ mm.put("service-data.vnf-config-parameters-list." +
+ "vnf-config-parameters[0].mated-pair-fully-qualified-domain-name",
+ "mt1nj01sbg01pyl-mt1nj01sbg02pyl.ar1ga.uvp.els-an.att.net");
+
+ mm.put("service-data.appc-request-header.svc-request-id", "SOMESERVICEREQUEST123451000");
+ mm.put("service-data.vnf-config-information.vnf-host-ip-address", "192.168.13.151");
+ mm.put("service-data.vnf-config-information.vendor", "Netconf");
+
+ mm.put("service-data.vnf-config-information.escape-test",
+ "blah blah \"xxx&nnn<>\\'\"there>blah<&''\"\"123\\\\\\'''blah blah &");
+
+ String ss = XmlJsonUtil.getXml(mm, "service-data.vnf-config-parameters-list");
+ log.info(ss);
+
+ ss = XmlJsonUtil.getXml(mm, "service-data.vnf-config-information");
+ log.info(ss);
+
+ ss = XmlJsonUtil.getJson(mm, "service-data.vnf-config-parameters-list.vnf-config-parameters");
+ log.info(ss);
+
+ ss = XmlJsonUtil.getJson(mm, "service-data.vnf-config-information");
+ log.info(ss);
+
+ ss = XmlJsonUtil.getJson(mm, "service-data.vnf-config-information.vnf-host-ip-address");
+ log.info(ss);
+
+ ss = XmlJsonUtil.getJson(mm, "\"service-data.vnf-config-information.vnf-host-ip-address");
+ log.info(ss);
+ }
+
+ @Test
+ public void testRemoveEmptyStructXml() {
+ String xmlin = "" +
+ "<T1>\n" +
+ " <T2>\n" +
+ " <T3>\n" +
+ " <T4></T4>\n" +
+ " <T5> </T5>\n" +
+ " <T6>\n" +
+ " </T6>\n" +
+ " </T3>\n" +
+ " <T7>blah</T7>\n" +
+ " </T2>\n" +
+ " <T8>\n" +
+ " <T9>\n" +
+ " <T10></T10>\n" +
+ " <T11> </T11>\n" +
+ " <T12>\n" +
+ " </T12>\n" +
+ " </T9>\n" +
+ " <T13>\n" +
+ " <T14></T14>\n" +
+ " <T15> </T15>\n" +
+ " <T16>\n" +
+ " <T17></T17>\n" +
+ " </T16>\n" +
+ " </T13>\n" +
+ " <T17>\n" +
+ " </T17>\n" +
+ " </T8>\n" +
+ " <T18>blah blah</T18>\n" +
+ "</T1>\n";
+
+ String xmloutexpected = "" +
+ "<T1>\n" +
+ " <T2>\n" +
+ " <T7>blah</T7>\n" +
+ " </T2>\n" +
+ " <T18>blah blah</T18>\n" +
+ "</T1>\n";
+
+ String xmlout = XmlJsonUtil.removeEmptyStructXml(xmlin);
+ log.info(xmlout);
+
+ Assert.assertEquals(xmloutexpected, xmlout);
+ }
+
+ @Test
+ public void testRemoveEmptyStructJson() {
+ String xmlin = "{\r\n" +
+ " \"T1\":{\r\n" +
+ " \"T2\":{\r\n" +
+ " \"T3\":[\r\n" +
+ " \r\n" +
+ " ],\r\n" +
+ " \"T4\":{\r\n" +
+ " \"T12\":[\r\n" +
+ " \r\n" +
+ " ],\r\n" +
+ " \"T13\":[ ],\r\n" +
+ " \"T14\":{\r\n" +
+ " \"T15\":{\r\n" +
+ " \r\n" +
+ " },\r\n" +
+ " \"T16\":{\r\n" +
+ " \r\n" +
+ " }\r\n" +
+ " }\r\n" +
+ " },\r\n" +
+ " \"T5\":{\r\n" +
+ " \"T6\":[\r\n" +
+ " \r\n" +
+ " ],\r\n" +
+ " \"T7\":[\r\n" +
+ " \"T8\":{\r\n" +
+ " \r\n" +
+ " },\r\n" +
+ " \"T9\":{ },\r\n" +
+ " \"T10\":\"blah\",\r\n" +
+ " \"T11\":[\r\n" +
+ " \r\n" +
+ " ]\r\n" +
+ " ]\r\n" +
+ " }\r\n" +
+ " }\r\n" +
+ " }\r\n" +
+ "}\r\n" +
+ "";
+
+ String xmloutexpected = "{\r\n" +
+ " \"T1\":{\r\n" +
+ " \"T2\":{\r\n" +
+ " \"T5\":{\r\n" +
+ " \"T7\":[\r\n" +
+ " \"T10\":\"blah\",\r\n" +
+ " ]\r\n" +
+ " }\r\n" +
+ " }\r\n" +
+ " }\r\n" +
+ "}\r\n" +
+ "";
+
+ String xmlout = XmlJsonUtil.removeEmptyStructJson(xmlin);
+ log.info(xmlout);
+
+ Assert.assertEquals(xmloutexpected, xmlout);
+ }
+}
diff --git a/plugins/sshapi-call-node/provider/src/test/java/jtest/org/onap/ccsdk/sli/plugins/restapicall/TestXmlParser.java b/plugins/sshapi-call-node/provider/src/test/java/jtest/org/onap/ccsdk/sli/plugins/restapicall/TestXmlParser.java
new file mode 100644
index 000000000..ba0ae41de
--- /dev/null
+++ b/plugins/sshapi-call-node/provider/src/test/java/jtest/org/onap/ccsdk/sli/plugins/restapicall/TestXmlParser.java
@@ -0,0 +1,123 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * ================================================================================
+ * Copyright (C) 2018 Samsung Electronics. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package jtest.org.onap.ccsdk.sli.plugins.restapicall;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.Is.is;
+
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+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.junit.Test;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.plugins.sshapicall.model.XmlParser;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class TestXmlParser {
+
+ private static final Logger log = LoggerFactory.getLogger(TestXmlParser.class);
+
+ @Test
+ public void test() throws Exception {
+ BufferedReader in = new BufferedReader(
+ new InputStreamReader(ClassLoader.getSystemResourceAsStream("test3.xml"))
+ );
+ StringBuilder b = new StringBuilder();
+ String line;
+ while ((line = in.readLine()) != null)
+ b.append(line).append('\n');
+
+ Set<String> listNameList = new HashSet<String>();
+ listNameList.add("project.dependencies.dependency");
+ listNameList.add("project.build.plugins.plugin");
+ listNameList.add("project.build.plugins.plugin.executions.execution");
+ listNameList.add("project.build.pluginManagement.plugins.plugin");
+ listNameList.add("project.build.pluginManagement." +
+ "plugins.plugin.configuration.lifecycleMappingMetadata.pluginExecutions.pluginExecution");
+
+ Map<String, String> mm = XmlParser.convertToProperties(b.toString(), listNameList);
+ logProperties(mm);
+ in.close();
+ }
+
+ @Test
+ public void testValidLength() throws Exception {
+ BufferedReader in = new BufferedReader(
+ new InputStreamReader(ClassLoader.getSystemResourceAsStream("test3.xml"))
+ );
+ StringBuilder b = new StringBuilder();
+ String line;
+ while ((line = in.readLine()) != null)
+ b.append(line).append('\n');
+
+ Set<String> listNameList = new HashSet<String>();
+ listNameList.add("ApplyGroupResponse.ApplyGroupResponseData.VrfDetails.VrfImport");
+ listNameList.add("ApplyGroupResponse.ApplyGroupResponseData.VrfDetails.VrfExport");
+
+ Map<String, String> mm = XmlParser.convertToProperties(b.toString(), listNameList);
+
+ assertThat(mm.get("ApplyGroupResponse.ApplyGroupResponseData.VrfDetails.VrfExport[5]"), is("SET_RESET_LP"));
+ assertThat(mm.get("ApplyGroupResponse.ApplyGroupResponseData.VrfDetails.VrfImport[0]"), is("SET_BVOIP_IN"));
+
+ logProperties(mm);
+ in.close();
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void testInvalidLength() throws Exception {
+ BufferedReader in = new BufferedReader(
+ new InputStreamReader(ClassLoader.getSystemResourceAsStream("invalidlength.xml"))
+ );
+ StringBuilder b = new StringBuilder();
+ String line;
+ while ((line = in.readLine()) != null)
+ b.append(line).append('\n');
+
+ Set<String> listNameList = new HashSet<String>();
+ listNameList.add("ApplyGroupResponse.ApplyGroupResponseData.VrfDetails.VrfImport");
+ listNameList.add("ApplyGroupResponse.ApplyGroupResponseData.VrfDetails.VrfExport");
+
+ Map<String, String> mm = XmlParser.convertToProperties(b.toString(), listNameList);
+ logProperties(mm);
+ in.close();
+ }
+
+ private void logProperties(Map<String, String> mm) {
+ List<String> ll = new ArrayList<>();
+ for (Object o : mm.keySet())
+ ll.add((String) o);
+ Collections.sort(ll);
+
+ log.info("Properties:");
+ for (String name : ll)
+ log.info("--- " + name + ": " + mm.get(name));
+ }
+}
diff --git a/plugins/sshapi-call-node/provider/src/test/resources/invalidlength.xml b/plugins/sshapi-call-node/provider/src/test/resources/invalidlength.xml
new file mode 100644
index 000000000..b71f6391f
--- /dev/null
+++ b/plugins/sshapi-call-node/provider/src/test/resources/invalidlength.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!--
+ ============LICENSE_START=======================================================
+ openECOMP : SDN-C
+ ================================================================================
+ Copyright (C) 2018 Samsung Electronics. All rights
+ reserved.
+ ================================================================================
+ 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.
+ ============LICENSE_END=========================================================
+ -->
+
+<ApplyGroupResponse xmlns="http://onap.org/vpn/schema/v1"
+ xmlns:ns2="http://onap.org/prov/vpn/schema/v2">
+ <ApplyGroupResponseData>
+ <ServiceInstanceId>ICOREPVC-81114561</ServiceInstanceId>
+ <VrfDetails>
+ <End2EndVpnKey>VPNL811182</End2EndVpnKey>
+ <VpnId>811182</VpnId>
+ <VrfName>21302:811182</VrfName>
+ <VrfImport>SET_BVOIP_IN</VrfImport>
+ <VrfImport>SET6_BVOIP_IN</VrfImport>
+ <VrfExport_length>a</VrfExport_length>
+ <VrfExport>SET6_DSU</VrfExport>
+ <VrfExport>SET_DSU</VrfExport>
+ <VrfExport>SET6_MANAGED</VrfExport>
+ <VrfExport>SET_MANAGED</VrfExport>
+ <VrfExport>SET_LOVRF_COMMUNITY</VrfExport>
+ <VrfExport>SET_RESET_LP</VrfExport>
+ <ApplyGroup>
+ <ns2:ApplyGroup>AG_MAX_MCASTROUTES</ns2:ApplyGroup>
+ </ApplyGroup>
+ </VrfDetails>
+ </ApplyGroupResponseData>
+ <response-code>200</response-code>
+ <response-message>Success</response-message>
+ <ack-final-indicator>Y</ack-final-indicator>
+</ApplyGroupResponse>
+
diff --git a/plugins/sshapi-call-node/provider/src/test/resources/test-template.json b/plugins/sshapi-call-node/provider/src/test/resources/test-template.json
new file mode 100644
index 000000000..cd5e74699
--- /dev/null
+++ b/plugins/sshapi-call-node/provider/src/test/resources/test-template.json
@@ -0,0 +1,57 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2018 Samsung Electronics. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+{
+ "sdn-circuit-request": [
+ ${repeat:tmp.sdn-circuit-req-row_length:
+ {
+ "request-id": ${tmp.sdn-circuit-req-row[${1}].request-id},
+ "source-uid": ${tmp.sdn-circuit-req-row[${1}].source-uid},
+ "action": ${tmp.sdn-circuit-req-row[${1}].action},
+ "request-timestamp": ${tmp.sdn-circuit-req-row[${1}].request-timestamp},
+ "update-timestamp": ${tmp.sdn-circuit-req-row[${1}].update-timestamp},
+ "request-status": ${tmp.sdn-circuit-req-row[${1}].request-status},
+ "processing-status": ${tmp.sdn-circuit-req-row[${1}].processing-status},
+ "reason-code": ${tmp.sdn-circuit-req-row[${1}].reason-code},
+ "reason-message": ${tmp.sdn-circuit-req-row[${1}].reason-message},
+ "customer-code": ${tmp.sdn-circuit-req-row[${1}].customer-code},
+ "bundle-id": ${tmp.sdn-circuit-req-row[${1}].bundle-id},
+ "router-name-1": ${tmp.sdn-circuit-req-row[${1}].router-name-1},
+ "tail-clfi-1": ${tmp.sdn-circuit-req-row[${1}].tail-clfi-1},
+ "srg-1": ${tmp.sdn-circuit-req-row[${1}].srg-1},
+ "router-name-2": ${tmp.sdn-circuit-req-row[${1}].router-name-2},
+ "tail-clfi-2": ${tmp.sdn-circuit-req-row[${1}].tail-clfi-2},
+ "srg-2": ${tmp.sdn-circuit-req-row[${1}].srg-2},
+ "facility-speed": ${tmp.sdn-circuit-req-row[${1}].facility-speed},
+ "facility-speed-units": ${tmp.sdn-circuit-req-row[${1}].facility-speed-units},
+ "facility-type": ${tmp.sdn-circuit-req-row[${1}].facility-type},
+ "service-clfi": ${tmp.sdn-circuit-req-row[${1}].service-clfi},
+ "clci": ${tmp.sdn-circuit-req-row[${1}].clci},
+ "wavelength-purpose": ${tmp.sdn-circuit-req-row[${1}].wavelength-purpose},
+ "activate-setting": ${tmp.sdn-circuit-req-row[${1}].activate-setting},
+ "apply-date": ${tmp.sdn-circuit-req-row[${1}].apply-date},
+ "run-id": ${tmp.sdn-circuit-req-row[${1}].run-id},
+ "hostname": ${tmp.sdn-circuit-req-row[${1}].hostname},
+ "algo-request-reason": ${tmp.sdn-circuit-req-row[${1}].algo-request-reason}
+ },
+ }
+ ]
+}
diff --git a/plugins/sshapi-call-node/provider/src/test/resources/test.json b/plugins/sshapi-call-node/provider/src/test/resources/test.json
new file mode 100644
index 000000000..e272d457a
--- /dev/null
+++ b/plugins/sshapi-call-node/provider/src/test/resources/test.json
@@ -0,0 +1,51 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2018 Samsung Electronics. All rights
+ * reserved.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+{
+ "equipment-data": [
+ {
+ "server-count": "4",
+ "max-server-speed": "1600000",
+ "number-primary-servers": "2",
+ "equipment-id": "Server1",
+ "server-model": "Unknown",
+ "server-id": "Server1",
+ "test-node" : {
+ "test-inner-node" : "Test-Value"
+ }
+ }
+ ],
+ "resource-state": {
+ "threshold-value": "1600000",
+ "last-added": "1605000",
+ "used": "1605000",
+ "limit-value": "1920000"
+ },
+ "resource-rule": {
+ "endpoint-position": "VCE-Cust",
+ "soft-limit-expression": "0.6 * max-server-speed * number-primary-servers",
+ "resource-name": "Bandwidth",
+ "service-model": "DUMMY",
+ "hard-limit-expression": "max-server-speed * number-primary-servers",
+ "equipment-level": "Server"
+ },
+ "message": "The provisioned access bandwidth is at or exceeds 50% of the total server capacity."
+}
diff --git a/plugins/sshapi-call-node/provider/src/test/resources/test.xml b/plugins/sshapi-call-node/provider/src/test/resources/test.xml
new file mode 100644
index 000000000..7645f1992
--- /dev/null
+++ b/plugins/sshapi-call-node/provider/src/test/resources/test.xml
@@ -0,0 +1,184 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ============LICENSE_START=======================================================
+ openECOMP : SDN-C
+ ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property.
+ * ================================================================================
+ * Copyright (C) 2018 Samsung Electronics. All rights
+ reserved.
+ ================================================================================
+ 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.
+ ============LICENSE_END=========================================================
+ -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.onap.ccsdk.sli.plugins</groupId>
+ <artifactId>sshapi-call-node</artifactId>
+ <version>6.0.0-SNAPSHOT</version>
+ </parent>
+ <artifactId>sshapi-call-node-provider</artifactId>
+ <packaging>bundle</packaging>
+ <name>SSHAPI Call Node - Provider</name>
+ <url>http://maven.apache.org</url>
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-test</artifactId>
+ <version>3.1.4.RELEASE</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli</groupId>
+ <artifactId>sli-common</artifactId>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli</groupId>
+ <artifactId>sli-provider</artifactId>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ <version>${slf4j.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>jcl-over-slf4j</artifactId>
+ <version>${slf4j.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-beans</artifactId>
+ <version>3.1.4.RELEASE</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-context</artifactId>
+ <version>3.1.4.RELEASE</version>
+ </dependency>
+ <dependency>
+ <groupId>xerces</groupId>
+ <artifactId>xerces</artifactId>
+ <version>2.4.0</version>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.sun.jersey</groupId>
+ <artifactId>jersey-client</artifactId>
+ <version>1.17</version>
+ </dependency>
+ <dependency>
+ <groupId>com.sun.jersey.contribs.jersey-oauth</groupId>
+ <artifactId>oauth-signature</artifactId>
+ <version>1.17</version>
+ </dependency>
+ <dependency>
+ <groupId>com.sun.jersey.contribs.jersey-oauth</groupId>
+ <artifactId>oauth-client</artifactId>
+ <version>1.17</version>
+ </dependency>
+ <dependency>
+ <groupId>commons-codec</groupId>
+ <artifactId>commons-codec</artifactId>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>com.brocade.developer</groupId>
+ <artifactId>providermodule-plugin</artifactId>
+ <configuration>
+ <packageId>org.onap.ccsdk.sli.plugins</packageId>
+ <appName>sshapi-call-node</appName>
+ </configuration>
+ <executions>
+ <execution>
+ <phase>process-sources</phase>
+ <goals>
+ <goal>process</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+
+
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <extensions>true</extensions>
+ <configuration>
+ <instructions>
+ <Bundle-SymbolicName>org.onap.ccsdk.sli.plugins.sshapicall</Bundle-SymbolicName>
+ <Export-Package>org.onap.ccsdk.sli.plugins.sshapicall</Export-Package>
+ <Import-Package>*</Import-Package>
+ </instructions>
+
+ <manifestLocation>${project.basedir}/src/main/resources/META-INF</manifestLocation>
+
+ </configuration>
+
+ </plugin>
+
+
+ </plugins>
+ <pluginManagement>
+ <plugins>
+ <!--This plugin's configuration is used to store Eclipse m2e settings
+ only. It has no influence on the Maven build itself. -->
+ <plugin>
+ <groupId>org.eclipse.m2e</groupId>
+ <artifactId>lifecycle-mapping</artifactId>
+ <version>1.0.0</version>
+ <configuration>
+ <lifecycleMappingMetadata>
+ <pluginExecutions>
+ <pluginExecution>
+ <pluginExecutionFilter>
+ <groupId>
+ com.brocade.developer
+ </groupId>
+ <artifactId>
+ providermodule-plugin
+ </artifactId>
+ <versionRange>
+ [1.2.0.100-SNAPSHOT,)
+ </versionRange>
+ <goals>
+ <goal>process</goal>
+ </goals>
+ </pluginExecutionFilter>
+ <action>
+ <ignore />
+ </action>
+ </pluginExecution>
+ </pluginExecutions>
+ </lifecycleMappingMetadata>
+ </configuration>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+</project>
diff --git a/plugins/sshapi-call-node/provider/src/test/resources/test3.xml b/plugins/sshapi-call-node/provider/src/test/resources/test3.xml
new file mode 100644
index 000000000..52a7a7d98
--- /dev/null
+++ b/plugins/sshapi-call-node/provider/src/test/resources/test3.xml
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!--
+ ============LICENSE_START=======================================================
+ openECOMP : SDN-C
+ ================================================================================
+ Copyright (C) 2018 Samsung Electronics. All rights
+ reserved.
+ ================================================================================
+ 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.
+ ============LICENSE_END=========================================================
+ -->
+
+<ApplyGroupResponse xmlns="http://onap.org/vpn/schema/v1"
+ xmlns:ns2="http://onap.org/prov/vpn/schema/v2">
+ <ApplyGroupResponseData>
+ <ServiceInstanceId>ICOREPVC-81114561</ServiceInstanceId>
+ <VrfDetails>
+ <End2EndVpnKey>VPNL811182</End2EndVpnKey>
+ <VpnId>811182</VpnId>
+ <VrfName>21302:811182</VrfName>
+ <VrfImport>SET_BVOIP_IN</VrfImport>
+ <VrfImport>SET6_BVOIP_IN</VrfImport>
+ <VrfExport>SET6_DSU</VrfExport>
+ <VrfExport>SET_DSU</VrfExport>
+ <VrfExport>SET6_MANAGED</VrfExport>
+ <VrfExport>SET_MANAGED</VrfExport>
+ <VrfExport>SET_LOVRF_COMMUNITY</VrfExport>
+ <VrfExport>SET_RESET_LP</VrfExport>
+ <ApplyGroup>
+ <ns2:ApplyGroup>AG_MAX_MCASTROUTES</ns2:ApplyGroup>
+ </ApplyGroup>
+ </VrfDetails>
+ <RoutingApplyGroups>
+ <RoutingProtocol>BGP4_PROTOCOL</RoutingProtocol>
+ <Family>v4</Family>
+ <PeerGroupName>gp_21302:811182</PeerGroupName>
+ <ApplyGroupPeer>
+ <ns2:ApplyGroup>AG_L3VPN_EBGP</ns2:ApplyGroup>
+ </ApplyGroupPeer>
+ <ApplyGroupPeer>
+ <ns2:ApplyGroup>AG_MAX_PREFIX</ns2:ApplyGroup>
+ </ApplyGroupPeer>
+ <ApplyGroupNeighbour>
+ <ns2:ApplyGroup>AG_BGP_UNMANAGED</ns2:ApplyGroup>
+ </ApplyGroupNeighbour>
+ <ApplyGroupNeighbour>
+ <ns2:ApplyGroup>AG_BFD_BGP_3000</ns2:ApplyGroup>
+ </ApplyGroupNeighbour>
+ </RoutingApplyGroups>
+ <RoutingApplyGroups>
+ <RoutingProtocol>BGP4_PROTOCOL</RoutingProtocol>
+ <Family>v6</Family>
+ <PeerGroupName>gp6_21302:811182</PeerGroupName>
+ <ApplyGroupPeer>
+ <ns2:ApplyGroup>AG6_L3VPN_EBGP</ns2:ApplyGroup>
+ </ApplyGroupPeer>
+ <ApplyGroupPeer>
+ <ns2:ApplyGroup>AG6_MAX_PREFIX</ns2:ApplyGroup>
+ </ApplyGroupPeer>
+ <ApplyGroupNeighbour>
+ <ns2:ApplyGroup>AG6_BGP_UNMANAGED</ns2:ApplyGroup>
+ </ApplyGroupNeighbour>
+ <ApplyGroupNeighbour>
+ <ns2:ApplyGroup>AG6_BFD_BGP_3000</ns2:ApplyGroup>
+ </ApplyGroupNeighbour>
+ </RoutingApplyGroups>
+ </ApplyGroupResponseData>
+ <response-code>200</response-code>
+ <response-message>Success</response-message>
+ <ack-final-indicator>Y</ack-final-indicator>
+</ApplyGroupResponse>
+
diff --git a/plugins/template-node/installer/pom.xml b/plugins/template-node/installer/pom.xml
new file mode 100644
index 000000000..c6ed6312f
--- /dev/null
+++ b/plugins/template-node/installer/pom.xml
@@ -0,0 +1,125 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>odlparent-lite</artifactId>
+ <version>2.1.0</version>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.plugins</groupId>
+ <artifactId>template-node-installer</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>pom</packaging>
+
+ <name>ccsdk-sli-plugins :: template-node :: ${project.artifactId}</name>
+
+ <properties>
+ <application.name>ccsdk-template-node</application.name>
+ <features.boot>${application.name}</features.boot>
+ <features.repositories>mvn:org.onap.ccsdk.sli.plugins/${features.boot}/${project.version}/xml/features</features.repositories>
+ <include.transitive.dependencies>false</include.transitive.dependencies>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.plugins</groupId>
+ <artifactId>template-node-provider</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <version>2.6</version>
+ <executions>
+ <execution>
+ <id>maven-repo-zip</id>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ <phase>package</phase>
+ <configuration>
+ <attach>true</attach>
+ <finalName>stage/${application.name}-${project.version}</finalName>
+ <descriptors>
+ <descriptor>src/assembly/assemble_mvnrepo_zip.xml</descriptor>
+ </descriptors>
+ <appendAssemblyId>true</appendAssemblyId>
+ </configuration>
+ </execution>
+ <execution>
+ <id>installer-zip</id>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ <phase>package</phase>
+ <configuration>
+ <attach>true</attach>
+ <finalName>${application.name}-${project.version}-installer</finalName>
+ <descriptors>
+ <descriptor>src/assembly/assemble_installer_zip.xml</descriptor>
+ </descriptors>
+ <appendAssemblyId>false</appendAssemblyId>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>copy-dependencies</id>
+ <goals>
+ <goal>copy-dependencies</goal>
+ </goals>
+ <phase>prepare-package</phase>
+ <configuration>
+ <transitive>false</transitive>
+ <outputDirectory>${project.build.directory}/assembly/system</outputDirectory>
+ <overWriteReleases>false</overWriteReleases>
+ <overWriteSnapshots>true</overWriteSnapshots>
+ <overWriteIfNewer>true</overWriteIfNewer>
+ <useRepositoryLayout>true</useRepositoryLayout>
+ <addParentPoms>false</addParentPoms>
+ <copyPom>false</copyPom>
+ <includeGroupIds>org.onap.ccsdk.sli.plugins</includeGroupIds>
+ <scope>provided</scope>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <artifactId>maven-resources-plugin</artifactId>
+ <version>2.6</version>
+ <executions>
+ <execution>
+ <id>copy-version</id>
+ <goals>
+ <goal>copy-resources</goal>
+ </goals><!-- here the phase you need -->
+ <phase>validate</phase>
+ <configuration>
+ <outputDirectory>${basedir}/target/stage</outputDirectory>
+ <resources>
+ <resource>
+ <directory>src/main/resources/scripts</directory>
+ <includes>
+ <include>install-feature.sh</include>
+ </includes>
+ <filtering>true</filtering>
+ </resource>
+ </resources>
+ </configuration>
+ </execution>
+
+ </executions>
+ </plugin>
+
+ </plugins>
+ </build>
+</project>
diff --git a/plugins/template-node/installer/src/assembly/assemble_installer_zip.xml b/plugins/template-node/installer/src/assembly/assemble_installer_zip.xml
new file mode 100644
index 000000000..d7a0a630d
--- /dev/null
+++ b/plugins/template-node/installer/src/assembly/assemble_installer_zip.xml
@@ -0,0 +1,58 @@
+<!--
+ ============LICENSE_START=======================================================
+ openECOMP : SDN-C
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property. All rights
+ reserved.
+ ================================================================================
+ 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.
+ ============LICENSE_END=========================================================
+ -->
+
+<!-- Defines how we build the .zip file which is our distribution. -->
+
+<assembly
+ xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
+ <id>installer_zip</id>
+ <formats>
+ <format>zip</format>
+ </formats>
+
+ <!-- we want "system" and related files right at the root level as this
+ file is suppose to be unzip on top of a karaf distro. -->
+ <includeBaseDirectory>false</includeBaseDirectory>
+
+ <fileSets>
+ <fileSet>
+ <directory>target/stage/</directory>
+ <outputDirectory>${application.name}</outputDirectory>
+ <fileMode>755</fileMode>
+ <includes>
+ <include>*.sh</include>
+ </includes>
+ </fileSet>
+ <fileSet>
+ <directory>target/stage/</directory>
+ <outputDirectory>${application.name}</outputDirectory>
+ <fileMode>644</fileMode>
+ <excludes>
+ <exclude>*.sh</exclude>
+ </excludes>
+ </fileSet>
+ </fileSets>
+
+
+
+</assembly>
diff --git a/plugins/template-node/installer/src/assembly/assemble_mvnrepo_zip.xml b/plugins/template-node/installer/src/assembly/assemble_mvnrepo_zip.xml
new file mode 100644
index 000000000..7500304e8
--- /dev/null
+++ b/plugins/template-node/installer/src/assembly/assemble_mvnrepo_zip.xml
@@ -0,0 +1,48 @@
+<!--
+ ============LICENSE_START=======================================================
+ openECOMP : SDN-C
+ ================================================================================
+ Copyright (C) 2017 AT&T Intellectual Property. All rights
+ reserved.
+ ================================================================================
+ 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.
+ ============LICENSE_END=========================================================
+ -->
+
+<!-- Defines how we build the .zip file which is our distribution. -->
+
+<assembly
+ xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
+ <id>repo</id>
+ <formats>
+ <format>zip</format>
+ </formats>
+
+ <!-- we want "system" and related files right at the root level as this
+ file is suppose to be unzip on top of a karaf distro. -->
+ <includeBaseDirectory>false</includeBaseDirectory>
+
+ <fileSets>
+ <fileSet>
+ <directory>target/assembly/</directory>
+ <outputDirectory>.</outputDirectory>
+ <excludes>
+ </excludes>
+ </fileSet>
+ </fileSets>
+
+
+
+</assembly>
diff --git a/plugins/template-node/installer/src/main/resources/scripts/install-feature.sh b/plugins/template-node/installer/src/main/resources/scripts/install-feature.sh
new file mode 100644
index 000000000..98276a7e0
--- /dev/null
+++ b/plugins/template-node/installer/src/main/resources/scripts/install-feature.sh
@@ -0,0 +1,39 @@
+#!/bin/bash
+
+###
+# ============LICENSE_START=======================================================
+# openECOMP : SDN-C
+# ================================================================================
+# Copyright (C) 2017 AT&T Intellectual Property. All rights
+# reserved.
+# ================================================================================
+# 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.
+# ============LICENSE_END=========================================================
+###
+
+ODL_HOME=${ODL_HOME:-/opt/opendaylight/current}
+ODL_KARAF_CLIENT=${ODL_KARAF_CLIENT:-${ODL_HOME}/bin/client}
+INSTALLERDIR=$(dirname $0)
+
+REPOZIP=${INSTALLERDIR}/${features.boot}-${project.version}.zip
+
+if [ -f ${REPOZIP} ]
+then
+ unzip -nd ${ODL_HOME} ${REPOZIP}
+else
+ echo "ERROR : repo zip ($REPOZIP) not found"
+ exit 1
+fi
+
+${ODL_KARAF_CLIENT} feature:repo-add ${features.repositories}
+${ODL_KARAF_CLIENT} feature:install ${features.boot}
diff --git a/plugins/template-node/pom.xml b/plugins/template-node/pom.xml
new file mode 100644
index 000000000..615c5d348
--- /dev/null
+++ b/plugins/template-node/pom.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>odlparent-lite</artifactId>
+ <version>2.1.0</version>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.plugins</groupId>
+ <artifactId>template-node</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>pom</packaging>
+
+ <modules>
+ <module>provider</module>
+ <module>installer</module>
+ </modules>
+</project>
diff --git a/plugins/template-node/provider/pom.xml b/plugins/template-node/provider/pom.xml
new file mode 100644
index 000000000..d7bc54fc6
--- /dev/null
+++ b/plugins/template-node/provider/pom.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>binding-parent</artifactId>
+ <version>2.1.0</version>
+ </parent>
+
+ <groupId>org.onap.ccsdk.sli.plugins</groupId>
+ <artifactId>template-node-provider</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>bundle</packaging>
+
+ <name>ccsdk-sli-plugins :: template-node :: ${project.artifactId}</name>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sli-core-artifacts</artifactId>
+ <version>${ccsdk.sli.core.version}</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.onap.ccsdk.sli.core</groupId>
+ <artifactId>sli-common</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.velocity</groupId>
+ <artifactId>velocity</artifactId>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/plugins/template-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/template/TemplateNode.java b/plugins/template-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/template/TemplateNode.java
new file mode 100755
index 000000000..005b62067
--- /dev/null
+++ b/plugins/template-node/provider/src/main/java/org/onap/ccsdk/sli/plugins/template/TemplateNode.java
@@ -0,0 +1,114 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * openECOMP : SDN-C
+ * ================================================================================
+ * Copyright (C) 2017 AT&T Intellectual Property. All rights
+ * reserved.
+ * Modifications Copyright © 2018 IBM.
+ * ================================================================================
+ * 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.
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.ccsdk.sli.plugins.template;
+
+import java.io.FileInputStream;
+import java.io.StringWriter;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Properties;
+import org.apache.velocity.Template;
+import org.apache.velocity.VelocityContext;
+import org.apache.velocity.app.VelocityEngine;
+import org.apache.velocity.runtime.RuntimeConstants;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+import org.onap.ccsdk.sli.core.sli.SvcLogicJavaPlugin;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class TemplateNode implements SvcLogicJavaPlugin {
+ private static final Logger logger = LoggerFactory.getLogger(TemplateNode.class);
+ public static final String TEMPLATE_PATH = "templatePath";
+ public static final String OUTPUT_PATH_KEY = "output";
+ public static final String PREFIX_KEY = "prefix";
+ public static final String REQUIRED_PARAMETERS_ERROR_MESSAGE = "templateName & outputPath are required fields";
+ protected static final String TEMPLATE_PROPERTIES_FILE_NAME = "template-node.properties";
+ protected static final String DEFAULT_PROPERTIES_DIR = "/opt/onap/ccsdk/data/properties";
+ protected static final String PROPERTIES_DIR_KEY = "SDNC_CONFIG_DIR";
+
+ protected VelocityEngine ve;
+
+ public TemplateNode() {
+ ve = new VelocityEngine();
+ setProperties();
+ ve.init();
+ }
+
+ protected void setProperties() {
+ String configDir = System.getProperty(PROPERTIES_DIR_KEY, DEFAULT_PROPERTIES_DIR);
+ Properties props = new Properties();
+
+ try (FileInputStream in = new FileInputStream(configDir + "/" + TEMPLATE_PROPERTIES_FILE_NAME)) {
+ props.load(in);
+ } catch (Exception e) {
+ logger.warn("Properties not loaded for template node, using sensible defaults. " + e.getMessage());
+ }
+
+ // give sensible defaults for required properties
+ ve.setProperty(RuntimeConstants.RESOURCE_LOADER, props.getProperty("velocity.resource.loader", "file"));
+ ve.setProperty(RuntimeConstants.FILE_RESOURCE_LOADER_PATH,
+ props.getProperty("velocity.file.resource.loader.path", "/opt/onap/sdnc/restapi/templates"));
+ ve.setProperty(RuntimeConstants.FILE_RESOURCE_LOADER_CACHE,
+ props.getProperty("velocity.file.resource.loader.cache", "false"));
+
+ // allow flexible reading of additional velocity properties
+ for (String propertyName : props.stringPropertyNames()) {
+ if (propertyName.startsWith("velocity")) {
+ logger.error("set " + propertyName.substring(9) + "=" + props.get(propertyName));
+ ve.setProperty(propertyName.substring(9), props.get(propertyName));
+ }
+ }
+ }
+
+ public void evaluateTemplate(Map<String, String> params, SvcLogicContext ctx) throws SvcLogicException {
+ String templateName = params.get(TEMPLATE_PATH);
+ String outputPath = params.get(OUTPUT_PATH_KEY);
+ String prefix = params.get(PREFIX_KEY);
+
+ if (prefix != null && prefix.length() > 0) {
+ outputPath = prefix + "." + outputPath;
+ }
+
+ if (templateName == null || outputPath == null) {
+ throw new SvcLogicException(REQUIRED_PARAMETERS_ERROR_MESSAGE);
+ } else {
+ try {
+ Template template = ve.getTemplate(templateName);
+ VelocityContext context = new VelocityContext();
+ context.put("ctx", ctx);
+ context.put("params", params);
+ //Adding these values directly to context makes working with the values cleaner
+ for (Entry<String, String> entry : params.entrySet()) {
+ context.put(entry.getKey(), entry.getValue());
+ }
+ StringWriter sw = new StringWriter();
+ template.merge(context, sw);
+ ctx.setAttribute(outputPath, sw.toString());
+ } catch (Exception e) {
+ throw new SvcLogicException(e.getMessage());
+ }
+ }
+ }
+
+}
diff --git a/plugins/template-node/provider/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/plugins/template-node/provider/src/main/resources/OSGI-INF/blueprint/blueprint.xml
new file mode 100644
index 000000000..60409c504
--- /dev/null
+++ b/plugins/template-node/provider/src/main/resources/OSGI-INF/blueprint/blueprint.xml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
+
+ <bean id="templateNode"
+ class="org.onap.ccsdk.sli.plugins.template.TemplateNode" />
+
+ <service id="templateNodeService" ref="templateNode"
+ interface="org.onap.ccsdk.sli.plugins.template.TemplateNode" />
+
+</blueprint> \ No newline at end of file
diff --git a/plugins/template-node/provider/src/test/java/org/onap/ccsdk/sli/plugins/template/MockTemplateNode.java b/plugins/template-node/provider/src/test/java/org/onap/ccsdk/sli/plugins/template/MockTemplateNode.java
new file mode 100644
index 000000000..d628ac929
--- /dev/null
+++ b/plugins/template-node/provider/src/test/java/org/onap/ccsdk/sli/plugins/template/MockTemplateNode.java
@@ -0,0 +1,7 @@
+package org.onap.ccsdk.sli.plugins.template;
+
+public class MockTemplateNode extends TemplateNode {
+ protected void setProperties() {
+ // do nothing
+ }
+}
diff --git a/plugins/template-node/provider/src/test/java/org/onap/ccsdk/sli/plugins/template/TemplateNodeTest.java b/plugins/template-node/provider/src/test/java/org/onap/ccsdk/sli/plugins/template/TemplateNodeTest.java
new file mode 100644
index 000000000..29c5c973e
--- /dev/null
+++ b/plugins/template-node/provider/src/test/java/org/onap/ccsdk/sli/plugins/template/TemplateNodeTest.java
@@ -0,0 +1,85 @@
+package org.onap.ccsdk.sli.plugins.template;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Vector;
+import org.apache.velocity.runtime.RuntimeConstants;
+import org.junit.Test;
+import org.onap.ccsdk.sli.core.sli.SvcLogicContext;
+import org.onap.ccsdk.sli.core.sli.SvcLogicException;
+
+public class TemplateNodeTest {
+
+ @Test
+ public void sunnyDay() throws Exception {
+ String requestId = "REQ001";
+ String uniqueKey = "UNIQUE_TEST";
+ String action = "uPdaTe";
+ String serviceType = "VPN";
+
+ TemplateNode t = new MockTemplateNode();
+
+ Map<String, String> params = new HashMap<String, String>();
+ params.put(TemplateNode.PREFIX_KEY, "output");
+ params.put(TemplateNode.OUTPUT_PATH_KEY, "mycontainer");
+ params.put(TemplateNode.TEMPLATE_PATH, "src/test/resources/basic.vtl");
+ params.put("service-type", serviceType);
+ SvcLogicContext ctx = new SvcLogicContext();
+ ctx.setAttribute("input.svc-request-id", requestId);
+ ctx.setAttribute("input.unique-key", uniqueKey);
+ ctx.setAttribute("action", action);
+
+ t.evaluateTemplate(params, ctx);
+ String result = ctx.getAttribute("output.mycontainer");
+ assertNotNull(result);
+ assertTrue(result.contains(requestId));
+ assertTrue(result.contains(uniqueKey));
+ assertTrue(result.contains(action.toUpperCase()));
+ assertTrue(result.contains(serviceType));
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void parameterException() throws Exception {
+ TemplateNode t = new MockTemplateNode();
+ Map<String, String> params = new HashMap<String, String>();
+ SvcLogicContext ctx = new SvcLogicContext();
+ t.evaluateTemplate(params, ctx);
+ }
+
+ @Test(expected = SvcLogicException.class)
+ public void missingTemplate() throws Exception {
+ TemplateNode t = new MockTemplateNode();
+ Map<String, String> params = new HashMap<String, String>();
+ params.put(TemplateNode.PREFIX_KEY, "output");
+ params.put(TemplateNode.OUTPUT_PATH_KEY, "mycontainer");
+ params.put(TemplateNode.TEMPLATE_PATH, "src/test/resources/missing.vtl");
+ SvcLogicContext ctx = new SvcLogicContext();
+ t.evaluateTemplate(params, ctx);
+ }
+
+ @Test
+ public void withProperties() throws Exception {
+ System.setProperty(TemplateNode.PROPERTIES_DIR_KEY, "src/test/resources");
+ TemplateNode t = new TemplateNode();
+ Vector<String> loader = (Vector<String>) t.ve.getProperty(RuntimeConstants.RESOURCE_LOADER);
+ assertTrue(loader.contains("class"));
+ assertEquals("/home/my/example", t.ve.getProperty(RuntimeConstants.FILE_RESOURCE_LOADER_PATH));
+ assertEquals("true", t.ve.getProperty(RuntimeConstants.FILE_RESOURCE_LOADER_CACHE));
+ assertEquals("customValue", t.ve.getProperty("custom.property"));
+ }
+
+ @Test
+ public void withNoProperties() throws Exception {
+ System.setProperty(TemplateNode.PROPERTIES_DIR_KEY, "i/do/not/exist");
+ TemplateNode t = new TemplateNode();
+ Vector<String> loader = (Vector<String>) t.ve.getProperty(RuntimeConstants.RESOURCE_LOADER);
+ assertTrue(loader.contains("file"));
+ assertEquals("/opt/onap/sdnc/restapi/templates", t.ve.getProperty(RuntimeConstants.FILE_RESOURCE_LOADER_PATH));
+ assertEquals("false", t.ve.getProperty(RuntimeConstants.FILE_RESOURCE_LOADER_CACHE));
+ assertEquals(null, t.ve.getProperty("custom.property"));
+ }
+
+} \ No newline at end of file
diff --git a/plugins/template-node/provider/src/test/resources/basic.vtl b/plugins/template-node/provider/src/test/resources/basic.vtl
new file mode 100644
index 000000000..63fcc670a
--- /dev/null
+++ b/plugins/template-node/provider/src/test/resources/basic.vtl
@@ -0,0 +1,12 @@
+{
+ "input": {
+ "sdnc-request-header": {
+ "svc-request-id": "$ctx.getAttribute("input.svc-request-id")",
+ "svc-action": "$ctx.getAttribute("action").toUpperCase()"
+ },
+ "service-information": {
+ "service-type": "$params.get("service-type")",
+ "service-instance-id": "$ctx.getAttribute("input.unique-key")"
+ }
+ }
+} \ No newline at end of file
diff --git a/plugins/template-node/provider/src/test/resources/template-node.properties b/plugins/template-node/provider/src/test/resources/template-node.properties
new file mode 100644
index 000000000..1199a0cde
--- /dev/null
+++ b/plugins/template-node/provider/src/test/resources/template-node.properties
@@ -0,0 +1,4 @@
+velocity.resource.loader=class
+velocity.file.resource.loader.path=/home/my/example
+velocity.file.resource.loader.cache=true
+velocity.custom.property=customValue \ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 8943a216b..1c9b9c80d 100644..100755
--- a/pom.xml
+++ b/pom.xml
@@ -1,146 +1,123 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <modelVersion>4.0.0</modelVersion>
+ <modelVersion>4.0.0</modelVersion>
- <parent>
- <groupId>org.onap.ccsdk.parent</groupId>
- <artifactId>odlparent-lite</artifactId>
- <version>2.1.0</version>
- </parent>
+ <parent>
+ <groupId>org.onap.ccsdk.parent</groupId>
+ <artifactId>oparent</artifactId>
+ <version>2.1.0-SNAPSHOT</version>
+ <relativePath/>
+ </parent>
- <groupId>org.onap.ccsdk.sli.northbound</groupId>
- <artifactId>ccsdk-sli-northbound</artifactId>
- <version>1.1.1-SNAPSHOT</version>
- <packaging>pom</packaging>
+ <groupId>org.onap.ccsdk.sli</groupId>
+ <artifactId>ccsdk-sli</artifactId>
+ <version>1.1.1-SNAPSHOT</version>
+ <packaging>pom</packaging>
- <name>ccsdk-sli-northbound</name>
- <description>The SDN-C Northbound APIs repo contains code for northbound API adaptors, typically MD-SAL applications</description>
- <url>https://wiki.onap.org</url>
- <organization>
- <name>ONAP</name>
- </organization>
+ <name>ccsdk-sli</name>
+ <description>Service Logic Interpreter</description>
+ <url>https://wiki.onap.org</url>
+ <organization>
+ <name>ONAP</name>
+ </organization>
- <modules>
- <module>asdcApi</module>
- <module>dataChange</module>
- <module>lcm</module>
- <module>dmaap-listener</module>
- <module>ueb-listener</module>
- <module>daexim-offsite-backup</module>
- <module>features</module>
- <module>artifacts</module>
- </modules>
+ <modules>
+ </modules>
- <scm>
- <connection>scm:git:ssh://git@${onap.git.host}/sdnc-northbound.git</connection>
+ <scm>
+ <connection>scm:git:ssh://git@${onap.git.host}/sdnc-code.git</connection>
+ <developerConnection>scm:git:ssh://${onap.git.host}:${onap.git.port}/${onap.git.project}/sli.git</developerConnection>
+ <url>${onap.git.protocol}://${onap.git.host}/projects/${onap.git.project}/repos/sli/browse</url>
+ <tag>sli-1.1.0</tag>
+ </scm>
+ <distributionManagement>
+ <site>
+ <id>ecomp-site</id>
+ <url>dav:${onap.nexus.url}/${sitePath}</url>
+ </site>
+ </distributionManagement>
- <developerConnection>scm:git:ssh://${onap.git.host}:${onap.git.port}/${onap.git.project}/sdnc-northbound.git</developerConnection>
- <url>${onap.git.protocol}://${onap.git.host}/projects/${onap.git.project}/repos/sdnc-northbound/browse</url>
- </scm>
- <issueManagement>
- <system>JIRA</system>
- <url>https://jira.onap.org/</url>
- </issueManagement>
- <ciManagement>
- <system>Jenkins</system>
- <url>https://jenkins.onap.org/</url>
- </ciManagement>
- <distributionManagement>
- <site>
- <id>sdnc-javadoc</id>
- <url>dav:https://${onap.nexus.host}:${onap.nexus.port}/repository/sdn-c-javadoc/${project.artifactId}/${project.version}</url>
- </site>
- </distributionManagement>
+ <properties>
+ <sitePath>content/sites/site/org/onap/ccsdk/sli/${project.version}/</sitePath>
+ </properties>
- <build>
- <plugins>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-surefire-plugin</artifactId>
- <configuration>
- <skipTests>false</skipTests>
- </configuration>
- </plugin>
- </plugins>
- </build>
+ <profiles>
+ <profile>
+ <id>blackduck</id>
+ <activation>
+ <property>
+ <name>blackduck-scan</name>
+ </property>
+ </activation>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>com.blackducksoftware.integration</groupId>
+ <artifactId>hub-maven-plugin</artifactId>
+ <version>1.4.0</version>
+ <inherited>false</inherited>
+ <configuration>
+ <hubProjectName>${project.name}</hubProjectName>
+ <outputDirectory>${project.basedir}</outputDirectory>
+ </configuration>
+ <executions>
+ <execution>
+ <id>create-bdio-file</id>
+ <phase>package</phase>
+ <goals>
+ <goal>createHubOutput</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
- <profiles>
- <profile>
- <id>blackduck</id>
- <activation>
- <property>
- <name>blackduck-scan</name>
- </property>
- </activation>
- <build>
- <plugins>
- <plugin>
- <groupId>com.blackducksoftware.integration</groupId>
- <artifactId>hub-maven-plugin</artifactId>
- <version>1.4.0</version>
- <inherited>false</inherited>
- <configuration>
- <hubProjectName>${project.name}</hubProjectName>
- <outputDirectory>${project.basedir}</outputDirectory>
- </configuration>
- <executions>
- <execution>
- <id>create-bdio-file</id>
- <phase>package</phase>
- <goals>
- <goal>createHubOutput</goal>
- </goals>
- </execution>
- </executions>
- </plugin>
- </plugins>
+ </profile>
+ <profile>
+ <id>dependency-list</id>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>com.github.ferstl</groupId>
+ <artifactId>depgraph-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <phase>validate</phase>
+ <inherited>false</inherited>
+ <goals>
+ <goal>aggregate</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>build-helper-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>attach-artifacts</id>
+ <phase>package</phase>
+ <inherited>false</inherited>
+ <goals>
+ <goal>attach-artifact</goal>
+ </goals>
+ <configuration>
+ <artifacts>
+ <artifact>
+ <file>${dependency-list.file}</file>
+ <type>txt</type>
+ <classifier>dependencies</classifier>
+ </artifact>
+ </artifacts>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
- </build>
-
- </profile>
- <profile>
- <id>dependency-list</id>
- <build>
- <plugins>
- <plugin>
- <groupId>com.github.ferstl</groupId>
- <artifactId>depgraph-maven-plugin</artifactId>
- <executions>
- <execution>
- <phase>validate</phase>
- <inherited>false</inherited>
- <goals>
- <goal>aggregate</goal>
- </goals>
- </execution>
- </executions>
- </plugin>
- <plugin>
- <groupId>org.codehaus.mojo</groupId>
- <artifactId>build-helper-maven-plugin</artifactId>
- <executions>
- <execution>
- <id>attach-artifacts</id>
- <phase>package</phase>
- <inherited>false</inherited>
- <goals>
- <goal>attach-artifact</goal>
- </goals>
- <configuration>
- <artifacts>
- <artifact>
- <file>${dependency-list.file}</file>
- <type>txt</type>
- <classifier>dependencies</classifier>
- </artifact>
- </artifacts>
- </configuration>
- </execution>
- </executions>
- </plugin>
- </plugins>
- </build>
- </profile>
- </profiles>
+ </profiles>
</project>
diff --git a/version.properties b/version.properties
index 8c043844d..977efc0e3 100644
--- a/version.properties
+++ b/version.properties
@@ -2,13 +2,3 @@
# Versioning variables
# Note that these variables cannot be structured (e.g. : version.release or version.snapshot etc... )
# because they are used in Jenkins, whose plug-in doesn't support
-
-release_name=1
-sprint_number=1
-feature_revision=1
-
-base_version=${release_name}.${sprint_number}.${feature_revision}
-
-release_version=${base_version}
-snapshot_version=${base_version}-SNAPSHOT
-