summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJessica Wagantall <jwagantall@linuxfoundation.org>2020-12-01 11:47:20 -0800
committerJessica Wagantall <jwagantall@linuxfoundation.org>2020-12-01 11:47:20 -0800
commit53eacd8519a535f96d8b4231e48925324f1086dd (patch)
treed9b4d0b1cb35677933adb4648e0563d64e0a5ef0
parent96a9aafdff7813324bc8a8ba1e743683e251dde6 (diff)
parent72e952ae47506673f7efc893ae447fe55598a952 (diff)
Merge branch 'master' of /home/jwagantall/linuxfoundation/onap/IT-21112/sli-core
Signed-off-by: Jessica Wagantall <jwagantall@linuxfoundation.org>
-rw-r--r--LICENSE.txt22
-rw-r--r--README.md7
-rwxr-xr-xartifacts/pom.xml152
-rwxr-xr-xdblib/.gitignore34
-rwxr-xr-xdblib/README.md6
-rwxr-xr-xdblib/installer/pom.xml128
-rwxr-xr-xdblib/installer/src/assembly/assemble_installer_zip.xml39
-rwxr-xr-xdblib/installer/src/assembly/assemble_mvnrepo_zip.xml29
-rw-r--r--dblib/installer/src/main/resources/scripts/install-feature.sh18
-rwxr-xr-xdblib/pom.xml27
-rwxr-xr-xdblib/provider/pom.xml64
-rwxr-xr-xdblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/CachedDataSource.java593
-rw-r--r--dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/CachedDataSourceFactory.java46
-rw-r--r--dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/DBConfigException.java47
-rwxr-xr-xdblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/DBLIBResourceProvider.java165
-rw-r--r--dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/DBLibConnection.java387
-rw-r--r--dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/DBLibException.java39
-rwxr-xr-xdblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/DBResourceManager.java983
-rw-r--r--dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/DBResourceObserver.java27
-rw-r--r--dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/DataAccessor.java34
-rw-r--r--dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/DataSourceComparator.java33
-rw-r--r--dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/DbLibService.java50
-rw-r--r--dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/DblibConfigurationException.java45
-rw-r--r--dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/NoAvailableConnectionsException.java36
-rwxr-xr-xdblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/TerminatingCachedDataSource.java59
-rwxr-xr-xdblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/config/BaseDBConfiguration.java258
-rw-r--r--dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/config/DbConfigPool.java63
-rw-r--r--dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/config/JDBCConfiguration.java31
-rwxr-xr-xdblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/config/TerminatingConfiguration.java33
-rw-r--r--dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/factory/DBConfigFactory.java105
-rwxr-xr-xdblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/jdbc/JdbcDBCachedDataSource.java201
-rw-r--r--dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/pm/PollingWorker.java259
-rw-r--r--dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/pm/SQLExecutionMonitor.java222
-rw-r--r--dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/pm/SQLExecutionMonitorObserver.java37
-rwxr-xr-xdblib/provider/src/main/resources/OSGI-INF/blueprint/dblib-blueprint.xml18
-rwxr-xr-xdblib/provider/src/main/resources/dblib.properties14
-rwxr-xr-xdblib/provider/src/main/resources/org/opendaylight/blueprint/dblib-blueprint.xml24
-rw-r--r--dblib/provider/src/test/java/org/onap/ccsdk/sli/core/dblib/CachedDataSourceTest.java121
-rw-r--r--dblib/provider/src/test/java/org/onap/ccsdk/sli/core/dblib/DBConfigExceptionTest.java19
-rw-r--r--dblib/provider/src/test/java/org/onap/ccsdk/sli/core/dblib/DblibConfigurationExceptionTest.java24
-rw-r--r--dblib/provider/src/test/java/org/onap/ccsdk/sli/core/dblib/NoAvailableConnectionsExceptionTest.java16
-rw-r--r--dblib/provider/src/test/java/org/onap/ccsdk/sli/core/dblib/TerminatingCachedDataSourceTest.java94
-rw-r--r--dblib/provider/src/test/java/org/onap/ccsdk/sli/core/dblib/TestDBResourceManager.java70
-rw-r--r--dblib/provider/src/test/java/org/onap/ccsdk/sli/core/dblib/TestDBResourceManager2.java95
-rw-r--r--dblib/provider/src/test/resources/dblib.properties38
-rw-r--r--features/ccsdk-dblib/pom.xml63
-rw-r--r--features/ccsdk-dblib/src/main/feature/feature.xml13
-rw-r--r--features/ccsdk-filters/pom.xml45
-rw-r--r--features/ccsdk-sli-core-all/pom.xml82
-rw-r--r--features/ccsdk-sli/pom.xml54
-rw-r--r--features/ccsdk-sliPluginUtils/pom.xml36
-rw-r--r--features/ccsdk-sliapi/pom.xml36
-rw-r--r--features/ccsdk-slicore-utils/pom.xml29
-rw-r--r--features/features-sli-core/pom.xml29
-rwxr-xr-xfeatures/installer/pom.xml214
-rwxr-xr-xfeatures/installer/src/assembly/assemble_installer_zip.xml39
-rwxr-xr-xfeatures/installer/src/assembly/assemble_mvnrepo_zip.xml29
-rw-r--r--features/installer/src/main/resources/scripts/install-feature.sh18
-rwxr-xr-xfeatures/pom.xml30
-rwxr-xr-xfilters/.gitignore34
-rwxr-xr-xfilters/.sonar/checkstyle.xml1
-rwxr-xr-xfilters/.sonar/pmd.xml67
-rwxr-xr-xfilters/README14
-rwxr-xr-xfilters/installer/pom.xml126
-rw-r--r--filters/installer/src/assembly/assemble_installer_zip.xml61
-rw-r--r--filters/installer/src/assembly/assemble_mvnrepo_zip.xml49
-rw-r--r--filters/installer/src/main/resources/scripts/install-feature.sh39
-rw-r--r--filters/pom.xml27
-rwxr-xr-xfilters/provider/pom.xml29
-rw-r--r--filters/provider/src/main/java/org/onap/ccsdk/sli/core/filters/ControllerAuditLogFilter.java40
-rw-r--r--filters/provider/src/main/java/org/onap/ccsdk/sli/core/filters/ControllerPayloadLoggingFilter.java7
-rw-r--r--filters/provider/src/test/java/org/onap/ccsdk/sli/core/filters/ControllerAuditLogFilterTest.java23
-rw-r--r--releases/0.5.0.yaml5
-rw-r--r--releases/0.5.1.yaml5
-rw-r--r--releases/0.5.2.yaml5
-rw-r--r--releases/0.6.0.yaml5
-rw-r--r--releases/0.6.1.yaml5
-rw-r--r--releases/0.7.0.yaml5
-rw-r--r--releases/0.7.1.yaml5
-rw-r--r--releases/1.0.0.yaml5
-rw-r--r--releases/1.0.1.yaml5
-rw-r--r--releases/1.1.0.yaml5
-rwxr-xr-xsli/.gitignore38
-rwxr-xr-xsli/common/pom.xml129
-rwxr-xr-xsli/common/src/main/antlr4/org/onap/ccsdk/sli/core/sli/ExprGrammar.g467
-rw-r--r--sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/ActivationEntry.java41
-rw-r--r--sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/BreakNodeException.java46
-rw-r--r--sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/CheckSumHelper.java51
-rw-r--r--sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/CommonConstants.java38
-rw-r--r--sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/ConfigurationException.java45
-rw-r--r--sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/DuplicateValueException.java45
-rw-r--r--sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/ErrorLogger.java100
-rwxr-xr-xsli/common/src/main/java/org/onap/ccsdk/sli/core/sli/ExitNodeException.java46
-rw-r--r--sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/MessageWriter.java281
-rwxr-xr-xsli/common/src/main/java/org/onap/ccsdk/sli/core/sli/MetricLogger.java165
-rw-r--r--sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SecurePrinter.java123
-rw-r--r--sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicAdaptor.java42
-rw-r--r--sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicAtom.java170
-rw-r--r--sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicBinaryExpression.java151
-rw-r--r--sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicConstants.java7
-rw-r--r--sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicContext.java438
-rw-r--r--sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicCrawler.java92
-rw-r--r--sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicDblibStore.java332
-rw-r--r--sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicException.java46
-rw-r--r--sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicExprListener.java271
-rw-r--r--sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicExprParserErrorListener.java44
-rw-r--r--sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicExpression.java52
-rw-r--r--sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicExpressionFactory.java75
-rw-r--r--sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicFunctionCall.java80
-rw-r--r--sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicGraph.java199
-rw-r--r--sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicJavaPlugin.java30
-rw-r--r--sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicJdbcStore.java574
-rw-r--r--sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicLoader.java178
-rw-r--r--sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicNode.java457
-rw-r--r--sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicParser.java615
-rw-r--r--sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicParserException.java43
-rw-r--r--sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicRecorder.java30
-rw-r--r--sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicResource.java52
-rw-r--r--sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicStore.java36
-rw-r--r--sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicStoreFactory.java100
-rw-r--r--sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicVariableTerm.java77
-rwxr-xr-xsli/common/src/main/resources/svclogic.xsd339
-rw-r--r--sli/common/src/test/java/org/onap/ccsdk/sli/core/sli/ConfigurationExceptionTestt.java30
-rw-r--r--sli/common/src/test/java/org/onap/ccsdk/sli/core/sli/DuplicatevalueExceptionTest.java28
-rw-r--r--sli/common/src/test/java/org/onap/ccsdk/sli/core/sli/ErrorLoggerTest.java56
-rw-r--r--sli/common/src/test/java/org/onap/ccsdk/sli/core/sli/ExitNodeExceptionTest.java27
-rw-r--r--sli/common/src/test/java/org/onap/ccsdk/sli/core/sli/ITCaseSvcLogicParser.java284
-rw-r--r--sli/common/src/test/java/org/onap/ccsdk/sli/core/sli/SvcLogicContextTest.java400
-rw-r--r--sli/common/src/test/java/org/onap/ccsdk/sli/core/sli/SvcLogicExpressionParserTest.java66
-rw-r--r--sli/common/src/test/java/org/onap/ccsdk/sli/core/sli/SvcLogicParserExceptionTest.java34
-rwxr-xr-xsli/common/src/test/java/org/onap/ccsdk/sli/core/sli/TestMetricLogger.java85
-rw-r--r--sli/common/src/test/java/org/onap/ccsdk/sli/core/sli/TestSvcLogicLoader.java38
-rw-r--r--sli/common/src/test/resources/2dArray.json4
-rw-r--r--sli/common/src/test/resources/3dArray.json4
-rw-r--r--sli/common/src/test/resources/ArrayMenu.json41
-rw-r--r--sli/common/src/test/resources/EmbeddedEscapedJson.json16
-rw-r--r--sli/common/src/test/resources/EscapedJson.json1
-rw-r--r--sli/common/src/test/resources/EvcActivateSvcLogic_v100.xml70
-rw-r--r--sli/common/src/test/resources/EvcPortSvcLogic_v100.xml263
-rw-r--r--sli/common/src/test/resources/JsonObject.json5
-rw-r--r--sli/common/src/test/resources/ObjectMenu.json43
-rw-r--r--sli/common/src/test/resources/QuotedValues.json43
-rw-r--r--sli/common/src/test/resources/ReleasePortSvcLogic_v101.xml89
-rw-r--r--sli/common/src/test/resources/Widget.json27
-rw-r--r--sli/common/src/test/resources/bad_neutron_logic_v11.xml61
-rwxr-xr-xsli/common/src/test/resources/dblib.properties14
-rwxr-xr-xsli/common/src/test/resources/expression.tests19
-rw-r--r--sli/common/src/test/resources/graphs/sliapi/graph.versions1
-rw-r--r--sli/common/src/test/resources/graphs/sliapi/sli_healthcheck.xml27
-rw-r--r--sli/common/src/test/resources/l3sdn_logic_v10.xml208
-rw-r--r--sli/common/src/test/resources/log4j2.properties39
-rw-r--r--sli/common/src/test/resources/mergetest.xml54
-rw-r--r--sli/common/src/test/resources/neutron_logic_v10.xml56
-rw-r--r--sli/common/src/test/resources/nonsense.xml24
-rwxr-xr-xsli/common/src/test/resources/parser-bad.tests3
-rwxr-xr-xsli/common/src/test/resources/parser-good.tests3
-rw-r--r--sli/common/src/test/resources/simplelogger.properties24
-rw-r--r--sli/common/src/test/resources/svclogic.properties27
-rw-r--r--sli/common/src/test/resources/svclogic.sh32
-rwxr-xr-xsli/installer/pom.xml144
-rw-r--r--sli/installer/src/assembly/assemble_installer_zip.xml59
-rw-r--r--sli/installer/src/assembly/assemble_mvnrepo_zip.xml42
-rw-r--r--sli/installer/src/main/resources/scripts/install-feature.sh39
-rwxr-xr-xsli/model/pom.xml27
-rwxr-xr-xsli/model/src/main/yang/sliapi.yang123
-rwxr-xr-xsli/model/src/main/yang/test-model@2019-07-23.yang210
-rwxr-xr-xsli/pom.xml30
-rw-r--r--sli/provider-base/pom.xml63
-rw-r--r--sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/AbstractSvcLogicNodeExecutor.java121
-rw-r--r--sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/BlockNodeExecutor.java71
-rw-r--r--sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/BreakNodeExecutor.java42
-rw-r--r--sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/CallNodeExecutor.java170
-rw-r--r--sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/ConfigureNodeExecutor.java242
-rw-r--r--sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/DeleteNodeExecutor.java75
-rw-r--r--sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/ExecuteNodeExecutor.java127
-rw-r--r--sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/ExistsNodeExecutor.java76
-rw-r--r--sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/ExitNodeExecutor.java42
-rw-r--r--sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/ForNodeExecutor.java110
-rw-r--r--sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/GetResourceNodeExecutor.java100
-rw-r--r--sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/HashMapResolver.java52
-rw-r--r--sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/InMemorySvcLogicStore.java66
-rw-r--r--sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/IsAvailableNodeExecutor.java72
-rw-r--r--sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/NotifyNodeExecutor.java75
-rw-r--r--sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/RecordNodeExecutor.java65
-rw-r--r--sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/ReleaseNodeExecutor.java74
-rw-r--r--sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/ReserveNodeExecutor.java88
-rw-r--r--sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/ReturnNodeExecutor.java77
-rw-r--r--sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/SaveNodeExecutor.java94
-rw-r--r--sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/SetNodeExecutor.java179
-rw-r--r--sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/SvcLogicExpressionResolver.java603
-rw-r--r--sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/SvcLogicPropertiesProvider.java28
-rw-r--r--sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/SvcLogicResolver.java17
-rw-r--r--sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/SvcLogicServiceBase.java80
-rw-r--r--sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/SvcLogicServiceImplBase.java180
-rw-r--r--sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/SwitchNodeExecutor.java63
-rw-r--r--sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/UpdateNodeExecutor.java89
-rw-r--r--sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/WhileNodeExecutor.java75
-rw-r--r--sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/recording/FileRecorder.java113
-rw-r--r--sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/recording/Slf4jRecorder.java160
-rw-r--r--sli/provider-base/src/test/java/org/onap/ccsdk/sli/core/sli/provider/base/BadPlugin.java56
-rw-r--r--sli/provider-base/src/test/java/org/onap/ccsdk/sli/core/sli/provider/base/ExecuteNodeExecutorTest.java64
-rw-r--r--sli/provider-base/src/test/java/org/onap/ccsdk/sli/core/sli/provider/base/GraphTests.java61
-rw-r--r--sli/provider-base/src/test/java/org/onap/ccsdk/sli/core/sli/provider/base/HashMapResolverTest.java51
-rw-r--r--sli/provider-base/src/test/java/org/onap/ccsdk/sli/core/sli/provider/base/InMemorySvcLogicStoreTest.java35
-rw-r--r--sli/provider-base/src/test/java/org/onap/ccsdk/sli/core/sli/provider/base/LunchSelectorPlugin.java78
-rw-r--r--sli/provider-base/src/test/java/org/onap/ccsdk/sli/core/sli/provider/base/PluginTest.java113
-rw-r--r--sli/provider-base/src/test/java/org/onap/ccsdk/sli/core/sli/provider/base/SetNodeExecutorTest.java220
-rw-r--r--sli/provider-base/src/test/java/org/onap/ccsdk/sli/core/sli/provider/base/SvcLogicExpressionResolverTest.java280
-rw-r--r--sli/provider-base/src/test/java/org/onap/ccsdk/sli/core/sli/recording/TestFileRecorder.java49
-rw-r--r--sli/provider-base/src/test/java/org/onap/ccsdk/sli/core/sli/recording/TestSlf4jRecorder.java33
-rw-r--r--sli/provider-base/src/test/resources/breakGraph.xml26
-rw-r--r--sli/provider-base/src/test/resources/clearMultipleArrayValues.xml23
-rw-r--r--sli/provider-base/src/test/resources/clearNestedSubArrayValues.xml27
-rw-r--r--sli/provider-base/src/test/resources/clearSingleArrayValues.xml23
-rw-r--r--sli/provider-base/src/test/resources/clearSingleSubArrayValues.xml27
-rw-r--r--sli/provider-base/src/test/resources/clearSubArrayValues.xml24
-rw-r--r--sli/provider-base/src/test/resources/clearValues.xml22
-rw-r--r--sli/provider-base/src/test/resources/copyValues.xml16
-rw-r--r--sli/provider-base/src/test/resources/expression.tests24
-rwxr-xr-xsli/provider-base/src/test/resources/expressions.xml55
-rw-r--r--sli/provider-base/src/test/resources/simplelogger.properties22
-rwxr-xr-xsli/provider/pom.xml144
-rwxr-xr-xsli/provider/src/main/java/org/onap/ccsdk/sli/core/sli/provider/MdsalHelper.java1274
-rw-r--r--sli/provider/src/main/java/org/onap/ccsdk/sli/core/sli/provider/PrintYangToProp.java1355
-rw-r--r--sli/provider/src/main/java/org/onap/ccsdk/sli/core/sli/provider/SvcLogicClassResolver.java98
-rw-r--r--sli/provider/src/main/java/org/onap/ccsdk/sli/core/sli/provider/SvcLogicPropertiesProviderImpl.java189
-rw-r--r--sli/provider/src/main/java/org/onap/ccsdk/sli/core/sli/provider/SvcLogicService.java52
-rwxr-xr-xsli/provider/src/main/java/org/onap/ccsdk/sli/core/sli/provider/SvcLogicServiceImpl.java90
-rw-r--r--sli/provider/src/main/resources/OSGI-INF/blueprint/sli-blueprint.xml36
-rw-r--r--sli/provider/src/main/resources/org/opendaylight/blueprint/sli-blueprint.xml36
-rw-r--r--sli/provider/src/test/java/org/onap/ccsdk/sli/core/sli/provider/ITCaseSvcLogicGraphExecutor.java265
-rwxr-xr-xsli/provider/src/test/java/org/onap/ccsdk/sli/core/sli/provider/MdsalHelperTest.java763
-rw-r--r--sli/provider/src/test/java/org/onap/ccsdk/sli/core/sli/provider/MdsalHelperTesterUtil.java37
-rw-r--r--sli/provider/src/test/java/org/onap/ccsdk/sli/core/sli/provider/PrintYangToPropTest.java142
-rw-r--r--sli/provider/src/test/java/org/opendaylight/yang/gen/v1/test/CosModelType.java51
-rwxr-xr-xsli/provider/src/test/java/org/opendaylight/yang/gen/v1/test/TestObject.java17
-rwxr-xr-xsli/provider/src/test/java/org/opendaylight/yang/gen/v1/test/TestObjectBuilder.java134
-rw-r--r--sli/provider/src/test/java/org/opendaylight/yang/gen/v1/test/WrapperObj.java10
-rw-r--r--sli/provider/src/test/resources/EnumerationMapping.properties1
-rwxr-xr-xsli/provider/src/test/resources/executor.tests8
-rw-r--r--sli/provider/src/test/resources/l3sdn.properties66
-rw-r--r--sli/provider/src/test/resources/l3sdn_logic_v10.xml227
-rwxr-xr-xsli/provider/src/test/resources/l3vpnyang/ietf-l3vpn-svc-part@2017-09-21.yang68
-rw-r--r--sli/provider/src/test/resources/simplelogger.properties22
-rw-r--r--sli/provider/src/test/resources/svclogic.properties27
-rwxr-xr-xsliPluginUtils/.gitignore34
-rwxr-xr-xsliPluginUtils/.sonar/checkstyle.xml1
-rwxr-xr-xsliPluginUtils/.sonar/pmd.xml67
-rwxr-xr-xsliPluginUtils/installer/pom.xml147
-rw-r--r--sliPluginUtils/installer/src/assembly/assemble_installer_zip.xml59
-rw-r--r--sliPluginUtils/installer/src/assembly/assemble_mvnrepo_zip.xml49
-rw-r--r--sliPluginUtils/installer/src/main/resources/scripts/install-feature.sh39
-rwxr-xr-xsliPluginUtils/pom.xml24
-rwxr-xr-xsliPluginUtils/provider/pom.xml72
-rw-r--r--sliPluginUtils/provider/src/main/java/org/onap/ccsdk/sli/core/slipluginutils/SliPluginUtils.java1178
-rw-r--r--sliPluginUtils/provider/src/main/java/org/onap/ccsdk/sli/core/slipluginutils/SliStringUtils.java559
-rw-r--r--sliPluginUtils/provider/src/main/java/org/onap/ccsdk/sli/core/slipluginutils/SvcLogicContextList.java210
-rw-r--r--sliPluginUtils/provider/src/main/java/org/onap/ccsdk/sli/core/slipluginutils/SvcLogicContextObject.java28
-rw-r--r--sliPluginUtils/provider/src/main/java/org/onap/ccsdk/sli/core/slipluginutils/commondatastructures/YesNo.java51
-rw-r--r--sliPluginUtils/provider/src/main/java/org/onap/ccsdk/sli/core/slipluginutils/commondatastructures/package-info.java28
-rw-r--r--sliPluginUtils/provider/src/main/resources/OSGI-INF/blueprint/slipluginutils-blueprint.xml13
-rw-r--r--sliPluginUtils/provider/src/main/resources/org/opendaylight/blueprint/slipluginutils-blueprint.xml13
-rw-r--r--sliPluginUtils/provider/src/test/java/org/onap/ccsdk/sli/core/slipluginutils/SliPluginUtils_StaticFunctionsTest.java591
-rw-r--r--sliPluginUtils/provider/src/test/java/org/onap/ccsdk/sli/core/slipluginutils/SliPluginUtils_checkParametersTest.java117
-rw-r--r--sliPluginUtils/provider/src/test/java/org/onap/ccsdk/sli/core/slipluginutils/SliPluginUtils_ctxSortList.java149
-rw-r--r--sliPluginUtils/provider/src/test/java/org/onap/ccsdk/sli/core/slipluginutils/SliPluginUtils_ctxSortListTest.java97
-rw-r--r--sliPluginUtils/provider/src/test/java/org/onap/ccsdk/sli/core/slipluginutils/SliStringUtilsTest.java398
-rw-r--r--sliPluginUtils/provider/src/test/java/org/onap/ccsdk/sli/core/slipluginutils/SvcLogicContextListTest.java307
-rw-r--r--sliPluginUtils/provider/src/test/resources/2dArray.json4
-rw-r--r--sliPluginUtils/provider/src/test/resources/3dArray.json4
-rw-r--r--sliPluginUtils/provider/src/test/resources/ArrayMenu.json41
-rw-r--r--sliPluginUtils/provider/src/test/resources/EmbeddedEscapedJson.json16
-rw-r--r--sliPluginUtils/provider/src/test/resources/EscapedJson.json1
-rw-r--r--sliPluginUtils/provider/src/test/resources/JsonObject.json5
-rw-r--r--sliPluginUtils/provider/src/test/resources/ObjectMenu.json43
-rw-r--r--sliPluginUtils/provider/src/test/resources/Widget.json27
-rwxr-xr-xsliapi/.gitignore38
-rwxr-xr-xsliapi/README.txt35
-rwxr-xr-xsliapi/installer/pom.xml164
-rw-r--r--sliapi/installer/src/assembly/assemble_installer_zip.xml59
-rw-r--r--sliapi/installer/src/assembly/assemble_mvnrepo_zip.xml49
-rw-r--r--sliapi/installer/src/main/resources/scripts/install-feature.sh39
-rwxr-xr-xsliapi/model/pom.xml24
-rw-r--r--sliapi/model/src/main/resources/sli-api.20161110.yaml254
-rw-r--r--sliapi/model/swagger/pom.xml222
-rw-r--r--sliapi/model/swagger/src/main/json/sliapi.json1
-rw-r--r--sliapi/model/swagger/src/main/yaml/sliapi.yaml378
-rwxr-xr-xsliapi/model/yang/pom.xml27
-rw-r--r--sliapi/model/yang/src/main/resources/sli-api.20161110.json554
-rw-r--r--sliapi/model/yang/src/main/resources/sli-api.20161110.yaml254
-rwxr-xr-xsliapi/model/yang/src/main/yang/sliapi.yang117
-rwxr-xr-xsliapi/pom.xml28
-rwxr-xr-xsliapi/provider/pom.xml112
-rw-r--r--sliapi/provider/src/main/java/org/onap/ccsdk/sli/core/sliapi/SliapiHelper.java40
-rw-r--r--sliapi/provider/src/main/java/org/onap/ccsdk/sli/core/sliapi/SliapiProvider.java676
-rw-r--r--sliapi/provider/src/main/resources/OSGI-INF/blueprint/sliapi-blueprint.xml28
-rw-r--r--sliapi/provider/src/main/resources/org/opendaylight/blueprint/sliapi-blueprint.xml28
-rw-r--r--sliapi/provider/src/test/java/org/onap/ccsdk/sli/core/sliapi/SliapiHelperTest.java35
-rw-r--r--sliapi/provider/src/test/java/org/onap/ccsdk/sli/core/sliapi/TestSliapiProvider.java209
-rw-r--r--sliapi/provider/src/test/resources/simplelogger.properties23
-rw-r--r--sliapi/provider/src/test/resources/sli_healthcheck.xml27
-rw-r--r--sliapi/provider/src/test/resources/svclogic.properties27
-rw-r--r--src/site/apt/nodes.apt953
-rw-r--r--src/site/site.xml31
-rwxr-xr-xutils/installer/pom.xml129
-rwxr-xr-xutils/installer/src/assembly/assemble_installer_zip.xml39
-rwxr-xr-xutils/installer/src/assembly/assemble_mvnrepo_zip.xml29
-rw-r--r--utils/installer/src/main/resources/scripts/install-feature.sh18
-rwxr-xr-xutils/pom.xml27
-rw-r--r--utils/provider/pom.xml49
-rw-r--r--utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/DefaultFileResolver.java61
-rwxr-xr-xutils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/EnvVarFileResolver.java76
-rwxr-xr-xutils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/JREFileResolver.java111
-rw-r--r--utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/KarafRootFileResolver.java63
-rw-r--r--utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/PathValidator.java17
-rw-r--r--utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/PropertiesFileResolver.java45
-rwxr-xr-xutils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/common/BundleContextFileResolver.java82
-rwxr-xr-xutils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/common/CoreDefaultFileResolver.java41
-rwxr-xr-xutils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/common/SdncConfigEnvVarFileResolver.java38
-rwxr-xr-xutils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/dblib/DblibDefaultFileResolver.java25
-rw-r--r--utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/dblib/DblibEnvVarFileResolver.java23
-rw-r--r--utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/JREFileResolverTest.java14
-rw-r--r--utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/KarafRootFileResolverTest.java13
-rw-r--r--utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/common/BundleContexFileResolverTest.java16
-rw-r--r--utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/common/CoreDefaultFileResolverTest.java25
-rw-r--r--utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/common/SdncConfigEnvVarFileResolverTest.java24
-rw-r--r--utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/dblib/DblibDefaultFileResolverTest.java25
-rw-r--r--utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/dblib/DblibEnvVarFileResolverTest.java24
328 files changed, 34509 insertions, 0 deletions
diff --git a/LICENSE.txt b/LICENSE.txt
new file mode 100644
index 000000000..3ea5081a0
--- /dev/null
+++ b/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/README.md b/README.md
new file mode 100644
index 000000000..262339dde
--- /dev/null
+++ b/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/artifacts/pom.xml b/artifacts/pom.xml
new file mode 100755
index 000000000..9b5f92fd5
--- /dev/null
+++ b/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/dblib/.gitignore b/dblib/.gitignore
new file mode 100755
index 000000000..b73caf31e
--- /dev/null
+++ b/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/dblib/README.md b/dblib/README.md
new file mode 100755
index 000000000..ab2c5130e
--- /dev/null
+++ b/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/dblib/installer/pom.xml b/dblib/installer/pom.xml
new file mode 100755
index 000000000..44779753d
--- /dev/null
+++ b/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/dblib/installer/src/assembly/assemble_installer_zip.xml b/dblib/installer/src/assembly/assemble_installer_zip.xml
new file mode 100755
index 000000000..a6a22a9ba
--- /dev/null
+++ b/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/dblib/installer/src/assembly/assemble_mvnrepo_zip.xml b/dblib/installer/src/assembly/assemble_mvnrepo_zip.xml
new file mode 100755
index 000000000..86b07f1f3
--- /dev/null
+++ b/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/dblib/installer/src/main/resources/scripts/install-feature.sh b/dblib/installer/src/main/resources/scripts/install-feature.sh
new file mode 100644
index 000000000..e16e79a12
--- /dev/null
+++ b/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/dblib/pom.xml b/dblib/pom.xml
new file mode 100755
index 000000000..00f4d5b37
--- /dev/null
+++ b/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/dblib/provider/pom.xml b/dblib/provider/pom.xml
new file mode 100755
index 000000000..c45513794
--- /dev/null
+++ b/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/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/CachedDataSource.java b/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/CachedDataSource.java
new file mode 100755
index 000000000..b9a0f071b
--- /dev/null
+++ b/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/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/CachedDataSourceFactory.java b/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/CachedDataSourceFactory.java
new file mode 100644
index 000000000..15aa7a1d0
--- /dev/null
+++ b/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/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/DBConfigException.java b/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/DBConfigException.java
new file mode 100644
index 000000000..e41e29b5d
--- /dev/null
+++ b/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/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/DBLIBResourceProvider.java b/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/DBLIBResourceProvider.java
new file mode 100755
index 000000000..45e5a7870
--- /dev/null
+++ b/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/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/DBLibConnection.java b/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/DBLibConnection.java
new file mode 100644
index 000000000..65d0b9512
--- /dev/null
+++ b/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/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/DBLibException.java b/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/DBLibException.java
new file mode 100644
index 000000000..de241f478
--- /dev/null
+++ b/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/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/DBResourceManager.java b/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/DBResourceManager.java
new file mode 100755
index 000000000..7c71bcc81
--- /dev/null
+++ b/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/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/DBResourceObserver.java b/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/DBResourceObserver.java
new file mode 100644
index 000000000..f30212dca
--- /dev/null
+++ b/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/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/DataAccessor.java b/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/DataAccessor.java
new file mode 100644
index 000000000..93d8b6bf5
--- /dev/null
+++ b/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/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/DataSourceComparator.java b/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/DataSourceComparator.java
new file mode 100644
index 000000000..4cfcc7318
--- /dev/null
+++ b/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/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/DbLibService.java b/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/DbLibService.java
new file mode 100644
index 000000000..b30ad7bbf
--- /dev/null
+++ b/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/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/DblibConfigurationException.java b/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/DblibConfigurationException.java
new file mode 100644
index 000000000..be493aa1f
--- /dev/null
+++ b/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/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/NoAvailableConnectionsException.java b/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/NoAvailableConnectionsException.java
new file mode 100644
index 000000000..a39e5c5b4
--- /dev/null
+++ b/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/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/TerminatingCachedDataSource.java b/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/TerminatingCachedDataSource.java
new file mode 100755
index 000000000..852dda3c7
--- /dev/null
+++ b/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/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/config/BaseDBConfiguration.java b/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/config/BaseDBConfiguration.java
new file mode 100755
index 000000000..ea6bc450d
--- /dev/null
+++ b/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/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/config/DbConfigPool.java b/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/config/DbConfigPool.java
new file mode 100644
index 000000000..ea7b3fdc8
--- /dev/null
+++ b/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/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/config/JDBCConfiguration.java b/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/config/JDBCConfiguration.java
new file mode 100644
index 000000000..fea103569
--- /dev/null
+++ b/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/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/config/TerminatingConfiguration.java b/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/config/TerminatingConfiguration.java
new file mode 100755
index 000000000..1ebd1441f
--- /dev/null
+++ b/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/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/factory/DBConfigFactory.java b/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/factory/DBConfigFactory.java
new file mode 100644
index 000000000..1aa907837
--- /dev/null
+++ b/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/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/jdbc/JdbcDBCachedDataSource.java b/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/jdbc/JdbcDBCachedDataSource.java
new file mode 100755
index 000000000..a53d18639
--- /dev/null
+++ b/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/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/pm/PollingWorker.java b/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/pm/PollingWorker.java
new file mode 100644
index 000000000..f66250676
--- /dev/null
+++ b/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/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/pm/SQLExecutionMonitor.java b/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/pm/SQLExecutionMonitor.java
new file mode 100644
index 000000000..b6664f3c3
--- /dev/null
+++ b/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/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/pm/SQLExecutionMonitorObserver.java b/dblib/provider/src/main/java/org/onap/ccsdk/sli/core/dblib/pm/SQLExecutionMonitorObserver.java
new file mode 100644
index 000000000..2fdde1ee4
--- /dev/null
+++ b/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/dblib/provider/src/main/resources/OSGI-INF/blueprint/dblib-blueprint.xml b/dblib/provider/src/main/resources/OSGI-INF/blueprint/dblib-blueprint.xml
new file mode 100755
index 000000000..f1d5166db
--- /dev/null
+++ b/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/dblib/provider/src/main/resources/dblib.properties b/dblib/provider/src/main/resources/dblib.properties
new file mode 100755
index 000000000..e0399cc31
--- /dev/null
+++ b/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/dblib/provider/src/main/resources/org/opendaylight/blueprint/dblib-blueprint.xml b/dblib/provider/src/main/resources/org/opendaylight/blueprint/dblib-blueprint.xml
new file mode 100755
index 000000000..d9bb99c07
--- /dev/null
+++ b/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/dblib/provider/src/test/java/org/onap/ccsdk/sli/core/dblib/CachedDataSourceTest.java b/dblib/provider/src/test/java/org/onap/ccsdk/sli/core/dblib/CachedDataSourceTest.java
new file mode 100644
index 000000000..45268107e
--- /dev/null
+++ b/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/dblib/provider/src/test/java/org/onap/ccsdk/sli/core/dblib/DBConfigExceptionTest.java b/dblib/provider/src/test/java/org/onap/ccsdk/sli/core/dblib/DBConfigExceptionTest.java
new file mode 100644
index 000000000..2a5b65c7a
--- /dev/null
+++ b/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/dblib/provider/src/test/java/org/onap/ccsdk/sli/core/dblib/DblibConfigurationExceptionTest.java b/dblib/provider/src/test/java/org/onap/ccsdk/sli/core/dblib/DblibConfigurationExceptionTest.java
new file mode 100644
index 000000000..7becd1ae4
--- /dev/null
+++ b/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/dblib/provider/src/test/java/org/onap/ccsdk/sli/core/dblib/NoAvailableConnectionsExceptionTest.java b/dblib/provider/src/test/java/org/onap/ccsdk/sli/core/dblib/NoAvailableConnectionsExceptionTest.java
new file mode 100644
index 000000000..2fdacb922
--- /dev/null
+++ b/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/dblib/provider/src/test/java/org/onap/ccsdk/sli/core/dblib/TerminatingCachedDataSourceTest.java b/dblib/provider/src/test/java/org/onap/ccsdk/sli/core/dblib/TerminatingCachedDataSourceTest.java
new file mode 100644
index 000000000..160a3d4ae
--- /dev/null
+++ b/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/dblib/provider/src/test/java/org/onap/ccsdk/sli/core/dblib/TestDBResourceManager.java b/dblib/provider/src/test/java/org/onap/ccsdk/sli/core/dblib/TestDBResourceManager.java
new file mode 100644
index 000000000..8d7d34324
--- /dev/null
+++ b/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/dblib/provider/src/test/java/org/onap/ccsdk/sli/core/dblib/TestDBResourceManager2.java b/dblib/provider/src/test/java/org/onap/ccsdk/sli/core/dblib/TestDBResourceManager2.java
new file mode 100644
index 000000000..a3cb8d914
--- /dev/null
+++ b/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/dblib/provider/src/test/resources/dblib.properties b/dblib/provider/src/test/resources/dblib.properties
new file mode 100644
index 000000000..9506ac8d1
--- /dev/null
+++ b/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/features/ccsdk-dblib/pom.xml b/features/ccsdk-dblib/pom.xml
new file mode 100644
index 000000000..88a840a15
--- /dev/null
+++ b/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/features/ccsdk-dblib/src/main/feature/feature.xml b/features/ccsdk-dblib/src/main/feature/feature.xml
new file mode 100644
index 000000000..771c37455
--- /dev/null
+++ b/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/features/ccsdk-filters/pom.xml b/features/ccsdk-filters/pom.xml
new file mode 100644
index 000000000..b096df322
--- /dev/null
+++ b/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/features/ccsdk-sli-core-all/pom.xml b/features/ccsdk-sli-core-all/pom.xml
new file mode 100644
index 000000000..270ed685f
--- /dev/null
+++ b/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/features/ccsdk-sli/pom.xml b/features/ccsdk-sli/pom.xml
new file mode 100644
index 000000000..f6e97ec20
--- /dev/null
+++ b/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/features/ccsdk-sliPluginUtils/pom.xml b/features/ccsdk-sliPluginUtils/pom.xml
new file mode 100644
index 000000000..c050dcde5
--- /dev/null
+++ b/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/features/ccsdk-sliapi/pom.xml b/features/ccsdk-sliapi/pom.xml
new file mode 100644
index 000000000..89e7eec3e
--- /dev/null
+++ b/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/features/ccsdk-slicore-utils/pom.xml b/features/ccsdk-slicore-utils/pom.xml
new file mode 100644
index 000000000..ea8492b75
--- /dev/null
+++ b/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/features/features-sli-core/pom.xml b/features/features-sli-core/pom.xml
new file mode 100644
index 000000000..1459cef01
--- /dev/null
+++ b/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/features/installer/pom.xml b/features/installer/pom.xml
new file mode 100755
index 000000000..d02e5d8d3
--- /dev/null
+++ b/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/features/installer/src/assembly/assemble_installer_zip.xml b/features/installer/src/assembly/assemble_installer_zip.xml
new file mode 100755
index 000000000..a6a22a9ba
--- /dev/null
+++ b/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/features/installer/src/assembly/assemble_mvnrepo_zip.xml b/features/installer/src/assembly/assemble_mvnrepo_zip.xml
new file mode 100755
index 000000000..86b07f1f3
--- /dev/null
+++ b/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/features/installer/src/main/resources/scripts/install-feature.sh b/features/installer/src/main/resources/scripts/install-feature.sh
new file mode 100644
index 000000000..e16e79a12
--- /dev/null
+++ b/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/features/pom.xml b/features/pom.xml
new file mode 100755
index 000000000..69355a4c7
--- /dev/null
+++ b/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/filters/.gitignore b/filters/.gitignore
new file mode 100755
index 000000000..b73caf31e
--- /dev/null
+++ b/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/filters/.sonar/checkstyle.xml b/filters/.sonar/checkstyle.xml
new file mode 100755
index 000000000..3fa231535
--- /dev/null
+++ b/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/filters/.sonar/pmd.xml b/filters/.sonar/pmd.xml
new file mode 100755
index 000000000..80343b3bd
--- /dev/null
+++ b/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/filters/README b/filters/README
new file mode 100755
index 000000000..5c1b3d627
--- /dev/null
+++ b/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/filters/installer/pom.xml b/filters/installer/pom.xml
new file mode 100755
index 000000000..fae31a12b
--- /dev/null
+++ b/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/filters/installer/src/assembly/assemble_installer_zip.xml b/filters/installer/src/assembly/assemble_installer_zip.xml
new file mode 100644
index 000000000..2ff550d2c
--- /dev/null
+++ b/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/filters/installer/src/assembly/assemble_mvnrepo_zip.xml b/filters/installer/src/assembly/assemble_mvnrepo_zip.xml
new file mode 100644
index 000000000..69e9e2909
--- /dev/null
+++ b/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/filters/installer/src/main/resources/scripts/install-feature.sh b/filters/installer/src/main/resources/scripts/install-feature.sh
new file mode 100644
index 000000000..74b95b5c8
--- /dev/null
+++ b/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/filters/pom.xml b/filters/pom.xml
new file mode 100644
index 000000000..8db5d810b
--- /dev/null
+++ b/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/filters/provider/pom.xml b/filters/provider/pom.xml
new file mode 100755
index 000000000..ea7f9962e
--- /dev/null
+++ b/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/filters/provider/src/main/java/org/onap/ccsdk/sli/core/filters/ControllerAuditLogFilter.java b/filters/provider/src/main/java/org/onap/ccsdk/sli/core/filters/ControllerAuditLogFilter.java
new file mode 100644
index 000000000..7805e365d
--- /dev/null
+++ b/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/filters/provider/src/main/java/org/onap/ccsdk/sli/core/filters/ControllerPayloadLoggingFilter.java b/filters/provider/src/main/java/org/onap/ccsdk/sli/core/filters/ControllerPayloadLoggingFilter.java
new file mode 100644
index 000000000..3f9f93fc5
--- /dev/null
+++ b/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/filters/provider/src/test/java/org/onap/ccsdk/sli/core/filters/ControllerAuditLogFilterTest.java b/filters/provider/src/test/java/org/onap/ccsdk/sli/core/filters/ControllerAuditLogFilterTest.java
new file mode 100644
index 000000000..9d0357a96
--- /dev/null
+++ b/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/releases/0.5.0.yaml b/releases/0.5.0.yaml
new file mode 100644
index 000000000..dc9dae2c0
--- /dev/null
+++ b/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/releases/0.5.1.yaml b/releases/0.5.1.yaml
new file mode 100644
index 000000000..00785283f
--- /dev/null
+++ b/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/releases/0.5.2.yaml b/releases/0.5.2.yaml
new file mode 100644
index 000000000..25c0b4ada
--- /dev/null
+++ b/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/releases/0.6.0.yaml b/releases/0.6.0.yaml
new file mode 100644
index 000000000..0106367c1
--- /dev/null
+++ b/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/releases/0.6.1.yaml b/releases/0.6.1.yaml
new file mode 100644
index 000000000..8ccc981ed
--- /dev/null
+++ b/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/releases/0.7.0.yaml b/releases/0.7.0.yaml
new file mode 100644
index 000000000..50ec2b4d4
--- /dev/null
+++ b/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/releases/0.7.1.yaml b/releases/0.7.1.yaml
new file mode 100644
index 000000000..0cdbee453
--- /dev/null
+++ b/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/releases/1.0.0.yaml b/releases/1.0.0.yaml
new file mode 100644
index 000000000..7e7e577e3
--- /dev/null
+++ b/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/releases/1.0.1.yaml b/releases/1.0.1.yaml
new file mode 100644
index 000000000..f86a0ba6a
--- /dev/null
+++ b/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/releases/1.1.0.yaml b/releases/1.1.0.yaml
new file mode 100644
index 000000000..3c256dd0f
--- /dev/null
+++ b/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/sli/.gitignore b/sli/.gitignore
new file mode 100755
index 000000000..3632ac676
--- /dev/null
+++ b/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/sli/common/pom.xml b/sli/common/pom.xml
new file mode 100755
index 000000000..201c11bdd
--- /dev/null
+++ b/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/sli/common/src/main/antlr4/org/onap/ccsdk/sli/core/sli/ExprGrammar.g4 b/sli/common/src/main/antlr4/org/onap/ccsdk/sli/core/sli/ExprGrammar.g4
new file mode 100755
index 000000000..42563168c
--- /dev/null
+++ b/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/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/ActivationEntry.java b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/ActivationEntry.java
new file mode 100644
index 000000000..a1c0eafe8
--- /dev/null
+++ b/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/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/BreakNodeException.java b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/BreakNodeException.java
new file mode 100644
index 000000000..e1c0e3db5
--- /dev/null
+++ b/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/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/CheckSumHelper.java b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/CheckSumHelper.java
new file mode 100644
index 000000000..9283cf650
--- /dev/null
+++ b/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/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/CommonConstants.java b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/CommonConstants.java
new file mode 100644
index 000000000..b1a7320d7
--- /dev/null
+++ b/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/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/ConfigurationException.java b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/ConfigurationException.java
new file mode 100644
index 000000000..144b99a8a
--- /dev/null
+++ b/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/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/DuplicateValueException.java b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/DuplicateValueException.java
new file mode 100644
index 000000000..43f4fe53e
--- /dev/null
+++ b/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/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/ErrorLogger.java b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/ErrorLogger.java
new file mode 100644
index 000000000..47f6526e9
--- /dev/null
+++ b/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/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/ExitNodeException.java b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/ExitNodeException.java
new file mode 100755
index 000000000..f119c1812
--- /dev/null
+++ b/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/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/MessageWriter.java b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/MessageWriter.java
new file mode 100644
index 000000000..5ededb9eb
--- /dev/null
+++ b/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/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/MetricLogger.java b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/MetricLogger.java
new file mode 100755
index 000000000..577b73401
--- /dev/null
+++ b/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/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SecurePrinter.java b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SecurePrinter.java
new file mode 100644
index 000000000..e25aed9f8
--- /dev/null
+++ b/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/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicAdaptor.java b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicAdaptor.java
new file mode 100644
index 000000000..a76b123ca
--- /dev/null
+++ b/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/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicAtom.java b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicAtom.java
new file mode 100644
index 000000000..b9ad19e25
--- /dev/null
+++ b/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/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicBinaryExpression.java b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicBinaryExpression.java
new file mode 100644
index 000000000..a990dd950
--- /dev/null
+++ b/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/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicConstants.java b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicConstants.java
new file mode 100644
index 000000000..61bfe7c20
--- /dev/null
+++ b/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/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicContext.java b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicContext.java
new file mode 100644
index 000000000..98cf7e05e
--- /dev/null
+++ b/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/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicCrawler.java b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicCrawler.java
new file mode 100644
index 000000000..c6fd8b6a2
--- /dev/null
+++ b/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/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicDblibStore.java b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicDblibStore.java
new file mode 100644
index 000000000..dc3a560eb
--- /dev/null
+++ b/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/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicException.java b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicException.java
new file mode 100644
index 000000000..c03ef9787
--- /dev/null
+++ b/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/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicExprListener.java b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicExprListener.java
new file mode 100644
index 000000000..a1871951f
--- /dev/null
+++ b/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/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicExprParserErrorListener.java b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicExprParserErrorListener.java
new file mode 100644
index 000000000..03f2a8b0b
--- /dev/null
+++ b/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/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicExpression.java b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicExpression.java
new file mode 100644
index 000000000..81aeb6c37
--- /dev/null
+++ b/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/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicExpressionFactory.java b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicExpressionFactory.java
new file mode 100644
index 000000000..727c84b19
--- /dev/null
+++ b/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/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicFunctionCall.java b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicFunctionCall.java
new file mode 100644
index 000000000..8289f16da
--- /dev/null
+++ b/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/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicGraph.java b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicGraph.java
new file mode 100644
index 000000000..97f2bd7ab
--- /dev/null
+++ b/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/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicJavaPlugin.java b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicJavaPlugin.java
new file mode 100644
index 000000000..23dff3e6e
--- /dev/null
+++ b/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/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicJdbcStore.java b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicJdbcStore.java
new file mode 100644
index 000000000..f23456fee
--- /dev/null
+++ b/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/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicLoader.java b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicLoader.java
new file mode 100644
index 000000000..433b723e7
--- /dev/null
+++ b/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/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicNode.java b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicNode.java
new file mode 100644
index 000000000..b0d4fc058
--- /dev/null
+++ b/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/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicParser.java b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicParser.java
new file mode 100644
index 000000000..adec7b27d
--- /dev/null
+++ b/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/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicParserException.java b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicParserException.java
new file mode 100644
index 000000000..61f80f7e2
--- /dev/null
+++ b/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/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicRecorder.java b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicRecorder.java
new file mode 100644
index 000000000..ca13536bb
--- /dev/null
+++ b/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/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicResource.java b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicResource.java
new file mode 100644
index 000000000..0e2c42574
--- /dev/null
+++ b/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/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicStore.java b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicStore.java
new file mode 100644
index 000000000..2eda67f11
--- /dev/null
+++ b/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/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicStoreFactory.java b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicStoreFactory.java
new file mode 100644
index 000000000..e0eb57304
--- /dev/null
+++ b/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/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicVariableTerm.java b/sli/common/src/main/java/org/onap/ccsdk/sli/core/sli/SvcLogicVariableTerm.java
new file mode 100644
index 000000000..4edf3ecbe
--- /dev/null
+++ b/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/sli/common/src/main/resources/svclogic.xsd b/sli/common/src/main/resources/svclogic.xsd
new file mode 100755
index 000000000..c9beae83e
--- /dev/null
+++ b/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/sli/common/src/test/java/org/onap/ccsdk/sli/core/sli/ConfigurationExceptionTestt.java b/sli/common/src/test/java/org/onap/ccsdk/sli/core/sli/ConfigurationExceptionTestt.java
new file mode 100644
index 000000000..ef7492366
--- /dev/null
+++ b/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/sli/common/src/test/java/org/onap/ccsdk/sli/core/sli/DuplicatevalueExceptionTest.java b/sli/common/src/test/java/org/onap/ccsdk/sli/core/sli/DuplicatevalueExceptionTest.java
new file mode 100644
index 000000000..387873557
--- /dev/null
+++ b/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/sli/common/src/test/java/org/onap/ccsdk/sli/core/sli/ErrorLoggerTest.java b/sli/common/src/test/java/org/onap/ccsdk/sli/core/sli/ErrorLoggerTest.java
new file mode 100644
index 000000000..d95ff3075
--- /dev/null
+++ b/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/sli/common/src/test/java/org/onap/ccsdk/sli/core/sli/ExitNodeExceptionTest.java b/sli/common/src/test/java/org/onap/ccsdk/sli/core/sli/ExitNodeExceptionTest.java
new file mode 100644
index 000000000..039b9f5ca
--- /dev/null
+++ b/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/sli/common/src/test/java/org/onap/ccsdk/sli/core/sli/ITCaseSvcLogicParser.java b/sli/common/src/test/java/org/onap/ccsdk/sli/core/sli/ITCaseSvcLogicParser.java
new file mode 100644
index 000000000..50eb917f8
--- /dev/null
+++ b/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/sli/common/src/test/java/org/onap/ccsdk/sli/core/sli/SvcLogicContextTest.java b/sli/common/src/test/java/org/onap/ccsdk/sli/core/sli/SvcLogicContextTest.java
new file mode 100644
index 000000000..43e7a862b
--- /dev/null
+++ b/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/sli/common/src/test/java/org/onap/ccsdk/sli/core/sli/SvcLogicExpressionParserTest.java b/sli/common/src/test/java/org/onap/ccsdk/sli/core/sli/SvcLogicExpressionParserTest.java
new file mode 100644
index 000000000..80df10cee
--- /dev/null
+++ b/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/sli/common/src/test/java/org/onap/ccsdk/sli/core/sli/SvcLogicParserExceptionTest.java b/sli/common/src/test/java/org/onap/ccsdk/sli/core/sli/SvcLogicParserExceptionTest.java
new file mode 100644
index 000000000..f9d33cb16
--- /dev/null
+++ b/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/sli/common/src/test/java/org/onap/ccsdk/sli/core/sli/TestMetricLogger.java b/sli/common/src/test/java/org/onap/ccsdk/sli/core/sli/TestMetricLogger.java
new file mode 100755
index 000000000..37d2fc8c5
--- /dev/null
+++ b/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/sli/common/src/test/java/org/onap/ccsdk/sli/core/sli/TestSvcLogicLoader.java b/sli/common/src/test/java/org/onap/ccsdk/sli/core/sli/TestSvcLogicLoader.java
new file mode 100644
index 000000000..2dd83e86d
--- /dev/null
+++ b/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/sli/common/src/test/resources/2dArray.json b/sli/common/src/test/resources/2dArray.json
new file mode 100644
index 000000000..2a94b46f4
--- /dev/null
+++ b/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/sli/common/src/test/resources/3dArray.json b/sli/common/src/test/resources/3dArray.json
new file mode 100644
index 000000000..149955596
--- /dev/null
+++ b/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/sli/common/src/test/resources/ArrayMenu.json b/sli/common/src/test/resources/ArrayMenu.json
new file mode 100644
index 000000000..26a24f292
--- /dev/null
+++ b/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/sli/common/src/test/resources/EmbeddedEscapedJson.json b/sli/common/src/test/resources/EmbeddedEscapedJson.json
new file mode 100644
index 000000000..dbb6d8d3a
--- /dev/null
+++ b/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/sli/common/src/test/resources/EscapedJson.json b/sli/common/src/test/resources/EscapedJson.json
new file mode 100644
index 000000000..a7719e819
--- /dev/null
+++ b/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/sli/common/src/test/resources/EvcActivateSvcLogic_v100.xml b/sli/common/src/test/resources/EvcActivateSvcLogic_v100.xml
new file mode 100644
index 000000000..708823efc
--- /dev/null
+++ b/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/sli/common/src/test/resources/EvcPortSvcLogic_v100.xml b/sli/common/src/test/resources/EvcPortSvcLogic_v100.xml
new file mode 100644
index 000000000..9a1a14708
--- /dev/null
+++ b/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/sli/common/src/test/resources/JsonObject.json b/sli/common/src/test/resources/JsonObject.json
new file mode 100644
index 000000000..0578368f8
--- /dev/null
+++ b/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/sli/common/src/test/resources/ObjectMenu.json b/sli/common/src/test/resources/ObjectMenu.json
new file mode 100644
index 000000000..56f842d48
--- /dev/null
+++ b/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/sli/common/src/test/resources/QuotedValues.json b/sli/common/src/test/resources/QuotedValues.json
new file mode 100644
index 000000000..8bf91c66b
--- /dev/null
+++ b/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/sli/common/src/test/resources/ReleasePortSvcLogic_v101.xml b/sli/common/src/test/resources/ReleasePortSvcLogic_v101.xml
new file mode 100644
index 000000000..cee027f75
--- /dev/null
+++ b/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/sli/common/src/test/resources/Widget.json b/sli/common/src/test/resources/Widget.json
new file mode 100644
index 000000000..6b90907ce
--- /dev/null
+++ b/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/sli/common/src/test/resources/bad_neutron_logic_v11.xml b/sli/common/src/test/resources/bad_neutron_logic_v11.xml
new file mode 100644
index 000000000..e6ec8614b
--- /dev/null
+++ b/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/sli/common/src/test/resources/dblib.properties b/sli/common/src/test/resources/dblib.properties
new file mode 100755
index 000000000..f08dce7a0
--- /dev/null
+++ b/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/sli/common/src/test/resources/expression.tests b/sli/common/src/test/resources/expression.tests
new file mode 100755
index 000000000..c352e9b08
--- /dev/null
+++ b/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/sli/common/src/test/resources/graphs/sliapi/graph.versions b/sli/common/src/test/resources/graphs/sliapi/graph.versions
new file mode 100644
index 000000000..d72920a43
--- /dev/null
+++ b/sli/common/src/test/resources/graphs/sliapi/graph.versions
@@ -0,0 +1 @@
+sli healthcheck 1.0.0 sync
diff --git a/sli/common/src/test/resources/graphs/sliapi/sli_healthcheck.xml b/sli/common/src/test/resources/graphs/sliapi/sli_healthcheck.xml
new file mode 100644
index 000000000..d512f546f
--- /dev/null
+++ b/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/sli/common/src/test/resources/l3sdn_logic_v10.xml b/sli/common/src/test/resources/l3sdn_logic_v10.xml
new file mode 100644
index 000000000..58a420f9e
--- /dev/null
+++ b/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/sli/common/src/test/resources/log4j2.properties b/sli/common/src/test/resources/log4j2.properties
new file mode 100644
index 000000000..3a5d8ef76
--- /dev/null
+++ b/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/sli/common/src/test/resources/mergetest.xml b/sli/common/src/test/resources/mergetest.xml
new file mode 100644
index 000000000..95c26da27
--- /dev/null
+++ b/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/sli/common/src/test/resources/neutron_logic_v10.xml b/sli/common/src/test/resources/neutron_logic_v10.xml
new file mode 100644
index 000000000..74088036b
--- /dev/null
+++ b/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/sli/common/src/test/resources/nonsense.xml b/sli/common/src/test/resources/nonsense.xml
new file mode 100644
index 000000000..c30c6bfc6
--- /dev/null
+++ b/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/sli/common/src/test/resources/parser-bad.tests b/sli/common/src/test/resources/parser-bad.tests
new file mode 100755
index 000000000..82913afc2
--- /dev/null
+++ b/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/sli/common/src/test/resources/parser-good.tests b/sli/common/src/test/resources/parser-good.tests
new file mode 100755
index 000000000..4147fdb62
--- /dev/null
+++ b/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/sli/common/src/test/resources/simplelogger.properties b/sli/common/src/test/resources/simplelogger.properties
new file mode 100644
index 000000000..73e4d3a99
--- /dev/null
+++ b/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/sli/common/src/test/resources/svclogic.properties b/sli/common/src/test/resources/svclogic.properties
new file mode 100644
index 000000000..426960f76
--- /dev/null
+++ b/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/sli/common/src/test/resources/svclogic.sh b/sli/common/src/test/resources/svclogic.sh
new file mode 100644
index 000000000..67977c3d9
--- /dev/null
+++ b/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/sli/installer/pom.xml b/sli/installer/pom.xml
new file mode 100755
index 000000000..40776bdcf
--- /dev/null
+++ b/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/sli/installer/src/assembly/assemble_installer_zip.xml b/sli/installer/src/assembly/assemble_installer_zip.xml
new file mode 100644
index 000000000..2d3c0606d
--- /dev/null
+++ b/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/sli/installer/src/assembly/assemble_mvnrepo_zip.xml b/sli/installer/src/assembly/assemble_mvnrepo_zip.xml
new file mode 100644
index 000000000..6a21012dc
--- /dev/null
+++ b/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/sli/installer/src/main/resources/scripts/install-feature.sh b/sli/installer/src/main/resources/scripts/install-feature.sh
new file mode 100644
index 000000000..74b95b5c8
--- /dev/null
+++ b/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/sli/model/pom.xml b/sli/model/pom.xml
new file mode 100755
index 000000000..0b859e7d2
--- /dev/null
+++ b/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/sli/model/src/main/yang/sliapi.yang b/sli/model/src/main/yang/sliapi.yang
new file mode 100755
index 000000000..a7d52928b
--- /dev/null
+++ b/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/sli/model/src/main/yang/test-model@2019-07-23.yang b/sli/model/src/main/yang/test-model@2019-07-23.yang
new file mode 100755
index 000000000..fc8e8b007
--- /dev/null
+++ b/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/sli/pom.xml b/sli/pom.xml
new file mode 100755
index 000000000..cfb7656d1
--- /dev/null
+++ b/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/sli/provider-base/pom.xml b/sli/provider-base/pom.xml
new file mode 100644
index 000000000..eedce9154
--- /dev/null
+++ b/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/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/AbstractSvcLogicNodeExecutor.java b/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/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/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/BlockNodeExecutor.java b/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/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/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/BreakNodeExecutor.java b/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/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/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/CallNodeExecutor.java b/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/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/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/ConfigureNodeExecutor.java b/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/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/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/DeleteNodeExecutor.java b/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/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/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/ExecuteNodeExecutor.java b/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/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/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/ExistsNodeExecutor.java b/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/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/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/ExitNodeExecutor.java b/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/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/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/ForNodeExecutor.java b/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/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/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/GetResourceNodeExecutor.java b/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/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/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/HashMapResolver.java b/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/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/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/InMemorySvcLogicStore.java b/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/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/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/IsAvailableNodeExecutor.java b/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/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/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/NotifyNodeExecutor.java b/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/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/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/RecordNodeExecutor.java b/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/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/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/ReleaseNodeExecutor.java b/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/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/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/ReserveNodeExecutor.java b/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/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/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/ReturnNodeExecutor.java b/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/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/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/SaveNodeExecutor.java b/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/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/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/SetNodeExecutor.java b/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/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/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/SvcLogicExpressionResolver.java b/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/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/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/SvcLogicPropertiesProvider.java b/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/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/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/SvcLogicResolver.java b/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/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/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/SvcLogicServiceBase.java b/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/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/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/SvcLogicServiceImplBase.java b/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/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/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/SwitchNodeExecutor.java b/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/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/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/UpdateNodeExecutor.java b/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/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/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/provider/base/WhileNodeExecutor.java b/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/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/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/recording/FileRecorder.java b/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/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/sli/provider-base/src/main/java/org/onap/ccsdk/sli/core/sli/recording/Slf4jRecorder.java b/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/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/sli/provider-base/src/test/java/org/onap/ccsdk/sli/core/sli/provider/base/BadPlugin.java b/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/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/sli/provider-base/src/test/java/org/onap/ccsdk/sli/core/sli/provider/base/ExecuteNodeExecutorTest.java b/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/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/sli/provider-base/src/test/java/org/onap/ccsdk/sli/core/sli/provider/base/GraphTests.java b/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/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/sli/provider-base/src/test/java/org/onap/ccsdk/sli/core/sli/provider/base/HashMapResolverTest.java b/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/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/sli/provider-base/src/test/java/org/onap/ccsdk/sli/core/sli/provider/base/InMemorySvcLogicStoreTest.java b/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/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/sli/provider-base/src/test/java/org/onap/ccsdk/sli/core/sli/provider/base/LunchSelectorPlugin.java b/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/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/sli/provider-base/src/test/java/org/onap/ccsdk/sli/core/sli/provider/base/PluginTest.java b/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/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/sli/provider-base/src/test/java/org/onap/ccsdk/sli/core/sli/provider/base/SetNodeExecutorTest.java b/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/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/sli/provider-base/src/test/java/org/onap/ccsdk/sli/core/sli/provider/base/SvcLogicExpressionResolverTest.java b/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/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/sli/provider-base/src/test/java/org/onap/ccsdk/sli/core/sli/recording/TestFileRecorder.java b/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/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/sli/provider-base/src/test/java/org/onap/ccsdk/sli/core/sli/recording/TestSlf4jRecorder.java b/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/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/sli/provider-base/src/test/resources/breakGraph.xml b/sli/provider-base/src/test/resources/breakGraph.xml
new file mode 100644
index 000000000..e2b89e84f
--- /dev/null
+++ b/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/sli/provider-base/src/test/resources/clearMultipleArrayValues.xml b/sli/provider-base/src/test/resources/clearMultipleArrayValues.xml
new file mode 100644
index 000000000..8f40058f1
--- /dev/null
+++ b/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/sli/provider-base/src/test/resources/clearNestedSubArrayValues.xml b/sli/provider-base/src/test/resources/clearNestedSubArrayValues.xml
new file mode 100644
index 000000000..a80b3e56c
--- /dev/null
+++ b/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/sli/provider-base/src/test/resources/clearSingleArrayValues.xml b/sli/provider-base/src/test/resources/clearSingleArrayValues.xml
new file mode 100644
index 000000000..56781a066
--- /dev/null
+++ b/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/sli/provider-base/src/test/resources/clearSingleSubArrayValues.xml b/sli/provider-base/src/test/resources/clearSingleSubArrayValues.xml
new file mode 100644
index 000000000..22f14f37b
--- /dev/null
+++ b/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/sli/provider-base/src/test/resources/clearSubArrayValues.xml b/sli/provider-base/src/test/resources/clearSubArrayValues.xml
new file mode 100644
index 000000000..cb25f38af
--- /dev/null
+++ b/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/sli/provider-base/src/test/resources/clearValues.xml b/sli/provider-base/src/test/resources/clearValues.xml
new file mode 100644
index 000000000..dc7f5c8a2
--- /dev/null
+++ b/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/sli/provider-base/src/test/resources/copyValues.xml b/sli/provider-base/src/test/resources/copyValues.xml
new file mode 100644
index 000000000..f56f7140a
--- /dev/null
+++ b/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/sli/provider-base/src/test/resources/expression.tests b/sli/provider-base/src/test/resources/expression.tests
new file mode 100644
index 000000000..848a0e7a4
--- /dev/null
+++ b/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/sli/provider-base/src/test/resources/expressions.xml b/sli/provider-base/src/test/resources/expressions.xml
new file mode 100755
index 000000000..79118570c
--- /dev/null
+++ b/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/sli/provider-base/src/test/resources/simplelogger.properties b/sli/provider-base/src/test/resources/simplelogger.properties
new file mode 100644
index 000000000..07ab67f70
--- /dev/null
+++ b/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/sli/provider/pom.xml b/sli/provider/pom.xml
new file mode 100755
index 000000000..3d5c389c4
--- /dev/null
+++ b/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/sli/provider/src/main/java/org/onap/ccsdk/sli/core/sli/provider/MdsalHelper.java b/sli/provider/src/main/java/org/onap/ccsdk/sli/core/sli/provider/MdsalHelper.java
new file mode 100755
index 000000000..d3ab6c33a
--- /dev/null
+++ b/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/sli/provider/src/main/java/org/onap/ccsdk/sli/core/sli/provider/PrintYangToProp.java b/sli/provider/src/main/java/org/onap/ccsdk/sli/core/sli/provider/PrintYangToProp.java
new file mode 100644
index 000000000..992ed64d4
--- /dev/null
+++ b/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/sli/provider/src/main/java/org/onap/ccsdk/sli/core/sli/provider/SvcLogicClassResolver.java b/sli/provider/src/main/java/org/onap/ccsdk/sli/core/sli/provider/SvcLogicClassResolver.java
new file mode 100644
index 000000000..08e957f1d
--- /dev/null
+++ b/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/sli/provider/src/main/java/org/onap/ccsdk/sli/core/sli/provider/SvcLogicPropertiesProviderImpl.java b/sli/provider/src/main/java/org/onap/ccsdk/sli/core/sli/provider/SvcLogicPropertiesProviderImpl.java
new file mode 100644
index 000000000..aad7a5a6d
--- /dev/null
+++ b/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/sli/provider/src/main/java/org/onap/ccsdk/sli/core/sli/provider/SvcLogicService.java b/sli/provider/src/main/java/org/onap/ccsdk/sli/core/sli/provider/SvcLogicService.java
new file mode 100644
index 000000000..a23594ee3
--- /dev/null
+++ b/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/sli/provider/src/main/java/org/onap/ccsdk/sli/core/sli/provider/SvcLogicServiceImpl.java b/sli/provider/src/main/java/org/onap/ccsdk/sli/core/sli/provider/SvcLogicServiceImpl.java
new file mode 100755
index 000000000..92c2aa49a
--- /dev/null
+++ b/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/sli/provider/src/main/resources/OSGI-INF/blueprint/sli-blueprint.xml b/sli/provider/src/main/resources/OSGI-INF/blueprint/sli-blueprint.xml
new file mode 100644
index 000000000..fb3ab9a03
--- /dev/null
+++ b/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/sli/provider/src/main/resources/org/opendaylight/blueprint/sli-blueprint.xml b/sli/provider/src/main/resources/org/opendaylight/blueprint/sli-blueprint.xml
new file mode 100644
index 000000000..fb3ab9a03
--- /dev/null
+++ b/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/sli/provider/src/test/java/org/onap/ccsdk/sli/core/sli/provider/ITCaseSvcLogicGraphExecutor.java b/sli/provider/src/test/java/org/onap/ccsdk/sli/core/sli/provider/ITCaseSvcLogicGraphExecutor.java
new file mode 100644
index 000000000..ad439cdb4
--- /dev/null
+++ b/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/sli/provider/src/test/java/org/onap/ccsdk/sli/core/sli/provider/MdsalHelperTest.java b/sli/provider/src/test/java/org/onap/ccsdk/sli/core/sli/provider/MdsalHelperTest.java
new file mode 100755
index 000000000..93d9931d0
--- /dev/null
+++ b/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/sli/provider/src/test/java/org/onap/ccsdk/sli/core/sli/provider/MdsalHelperTesterUtil.java b/sli/provider/src/test/java/org/onap/ccsdk/sli/core/sli/provider/MdsalHelperTesterUtil.java
new file mode 100644
index 000000000..2167b8101
--- /dev/null
+++ b/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/sli/provider/src/test/java/org/onap/ccsdk/sli/core/sli/provider/PrintYangToPropTest.java b/sli/provider/src/test/java/org/onap/ccsdk/sli/core/sli/provider/PrintYangToPropTest.java
new file mode 100644
index 000000000..50b7926a0
--- /dev/null
+++ b/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/sli/provider/src/test/java/org/opendaylight/yang/gen/v1/test/CosModelType.java b/sli/provider/src/test/java/org/opendaylight/yang/gen/v1/test/CosModelType.java
new file mode 100644
index 000000000..2aaaf8aa3
--- /dev/null
+++ b/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/sli/provider/src/test/java/org/opendaylight/yang/gen/v1/test/TestObject.java b/sli/provider/src/test/java/org/opendaylight/yang/gen/v1/test/TestObject.java
new file mode 100755
index 000000000..eacfc9f63
--- /dev/null
+++ b/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/sli/provider/src/test/java/org/opendaylight/yang/gen/v1/test/TestObjectBuilder.java b/sli/provider/src/test/java/org/opendaylight/yang/gen/v1/test/TestObjectBuilder.java
new file mode 100755
index 000000000..8301a0f05
--- /dev/null
+++ b/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/sli/provider/src/test/java/org/opendaylight/yang/gen/v1/test/WrapperObj.java b/sli/provider/src/test/java/org/opendaylight/yang/gen/v1/test/WrapperObj.java
new file mode 100644
index 000000000..bae0bdb1c
--- /dev/null
+++ b/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/sli/provider/src/test/resources/EnumerationMapping.properties b/sli/provider/src/test/resources/EnumerationMapping.properties
new file mode 100644
index 000000000..d0fb29710
--- /dev/null
+++ b/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/sli/provider/src/test/resources/executor.tests b/sli/provider/src/test/resources/executor.tests
new file mode 100755
index 000000000..5468c8d60
--- /dev/null
+++ b/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/sli/provider/src/test/resources/l3sdn.properties b/sli/provider/src/test/resources/l3sdn.properties
new file mode 100644
index 000000000..6f40ebca0
--- /dev/null
+++ b/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/sli/provider/src/test/resources/l3sdn_logic_v10.xml b/sli/provider/src/test/resources/l3sdn_logic_v10.xml
new file mode 100644
index 000000000..64397236b
--- /dev/null
+++ b/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/sli/provider/src/test/resources/l3vpnyang/ietf-l3vpn-svc-part@2017-09-21.yang b/sli/provider/src/test/resources/l3vpnyang/ietf-l3vpn-svc-part@2017-09-21.yang
new file mode 100755
index 000000000..4af080608
--- /dev/null
+++ b/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/sli/provider/src/test/resources/simplelogger.properties b/sli/provider/src/test/resources/simplelogger.properties
new file mode 100644
index 000000000..07ab67f70
--- /dev/null
+++ b/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/sli/provider/src/test/resources/svclogic.properties b/sli/provider/src/test/resources/svclogic.properties
new file mode 100644
index 000000000..426960f76
--- /dev/null
+++ b/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/sliPluginUtils/.gitignore b/sliPluginUtils/.gitignore
new file mode 100755
index 000000000..b73caf31e
--- /dev/null
+++ b/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/sliPluginUtils/.sonar/checkstyle.xml b/sliPluginUtils/.sonar/checkstyle.xml
new file mode 100755
index 000000000..3fa231535
--- /dev/null
+++ b/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/sliPluginUtils/.sonar/pmd.xml b/sliPluginUtils/.sonar/pmd.xml
new file mode 100755
index 000000000..80343b3bd
--- /dev/null
+++ b/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/sliPluginUtils/installer/pom.xml b/sliPluginUtils/installer/pom.xml
new file mode 100755
index 000000000..c133cd05b
--- /dev/null
+++ b/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/sliPluginUtils/installer/src/assembly/assemble_installer_zip.xml b/sliPluginUtils/installer/src/assembly/assemble_installer_zip.xml
new file mode 100644
index 000000000..2d3c0606d
--- /dev/null
+++ b/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/sliPluginUtils/installer/src/assembly/assemble_mvnrepo_zip.xml b/sliPluginUtils/installer/src/assembly/assemble_mvnrepo_zip.xml
new file mode 100644
index 000000000..63ef515a0
--- /dev/null
+++ b/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/sliPluginUtils/installer/src/main/resources/scripts/install-feature.sh b/sliPluginUtils/installer/src/main/resources/scripts/install-feature.sh
new file mode 100644
index 000000000..638c73394
--- /dev/null
+++ b/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/sliPluginUtils/pom.xml b/sliPluginUtils/pom.xml
new file mode 100755
index 000000000..974e0661c
--- /dev/null
+++ b/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/sliPluginUtils/provider/pom.xml b/sliPluginUtils/provider/pom.xml
new file mode 100755
index 000000000..086faf39e
--- /dev/null
+++ b/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/sliPluginUtils/provider/src/main/java/org/onap/ccsdk/sli/core/slipluginutils/SliPluginUtils.java b/sliPluginUtils/provider/src/main/java/org/onap/ccsdk/sli/core/slipluginutils/SliPluginUtils.java
new file mode 100644
index 000000000..2edb36dc4
--- /dev/null
+++ b/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/sliPluginUtils/provider/src/main/java/org/onap/ccsdk/sli/core/slipluginutils/SliStringUtils.java b/sliPluginUtils/provider/src/main/java/org/onap/ccsdk/sli/core/slipluginutils/SliStringUtils.java
new file mode 100644
index 000000000..9e3367d45
--- /dev/null
+++ b/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/sliPluginUtils/provider/src/main/java/org/onap/ccsdk/sli/core/slipluginutils/SvcLogicContextList.java b/sliPluginUtils/provider/src/main/java/org/onap/ccsdk/sli/core/slipluginutils/SvcLogicContextList.java
new file mode 100644
index 000000000..32e1aebdc
--- /dev/null
+++ b/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/sliPluginUtils/provider/src/main/java/org/onap/ccsdk/sli/core/slipluginutils/SvcLogicContextObject.java b/sliPluginUtils/provider/src/main/java/org/onap/ccsdk/sli/core/slipluginutils/SvcLogicContextObject.java
new file mode 100644
index 000000000..aa41a5c60
--- /dev/null
+++ b/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/sliPluginUtils/provider/src/main/java/org/onap/ccsdk/sli/core/slipluginutils/commondatastructures/YesNo.java b/sliPluginUtils/provider/src/main/java/org/onap/ccsdk/sli/core/slipluginutils/commondatastructures/YesNo.java
new file mode 100644
index 000000000..5db752e29
--- /dev/null
+++ b/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/sliPluginUtils/provider/src/main/java/org/onap/ccsdk/sli/core/slipluginutils/commondatastructures/package-info.java b/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/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/sliPluginUtils/provider/src/main/resources/OSGI-INF/blueprint/slipluginutils-blueprint.xml b/sliPluginUtils/provider/src/main/resources/OSGI-INF/blueprint/slipluginutils-blueprint.xml
new file mode 100644
index 000000000..534b92c93
--- /dev/null
+++ b/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/sliPluginUtils/provider/src/main/resources/org/opendaylight/blueprint/slipluginutils-blueprint.xml b/sliPluginUtils/provider/src/main/resources/org/opendaylight/blueprint/slipluginutils-blueprint.xml
new file mode 100644
index 000000000..534b92c93
--- /dev/null
+++ b/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/sliPluginUtils/provider/src/test/java/org/onap/ccsdk/sli/core/slipluginutils/SliPluginUtils_StaticFunctionsTest.java b/sliPluginUtils/provider/src/test/java/org/onap/ccsdk/sli/core/slipluginutils/SliPluginUtils_StaticFunctionsTest.java
new file mode 100644
index 000000000..42e7ceb94
--- /dev/null
+++ b/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/sliPluginUtils/provider/src/test/java/org/onap/ccsdk/sli/core/slipluginutils/SliPluginUtils_checkParametersTest.java b/sliPluginUtils/provider/src/test/java/org/onap/ccsdk/sli/core/slipluginutils/SliPluginUtils_checkParametersTest.java
new file mode 100644
index 000000000..f92271f7c
--- /dev/null
+++ b/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/sliPluginUtils/provider/src/test/java/org/onap/ccsdk/sli/core/slipluginutils/SliPluginUtils_ctxSortList.java b/sliPluginUtils/provider/src/test/java/org/onap/ccsdk/sli/core/slipluginutils/SliPluginUtils_ctxSortList.java
new file mode 100644
index 000000000..3d4469bf2
--- /dev/null
+++ b/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/sliPluginUtils/provider/src/test/java/org/onap/ccsdk/sli/core/slipluginutils/SliPluginUtils_ctxSortListTest.java b/sliPluginUtils/provider/src/test/java/org/onap/ccsdk/sli/core/slipluginutils/SliPluginUtils_ctxSortListTest.java
new file mode 100644
index 000000000..bf7cc1399
--- /dev/null
+++ b/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/sliPluginUtils/provider/src/test/java/org/onap/ccsdk/sli/core/slipluginutils/SliStringUtilsTest.java b/sliPluginUtils/provider/src/test/java/org/onap/ccsdk/sli/core/slipluginutils/SliStringUtilsTest.java
new file mode 100644
index 000000000..da7046f43
--- /dev/null
+++ b/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/sliPluginUtils/provider/src/test/java/org/onap/ccsdk/sli/core/slipluginutils/SvcLogicContextListTest.java b/sliPluginUtils/provider/src/test/java/org/onap/ccsdk/sli/core/slipluginutils/SvcLogicContextListTest.java
new file mode 100644
index 000000000..f916bbfca
--- /dev/null
+++ b/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/sliPluginUtils/provider/src/test/resources/2dArray.json b/sliPluginUtils/provider/src/test/resources/2dArray.json
new file mode 100644
index 000000000..2a94b46f4
--- /dev/null
+++ b/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/sliPluginUtils/provider/src/test/resources/3dArray.json b/sliPluginUtils/provider/src/test/resources/3dArray.json
new file mode 100644
index 000000000..149955596
--- /dev/null
+++ b/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/sliPluginUtils/provider/src/test/resources/ArrayMenu.json b/sliPluginUtils/provider/src/test/resources/ArrayMenu.json
new file mode 100644
index 000000000..26a24f292
--- /dev/null
+++ b/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/sliPluginUtils/provider/src/test/resources/EmbeddedEscapedJson.json b/sliPluginUtils/provider/src/test/resources/EmbeddedEscapedJson.json
new file mode 100644
index 000000000..dbb6d8d3a
--- /dev/null
+++ b/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/sliPluginUtils/provider/src/test/resources/EscapedJson.json b/sliPluginUtils/provider/src/test/resources/EscapedJson.json
new file mode 100644
index 000000000..a7719e819
--- /dev/null
+++ b/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/sliPluginUtils/provider/src/test/resources/JsonObject.json b/sliPluginUtils/provider/src/test/resources/JsonObject.json
new file mode 100644
index 000000000..0578368f8
--- /dev/null
+++ b/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/sliPluginUtils/provider/src/test/resources/ObjectMenu.json b/sliPluginUtils/provider/src/test/resources/ObjectMenu.json
new file mode 100644
index 000000000..56f842d48
--- /dev/null
+++ b/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/sliPluginUtils/provider/src/test/resources/Widget.json b/sliPluginUtils/provider/src/test/resources/Widget.json
new file mode 100644
index 000000000..6b90907ce
--- /dev/null
+++ b/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/sliapi/.gitignore b/sliapi/.gitignore
new file mode 100755
index 000000000..1558a77c4
--- /dev/null
+++ b/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/sliapi/README.txt b/sliapi/README.txt
new file mode 100755
index 000000000..f9f4a2ab5
--- /dev/null
+++ b/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/sliapi/installer/pom.xml b/sliapi/installer/pom.xml
new file mode 100755
index 000000000..1b3b24a45
--- /dev/null
+++ b/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/sliapi/installer/src/assembly/assemble_installer_zip.xml b/sliapi/installer/src/assembly/assemble_installer_zip.xml
new file mode 100644
index 000000000..2d3c0606d
--- /dev/null
+++ b/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/sliapi/installer/src/assembly/assemble_mvnrepo_zip.xml b/sliapi/installer/src/assembly/assemble_mvnrepo_zip.xml
new file mode 100644
index 000000000..c4eb9aa25
--- /dev/null
+++ b/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/sliapi/installer/src/main/resources/scripts/install-feature.sh b/sliapi/installer/src/main/resources/scripts/install-feature.sh
new file mode 100644
index 000000000..74b95b5c8
--- /dev/null
+++ b/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/sliapi/model/pom.xml b/sliapi/model/pom.xml
new file mode 100755
index 000000000..f23ad8da7
--- /dev/null
+++ b/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/sliapi/model/src/main/resources/sli-api.20161110.yaml b/sliapi/model/src/main/resources/sli-api.20161110.yaml
new file mode 100644
index 000000000..3420c66b5
--- /dev/null
+++ b/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/sliapi/model/swagger/pom.xml b/sliapi/model/swagger/pom.xml
new file mode 100644
index 000000000..db9ddbc42
--- /dev/null
+++ b/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/sliapi/model/swagger/src/main/json/sliapi.json b/sliapi/model/swagger/src/main/json/sliapi.json
new file mode 100644
index 000000000..b53663201
--- /dev/null
+++ b/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/sliapi/model/swagger/src/main/yaml/sliapi.yaml b/sliapi/model/swagger/src/main/yaml/sliapi.yaml
new file mode 100644
index 000000000..b1a63be5d
--- /dev/null
+++ b/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/sliapi/model/yang/pom.xml b/sliapi/model/yang/pom.xml
new file mode 100755
index 000000000..4d35f025c
--- /dev/null
+++ b/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/sliapi/model/yang/src/main/resources/sli-api.20161110.json b/sliapi/model/yang/src/main/resources/sli-api.20161110.json
new file mode 100644
index 000000000..1c6cdabfe
--- /dev/null
+++ b/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/sliapi/model/yang/src/main/resources/sli-api.20161110.yaml b/sliapi/model/yang/src/main/resources/sli-api.20161110.yaml
new file mode 100644
index 000000000..3420c66b5
--- /dev/null
+++ b/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/sliapi/model/yang/src/main/yang/sliapi.yang b/sliapi/model/yang/src/main/yang/sliapi.yang
new file mode 100755
index 000000000..98cbb2aa7
--- /dev/null
+++ b/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/sliapi/pom.xml b/sliapi/pom.xml
new file mode 100755
index 000000000..2af92cf7e
--- /dev/null
+++ b/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/sliapi/provider/pom.xml b/sliapi/provider/pom.xml
new file mode 100755
index 000000000..79f3d5560
--- /dev/null
+++ b/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/sliapi/provider/src/main/java/org/onap/ccsdk/sli/core/sliapi/SliapiHelper.java b/sliapi/provider/src/main/java/org/onap/ccsdk/sli/core/sliapi/SliapiHelper.java
new file mode 100644
index 000000000..95e51537f
--- /dev/null
+++ b/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/sliapi/provider/src/main/java/org/onap/ccsdk/sli/core/sliapi/SliapiProvider.java b/sliapi/provider/src/main/java/org/onap/ccsdk/sli/core/sliapi/SliapiProvider.java
new file mode 100644
index 000000000..449fc3822
--- /dev/null
+++ b/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/sliapi/provider/src/main/resources/OSGI-INF/blueprint/sliapi-blueprint.xml b/sliapi/provider/src/main/resources/OSGI-INF/blueprint/sliapi-blueprint.xml
new file mode 100644
index 000000000..875027e63
--- /dev/null
+++ b/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/sliapi/provider/src/main/resources/org/opendaylight/blueprint/sliapi-blueprint.xml b/sliapi/provider/src/main/resources/org/opendaylight/blueprint/sliapi-blueprint.xml
new file mode 100644
index 000000000..875027e63
--- /dev/null
+++ b/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/sliapi/provider/src/test/java/org/onap/ccsdk/sli/core/sliapi/SliapiHelperTest.java b/sliapi/provider/src/test/java/org/onap/ccsdk/sli/core/sliapi/SliapiHelperTest.java
new file mode 100644
index 000000000..228f6127e
--- /dev/null
+++ b/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/sliapi/provider/src/test/java/org/onap/ccsdk/sli/core/sliapi/TestSliapiProvider.java b/sliapi/provider/src/test/java/org/onap/ccsdk/sli/core/sliapi/TestSliapiProvider.java
new file mode 100644
index 000000000..f48cf783b
--- /dev/null
+++ b/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/sliapi/provider/src/test/resources/simplelogger.properties b/sliapi/provider/src/test/resources/simplelogger.properties
new file mode 100644
index 000000000..2f7d8ea0b
--- /dev/null
+++ b/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/sliapi/provider/src/test/resources/sli_healthcheck.xml b/sliapi/provider/src/test/resources/sli_healthcheck.xml
new file mode 100644
index 000000000..d512f546f
--- /dev/null
+++ b/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/sliapi/provider/src/test/resources/svclogic.properties b/sliapi/provider/src/test/resources/svclogic.properties
new file mode 100644
index 000000000..426960f76
--- /dev/null
+++ b/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/src/site/apt/nodes.apt b/src/site/apt/nodes.apt
new file mode 100644
index 000000000..95a51467c
--- /dev/null
+++ b/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/src/site/site.xml b/src/site/site.xml
new file mode 100644
index 000000000..af081b167
--- /dev/null
+++ b/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/utils/installer/pom.xml b/utils/installer/pom.xml
new file mode 100755
index 000000000..829a33051
--- /dev/null
+++ b/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/utils/installer/src/assembly/assemble_installer_zip.xml b/utils/installer/src/assembly/assemble_installer_zip.xml
new file mode 100755
index 000000000..a6a22a9ba
--- /dev/null
+++ b/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/utils/installer/src/assembly/assemble_mvnrepo_zip.xml b/utils/installer/src/assembly/assemble_mvnrepo_zip.xml
new file mode 100755
index 000000000..86b07f1f3
--- /dev/null
+++ b/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/utils/installer/src/main/resources/scripts/install-feature.sh b/utils/installer/src/main/resources/scripts/install-feature.sh
new file mode 100644
index 000000000..e16e79a12
--- /dev/null
+++ b/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/utils/pom.xml b/utils/pom.xml
new file mode 100755
index 000000000..b8c196cff
--- /dev/null
+++ b/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/utils/provider/pom.xml b/utils/provider/pom.xml
new file mode 100644
index 000000000..3d4fd856d
--- /dev/null
+++ b/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/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/DefaultFileResolver.java b/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/DefaultFileResolver.java
new file mode 100644
index 000000000..8938aa6e7
--- /dev/null
+++ b/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/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/EnvVarFileResolver.java b/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/EnvVarFileResolver.java
new file mode 100755
index 000000000..518fb30d3
--- /dev/null
+++ b/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/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/JREFileResolver.java b/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/JREFileResolver.java
new file mode 100755
index 000000000..c4a4fca47
--- /dev/null
+++ b/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/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/KarafRootFileResolver.java b/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/KarafRootFileResolver.java
new file mode 100644
index 000000000..0cb754504
--- /dev/null
+++ b/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/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/PathValidator.java b/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/PathValidator.java
new file mode 100644
index 000000000..08f0fc050
--- /dev/null
+++ b/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/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/PropertiesFileResolver.java b/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/PropertiesFileResolver.java
new file mode 100644
index 000000000..bfb417dca
--- /dev/null
+++ b/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/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/common/BundleContextFileResolver.java b/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/common/BundleContextFileResolver.java
new file mode 100755
index 000000000..356009f3f
--- /dev/null
+++ b/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/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/common/CoreDefaultFileResolver.java b/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/common/CoreDefaultFileResolver.java
new file mode 100755
index 000000000..4d7e90261
--- /dev/null
+++ b/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/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/common/SdncConfigEnvVarFileResolver.java b/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/common/SdncConfigEnvVarFileResolver.java
new file mode 100755
index 000000000..51b6134f7
--- /dev/null
+++ b/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/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/dblib/DblibDefaultFileResolver.java b/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/dblib/DblibDefaultFileResolver.java
new file mode 100755
index 000000000..082bdf403
--- /dev/null
+++ b/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/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/dblib/DblibEnvVarFileResolver.java b/utils/provider/src/main/java/org/onap/ccsdk/sli/core/utils/dblib/DblibEnvVarFileResolver.java
new file mode 100644
index 000000000..959271cb7
--- /dev/null
+++ b/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/utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/JREFileResolverTest.java b/utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/JREFileResolverTest.java
new file mode 100644
index 000000000..8a066f057
--- /dev/null
+++ b/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/utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/KarafRootFileResolverTest.java b/utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/KarafRootFileResolverTest.java
new file mode 100644
index 000000000..df16b41d0
--- /dev/null
+++ b/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/utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/common/BundleContexFileResolverTest.java b/utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/common/BundleContexFileResolverTest.java
new file mode 100644
index 000000000..7ddf550b0
--- /dev/null
+++ b/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/utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/common/CoreDefaultFileResolverTest.java b/utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/common/CoreDefaultFileResolverTest.java
new file mode 100644
index 000000000..f1f5f2244
--- /dev/null
+++ b/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/utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/common/SdncConfigEnvVarFileResolverTest.java b/utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/common/SdncConfigEnvVarFileResolverTest.java
new file mode 100644
index 000000000..130dc0a1e
--- /dev/null
+++ b/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/utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/dblib/DblibDefaultFileResolverTest.java b/utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/dblib/DblibDefaultFileResolverTest.java
new file mode 100644
index 000000000..834a8c449
--- /dev/null
+++ b/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/utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/dblib/DblibEnvVarFileResolverTest.java b/utils/provider/src/test/java/org/onap/ccsdk/sli/core/utils/dblib/DblibEnvVarFileResolverTest.java
new file mode 100644
index 000000000..b5150ab67
--- /dev/null
+++ b/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