From c74f7b13b573386e70c10721fc391624ee792ed6 Mon Sep 17 00:00:00 2001 From: michaere Date: Mon, 5 Mar 2018 16:33:32 +0000 Subject: [PATCH] Port champ-microservice project restructure Includes project restructure and introduction of a parent pom. The original source folder and core functionality is now held within champ-lib, with champ-service forming the ajsc microservice from which it injects champ-lib core functionality. Issue-ID: AAI-813 Change-Id: I2ce0c4a70e485665276e7955572de23969deb706 Signed-off-by: michaere --- README.md | 1024 ++++++++++++------- License.txt => champ-lib/License.txt | 0 champ-lib/champ-core/License.txt | 21 + champ-lib/champ-core/pom.xml | 119 +++ .../java/org/onap/aai/champcore}/ChampAPI.java | 8 +- .../org/onap/aai/champcore}/ChampCapabilities.java | 2 +- .../java/org/onap/aai/champcore/ChampGraph.java | 627 ++++++++++++ .../org/onap/aai/champcore/ChampTransaction.java | 73 ++ .../java/org/onap/aai/champcore/FormatMapper.java | 30 + .../java/org/onap/aai/champcore/Formatter.java | 77 ++ .../aai/champcore/NoOpTinkerPopTransaction.java | 57 ++ .../champcore/event/AbstractLoggingChampGraph.java | 792 +++++++++++++++ .../org/onap/aai/champcore}/event/ChampEvent.java | 41 +- .../exceptions/ChampIndexNotExistsException.java | 2 +- .../exceptions/ChampMarshallingException.java | 2 +- .../exceptions/ChampObjectNotExistsException.java | 2 +- .../ChampRelationshipNotExistsException.java | 2 +- .../exceptions/ChampSchemaViolationException.java | 2 +- .../exceptions/ChampTransactionException.java | 41 + .../exceptions/ChampUnmarshallingException.java | 2 +- .../graph/impl/AbstractTinkerpopChampGraph.java | 1068 ++++++++++++++++++++ .../graph/impl/AbstractValidatingChampGraph.java | 293 ++++++ .../aai/champcore}/graph/impl/ChampAPIImpl.java | 33 +- .../graph/impl/InMemoryChampGraphImpl.java | 51 +- .../champcore/graph/impl/TinkerpopTransaction.java | 164 +++ .../java/org/onap/aai/champcore}/ie/Exporter.java | 4 +- .../aai/champcore}/ie/GraphMLImporterExporter.java | 61 +- .../java/org/onap/aai/champcore}/ie/Importer.java | 4 +- .../aai/champcore}/model/ChampCardinality.java | 2 +- .../model/ChampConnectionConstraint.java | 2 +- .../model/ChampConnectionMultiplicity.java | 2 +- .../onap/aai/champcore}/model/ChampElement.java | 6 +- .../org/onap/aai/champcore}/model/ChampField.java | 2 +- .../org/onap/aai/champcore/model/ChampObject.java | 280 +++++ .../champcore}/model/ChampObjectConstraint.java | 2 +- .../aai/champcore}/model/ChampObjectIndex.java | 6 +- .../onap/aai/champcore}/model/ChampPartition.java | 14 +- .../champcore}/model/ChampPropertyConstraint.java | 2 +- .../aai/champcore}/model/ChampRelationship.java | 32 +- .../model/ChampRelationshipConstraint.java | 2 +- .../champcore}/model/ChampRelationshipIndex.java | 6 +- .../org/onap/aai/champcore}/model/ChampSchema.java | 9 +- .../aai/champcore}/model/fluent/BuildStep.java | 2 +- .../onap/aai/champcore}/model/fluent/KeyStep.java | 4 +- .../champcore}/model/fluent/PropertiesStep.java | 2 +- .../model/fluent/index/CreateObjectIndexable.java | 2 +- .../fluent/index/CreateRelationshipIndexable.java | 2 +- .../model/fluent/index/ObjectIndexFieldStep.java | 8 +- .../model/fluent/index/ObjectIndexTypeStep.java | 2 +- .../fluent/index/RelationshipIndexFieldStep.java | 8 +- .../fluent/index/RelationshipIndexTypeStep.java | 2 +- .../index/impl/CreateObjectIndexableImpl.java | 16 +- .../impl/CreateRelationshipIndexableImpl.java | 14 +- .../model/fluent/object/CreateChampObjectable.java | 6 +- .../fluent/object/ObjectBuildOrPropertiesStep.java | 8 +- .../object/ObjectBuildOrPropertiesStepImpl.java | 6 +- .../model/fluent/object/ObjectKeyStepImpl.java | 8 +- .../object/impl/CreateChampObjectableImpl.java | 12 +- .../fluent/partition/CreateChampPartitionable.java | 10 +- .../partition/impl/CreateChampPartionableImpl.java | 10 +- .../relationship/CreateChampRelationshipable.java | 6 +- .../RelationshipBuildOrPropertiesStep.java | 8 +- .../relationship/SourceBuildOrPropertiesStep.java | 2 +- .../model/fluent/relationship/SourceFromStep.java | 4 +- .../model/fluent/relationship/SourceKeyStep.java | 2 +- .../model/fluent/relationship/SourceStep.java | 2 +- .../fluent/relationship/SourceTypeOrFromStep.java | 2 +- .../model/fluent/relationship/SourceTypeStep.java | 2 +- .../relationship/TargetBuildOrPropertiesStep.java | 2 +- .../model/fluent/relationship/TargetFromStep.java | 4 +- .../model/fluent/relationship/TargetKeyStep.java | 2 +- .../model/fluent/relationship/TargetStep.java | 2 +- .../fluent/relationship/TargetTypeOrFromStep.java | 2 +- .../model/fluent/relationship/TargetTypeStep.java | 2 +- .../impl/ChampRelationshipKeyStepImpl.java | 8 +- .../impl/CreateChampRelationshipableImpl.java | 12 +- .../RelationshipBuildOrPropertiesStepImpl.java | 6 +- .../impl/SourceBuildOrPropertiesStepImpl.java | 10 +- .../relationship/impl/SourceKeyStepImpl.java | 12 +- .../fluent/relationship/impl/SourceStepImpl.java | 8 +- .../impl/SourceTypeOrFromStepImpl.java | 12 +- .../impl/TargetBuildOrPropertiesStepImpl.java | 10 +- .../relationship/impl/TargetKeyStepImpl.java | 10 +- .../fluent/relationship/impl/TargetStepImpl.java | 10 +- .../impl/TargetTypeOrFromStepImpl.java | 12 +- .../model/fluent/schema/CreateChampSchemable.java | 8 +- .../fluent/schema/ObjectConstraintBuildStep.java | 4 +- .../fluent/schema/ObjectConstraintFieldStep.java | 2 +- .../schema/ObjectConstraintFieldTypeStep.java | 4 +- .../schema/ObjectConstraintPropertyStep.java | 4 +- .../ObjectConstraintRequiredOptionalStep.java | 4 +- .../fluent/schema/ObjectConstraintSubStep.java | 2 +- .../fluent/schema/ObjectConstraintTypeStep.java | 4 +- .../schema/RelationshipConstraintBuildStep.java | 4 +- .../schema/RelationshipConstraintFieldStep.java | 2 +- .../RelationshipConstraintFieldTypeStep.java | 4 +- .../RelationshipConstraintMultiplicityStep.java | 6 +- ...elationshipConstraintPropertyOptionalsStep.java | 2 +- ...RelationshipConstraintRequiredOptionalStep.java | 2 +- .../schema/RelationshipConstraintSourceStep.java | 2 +- .../schema/RelationshipConstraintSubStep.java | 4 +- .../schema/RelationshipConstraintTargetStep.java | 2 +- .../schema/RelationshipConstraintTypeStep.java | 2 +- .../schema/impl/CreateChampSchemableImpl.java | 18 +- .../schema/impl/ObjectConstraintBuildStepImpl.java | 10 +- .../schema/impl/ObjectConstraintFieldStepImpl.java | 12 +- .../impl/ObjectConstraintPropertyStepImpl.java | 12 +- .../schema/impl/ObjectConstraintSubStepImpl.java | 22 +- .../impl/RelationshipConstraintBuildStepImpl.java | 12 +- ...ionshipConstraintPropertyOptionalsStepImpl.java | 16 +- ...tionshipConstraintRequiredOptionalStepImpl.java | 16 +- .../impl/RelationshipConstraintSubStepImpl.java | 32 +- .../schema/AlwaysValidChampSchemaEnforcer.java | 14 +- .../aai/champcore}/schema/ChampSchemaEnforcer.java | 16 +- .../schema/DefaultChampSchemaEnforcer.java | 24 +- .../onap/aai/champcore}/transform/Champformer.java | 8 +- .../champcore}/transform/TinkerpopChampformer.java | 12 +- .../aai/champcore/concurrency/ConcurrencyTest.java | 74 ++ .../onap/aai/champcore/core/BaseChampAPITest.java | 34 + .../org/onap/aai/champcore/core/ChampAPITest.java | 242 +++++ .../onap/aai/champcore}/core/ChampElementTest.java | 8 +- .../onap/aai/champcore}/core/ChampFieldTest.java | 4 +- .../aai/champcore}/core/ChampObjectIndexTest.java | 30 +- .../onap/aai/champcore/core/ChampObjectTest.java | 359 +++++++ .../aai/champcore/core/ChampPartitionTest.java | 226 +++++ .../core/ChampPropertyConstraintTest.java | 8 +- .../champcore/core/ChampRelationshipIndexTest.java | 179 ++++ .../aai/champcore/core/ChampRelationshipTest.java | 310 ++++++ .../onap/aai/champcore}/core/ChampSchemaTest.java | 74 +- .../aai/champcore/core/ChampTransactionTest.java | 502 +++++++++ .../event/AbstractLoggingChampGraphTest.java | 365 +++++-- .../champcore}/exceptions/ChampExceptionTest.java | 8 +- .../org/onap/aai/champcore}/ie/ExportTest.java | 8 +- .../org/onap/aai/champcore}/ie/ImportTest.java | 14 +- .../src}/test/resources/import-test.graphml | 0 .../champ-core/src}/test/resources/logback.xml | 0 champ-lib/champ-janus/License.txt | 21 + champ-lib/champ-janus/pom.xml | 188 ++++ .../onap/aai/champjanus/graph/impl/GraphSON.java | 66 ++ .../champjanus/graph/impl/JanusChampGraphImpl.java | 493 +++++++++ .../champjanus/concurrency/ConcurrencyTest.java | 33 + .../org/onap/aai/champjanus/core/ChampAPITest.java | 38 + .../aai/champjanus/core/ChampObjectIndexTest.java | 46 + .../core/ChampRelationshipIndexTest.java | 38 + .../onap/aai/champjanus/core/ChampSchemaTest.java | 37 + .../aai/champjanus/core/JanusChampSetupTest.java | 74 ++ champ-lib/champ-titan/License.txt | 21 + champ-lib/champ-titan/pom.xml | 188 ++++ .../onap/aai/champtitan/graph/impl/GraphSON.java | 66 ++ .../champtitan/graph/impl/TitanChampGraphImpl.java | 474 +++++++++ .../champtitan}/perf/ChampAPIPerformanceTest.java | 176 ++-- .../champtitan/concurrency/ConcurrencyTest.java | 33 + .../org/onap/aai/champtitan/core/ChampAPITest.java | 40 + .../aai/champtitan/core/ChampObjectIndexTest.java | 48 + .../core/ChampRelationshipIndexTest.java | 38 + .../onap/aai/champtitan/core/ChampSchemaTest.java | 37 + .../aai/champtitan/core/ChampTransactionTest.java | 335 ++++++ .../aai/champtitan/core/TitanChampSetupTest.java | 74 ++ champ-lib/pom.xml | 300 ++++++ champ-service-deps-janus/pom.xml | 125 +++ champ-service-deps-titan/pom.xml | 122 +++ champ-service/License.txt | 21 + champ-service/ajsc-shared-config/etc/logback.xml | 235 +++++ champ-service/antBuild/build.xml | 178 ++++ .../auth/champion-service_policy.json-REPLACE | 1 + .../appconfig-local/auth/tomcat_keystore-REPLACE | 1 + .../appconfig-local/champ-api.properties-REPLACE | 7 + .../etc/appprops/AAFUserRoles.properties | 12 + .../appprops/PostProcessorInterceptors.properties | 2 + .../appprops/PreProcessorInterceptors.properties | 3 + .../etc/appprops/app-intercepts.properties | 7 + .../etc/appprops/methodMapper.properties | 45 + .../etc/sysprops/sys-props.properties | 117 +++ champ-service/pom.xml | 360 +++++++ .../champ-service/v1/conf/jaxrsBeans.groovy | 11 + .../champ-service/v1/docs/README.txt | 1 + .../champ-service/v1/lib/README.txt | 1 + .../champ-service/v1/routes/champ.route | 4 + .../champ-service/v1/routes/jaxrsExample.route | 5 + .../src/main/assemble/ajsc_module_assembly.xml | 66 ++ .../src/main/assemble/ajsc_props_assembly.xml | 23 + .../src/main/assemble/ajsc_runtime_assembly.xml | 44 + champ-service/src/main/bin/start.sh | 94 ++ champ-service/src/main/config/ajsc-chef.jks | Bin 0 -> 5256 bytes champ-service/src/main/config/ajsc-jetty.xml | 114 +++ .../src/main/config/ajsc-override-web.xml | 50 + champ-service/src/main/config/ajscJetty.jks | Bin 0 -> 3736 bytes champ-service/src/main/config/cadi.properties | 28 + .../src/main/config/jul-redirect.properties | 13 + champ-service/src/main/config/keyfile | 27 + champ-service/src/main/config/runner-web.xml | 94 ++ champ-service/src/main/docker/Dockerfile | 34 + .../src/main/java/org/onap/champ/ChampRESTAPI.java | 568 +++++++++++ .../champ/async/ChampAsyncRequestProcessor.java | 327 ++++++ .../champ/async/ChampAsyncResponsePublisher.java | 160 +++ .../onap/champ/entity/ChampObjectDeserializer.java | 67 ++ .../onap/champ/entity/ChampObjectSerializer.java | 54 + .../entity/ChampRelationshipDeserializer.java | 73 ++ .../champ/entity/ChampRelationshipSerializer.java | 55 + .../main/java/org/onap/champ/event/GraphEvent.java | 245 +++++ .../java/org/onap/champ/event/GraphEventEdge.java | 221 ++++ .../org/onap/champ/event/GraphEventVertex.java | 187 ++++ .../champ/exception/ChampServiceException.java | 62 ++ .../org/onap/champ/service/ChampDataService.java | 355 +++++++ .../org/onap/champ/service/ChampThreadFactory.java | 47 + .../onap/champ/service/ChampTransactionCache.java | 77 ++ .../org/onap/champ/service/ChampUUIDService.java | 115 +++ .../java/org/onap/champ/service/EchoService.java | 54 + .../org/onap/champ/service/logging/ChampMsgs.java | 130 +++ .../onap/champ/service/logging/LoggingUtil.java | 92 ++ .../java/org/onap/champ/util/ChampProperties.java | 53 + .../org/onap/champ/util/ChampServiceConstants.java | 14 + .../services/javax.ws.rs.client.ClientBuilder | 1 + .../main/resources/logging/ChampMsgs.properties | 78 ++ ...ame__#__module.ajsc.namespace.version__.context | 1 + .../src/main/runtime/context/default#0.context | 1 + ...e.name__#__module.ajsc.namespace.version__.json | 1 + .../src/main/runtime/shiroRole/ajscadmin.json | 1 + ...ontextadmin#__module.ajsc.namespace.name__.json | 1 + .../runtime/shiroRole/contextadmin#default.json | 1 + champ-service/src/main/runtime/shiroUser/ajsc.json | 1 + .../main/runtime/shiroUserRole/ajsc#ajscadmin.json | 1 + ...ontextadmin#__module.ajsc.namespace.name__.json | 1 + .../shiroUserRole/ajsc#contextadmin#default.json | 1 + pom.xml | 412 +------- src/main/java/org/onap/aai/champ/ChampGraph.java | 308 ------ .../graph/impl/AbstractGremlinChampGraph.java | 350 ------- .../graph/impl/AbstractTinkerpopChampGraph.java | 753 -------------- .../graph/impl/AbstractValidatingChampGraph.java | 176 ---- .../aai/champ/graph/impl/TitanChampGraphImpl.java | 458 --------- .../java/org/onap/aai/champ/model/ChampObject.java | 239 ----- .../aai/champ/concurrency/ConcurrencyTest.java | 72 -- .../org/onap/aai/champ/core/BaseChampAPITest.java | 50 - .../java/org/onap/aai/champ/core/ChampAPITest.java | 239 ----- .../org/onap/aai/champ/core/ChampObjectTest.java | 331 ------ .../onap/aai/champ/core/ChampPartitionTest.java | 195 ---- .../aai/champ/core/ChampRelationshipIndexTest.java | 175 ---- .../onap/aai/champ/core/ChampRelationshipTest.java | 261 ----- version.properties | 4 +- 239 files changed, 14729 insertions(+), 5022 deletions(-) rename License.txt => champ-lib/License.txt (100%) create mode 100644 champ-lib/champ-core/License.txt create mode 100644 champ-lib/champ-core/pom.xml rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/ChampAPI.java (90%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/ChampCapabilities.java (97%) create mode 100644 champ-lib/champ-core/src/main/java/org/onap/aai/champcore/ChampGraph.java create mode 100644 champ-lib/champ-core/src/main/java/org/onap/aai/champcore/ChampTransaction.java create mode 100644 champ-lib/champ-core/src/main/java/org/onap/aai/champcore/FormatMapper.java create mode 100644 champ-lib/champ-core/src/main/java/org/onap/aai/champcore/Formatter.java create mode 100644 champ-lib/champ-core/src/main/java/org/onap/aai/champcore/NoOpTinkerPopTransaction.java create mode 100644 champ-lib/champ-core/src/main/java/org/onap/aai/champcore/event/AbstractLoggingChampGraph.java rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/event/ChampEvent.java (81%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/exceptions/ChampIndexNotExistsException.java (97%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/exceptions/ChampMarshallingException.java (97%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/exceptions/ChampObjectNotExistsException.java (97%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/exceptions/ChampRelationshipNotExistsException.java (97%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/exceptions/ChampSchemaViolationException.java (97%) create mode 100644 champ-lib/champ-core/src/main/java/org/onap/aai/champcore/exceptions/ChampTransactionException.java rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/exceptions/ChampUnmarshallingException.java (97%) create mode 100644 champ-lib/champ-core/src/main/java/org/onap/aai/champcore/graph/impl/AbstractTinkerpopChampGraph.java create mode 100644 champ-lib/champ-core/src/main/java/org/onap/aai/champcore/graph/impl/AbstractValidatingChampGraph.java rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/graph/impl/ChampAPIImpl.java (76%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/graph/impl/InMemoryChampGraphImpl.java (81%) create mode 100644 champ-lib/champ-core/src/main/java/org/onap/aai/champcore/graph/impl/TinkerpopTransaction.java rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/ie/Exporter.java (93%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/ie/GraphMLImporterExporter.java (90%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/ie/Importer.java (93%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/ChampCardinality.java (96%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/ChampConnectionConstraint.java (98%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/ChampConnectionMultiplicity.java (97%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/ChampElement.java (91%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/ChampField.java (98%) create mode 100644 champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/ChampObject.java rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/ChampObjectConstraint.java (98%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/ChampObjectIndex.java (92%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/ChampPartition.java (90%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/ChampPropertyConstraint.java (98%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/ChampRelationship.java (89%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/ChampRelationshipConstraint.java (99%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/ChampRelationshipIndex.java (92%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/ChampSchema.java (96%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/fluent/BuildStep.java (96%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/fluent/KeyStep.java (96%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/fluent/PropertiesStep.java (96%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/fluent/index/CreateObjectIndexable.java (95%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/fluent/index/CreateRelationshipIndexable.java (95%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/fluent/index/ObjectIndexFieldStep.java (87%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/fluent/index/ObjectIndexTypeStep.java (95%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/fluent/index/RelationshipIndexFieldStep.java (87%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/fluent/index/RelationshipIndexTypeStep.java (95%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/fluent/index/impl/CreateObjectIndexableImpl.java (82%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/fluent/index/impl/CreateRelationshipIndexableImpl.java (79%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/fluent/object/CreateChampObjectable.java (88%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/fluent/object/ObjectBuildOrPropertiesStep.java (84%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/fluent/object/ObjectBuildOrPropertiesStepImpl.java (91%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/fluent/object/ObjectKeyStepImpl.java (87%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/fluent/object/impl/CreateChampObjectableImpl.java (78%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/fluent/partition/CreateChampPartitionable.java (83%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/fluent/partition/impl/CreateChampPartionableImpl.java (84%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/fluent/relationship/CreateChampRelationshipable.java (88%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/fluent/relationship/RelationshipBuildOrPropertiesStep.java (83%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/fluent/relationship/SourceBuildOrPropertiesStep.java (95%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/fluent/relationship/SourceFromStep.java (91%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/fluent/relationship/SourceKeyStep.java (95%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/fluent/relationship/SourceStep.java (95%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/fluent/relationship/SourceTypeOrFromStep.java (95%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/fluent/relationship/SourceTypeStep.java (95%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/fluent/relationship/TargetBuildOrPropertiesStep.java (95%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/fluent/relationship/TargetFromStep.java (91%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/fluent/relationship/TargetKeyStep.java (95%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/fluent/relationship/TargetStep.java (95%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/fluent/relationship/TargetTypeOrFromStep.java (95%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/fluent/relationship/TargetTypeStep.java (95%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/fluent/relationship/impl/ChampRelationshipKeyStepImpl.java (87%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/fluent/relationship/impl/CreateChampRelationshipableImpl.java (81%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/fluent/relationship/impl/RelationshipBuildOrPropertiesStepImpl.java (89%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/fluent/relationship/impl/SourceBuildOrPropertiesStepImpl.java (85%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/fluent/relationship/impl/SourceKeyStepImpl.java (83%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/fluent/relationship/impl/SourceStepImpl.java (85%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/fluent/relationship/impl/SourceTypeOrFromStepImpl.java (83%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/fluent/relationship/impl/TargetBuildOrPropertiesStepImpl.java (87%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/fluent/relationship/impl/TargetKeyStepImpl.java (86%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/fluent/relationship/impl/TargetStepImpl.java (84%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/fluent/relationship/impl/TargetTypeOrFromStepImpl.java (83%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/fluent/schema/CreateChampSchemable.java (88%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/fluent/schema/ObjectConstraintBuildStep.java (91%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/fluent/schema/ObjectConstraintFieldStep.java (95%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/fluent/schema/ObjectConstraintFieldTypeStep.java (92%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/fluent/schema/ObjectConstraintPropertyStep.java (91%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/fluent/schema/ObjectConstraintRequiredOptionalStep.java (92%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/fluent/schema/ObjectConstraintSubStep.java (95%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/fluent/schema/ObjectConstraintTypeStep.java (95%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/fluent/schema/RelationshipConstraintBuildStep.java (91%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/fluent/schema/RelationshipConstraintFieldStep.java (95%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/fluent/schema/RelationshipConstraintFieldTypeStep.java (92%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/fluent/schema/RelationshipConstraintMultiplicityStep.java (88%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/fluent/schema/RelationshipConstraintPropertyOptionalsStep.java (95%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/fluent/schema/RelationshipConstraintRequiredOptionalStep.java (95%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/fluent/schema/RelationshipConstraintSourceStep.java (95%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/fluent/schema/RelationshipConstraintSubStep.java (92%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/fluent/schema/RelationshipConstraintTargetStep.java (95%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/fluent/schema/RelationshipConstraintTypeStep.java (95%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/fluent/schema/impl/CreateChampSchemableImpl.java (77%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/fluent/schema/impl/ObjectConstraintBuildStepImpl.java (83%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/fluent/schema/impl/ObjectConstraintFieldStepImpl.java (81%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/fluent/schema/impl/ObjectConstraintPropertyStepImpl.java (81%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/fluent/schema/impl/ObjectConstraintSubStepImpl.java (84%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/fluent/schema/impl/RelationshipConstraintBuildStepImpl.java (80%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/fluent/schema/impl/RelationshipConstraintPropertyOptionalsStepImpl.java (82%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/fluent/schema/impl/RelationshipConstraintRequiredOptionalStepImpl.java (82%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/model/fluent/schema/impl/RelationshipConstraintSubStepImpl.java (86%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/schema/AlwaysValidChampSchemaEnforcer.java (79%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/schema/ChampSchemaEnforcer.java (77%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/schema/DefaultChampSchemaEnforcer.java (90%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/transform/Champformer.java (86%) rename {src/main/java/org/onap/aai/champ => champ-lib/champ-core/src/main/java/org/onap/aai/champcore}/transform/TinkerpopChampformer.java (90%) create mode 100644 champ-lib/champ-core/src/test/java/org/onap/aai/champcore/concurrency/ConcurrencyTest.java create mode 100644 champ-lib/champ-core/src/test/java/org/onap/aai/champcore/core/BaseChampAPITest.java create mode 100644 champ-lib/champ-core/src/test/java/org/onap/aai/champcore/core/ChampAPITest.java rename {src/test/java/org/onap/aai/champ => champ-lib/champ-core/src/test/java/org/onap/aai/champcore}/core/ChampElementTest.java (91%) rename {src/test/java/org/onap/aai/champ => champ-lib/champ-core/src/test/java/org/onap/aai/champcore}/core/ChampFieldTest.java (95%) rename {src/test/java/org/onap/aai/champ => champ-lib/champ-core/src/test/java/org/onap/aai/champcore}/core/ChampObjectIndexTest.java (91%) create mode 100644 champ-lib/champ-core/src/test/java/org/onap/aai/champcore/core/ChampObjectTest.java create mode 100644 champ-lib/champ-core/src/test/java/org/onap/aai/champcore/core/ChampPartitionTest.java rename {src/test/java/org/onap/aai/champ => champ-lib/champ-core/src/test/java/org/onap/aai/champcore}/core/ChampPropertyConstraintTest.java (91%) create mode 100644 champ-lib/champ-core/src/test/java/org/onap/aai/champcore/core/ChampRelationshipIndexTest.java create mode 100644 champ-lib/champ-core/src/test/java/org/onap/aai/champcore/core/ChampRelationshipTest.java rename {src/test/java/org/onap/aai/champ => champ-lib/champ-core/src/test/java/org/onap/aai/champcore}/core/ChampSchemaTest.java (93%) create mode 100644 champ-lib/champ-core/src/test/java/org/onap/aai/champcore/core/ChampTransactionTest.java rename {src/test/java/org/onap/aai/champ => champ-lib/champ-core/src/test/java/org/onap/aai/champcore}/event/AbstractLoggingChampGraphTest.java (77%) rename {src/test/java/org/onap/aai/champ => champ-lib/champ-core/src/test/java/org/onap/aai/champcore}/exceptions/ChampExceptionTest.java (91%) rename {src/test/java/org/onap/aai/champ => champ-lib/champ-core/src/test/java/org/onap/aai/champcore}/ie/ExportTest.java (85%) rename {src/test/java/org/onap/aai/champ => champ-lib/champ-core/src/test/java/org/onap/aai/champcore}/ie/ImportTest.java (88%) rename {src => champ-lib/champ-core/src}/test/resources/import-test.graphml (100%) mode change 100755 => 100644 rename {src => champ-lib/champ-core/src}/test/resources/logback.xml (100%) create mode 100644 champ-lib/champ-janus/License.txt create mode 100644 champ-lib/champ-janus/pom.xml create mode 100644 champ-lib/champ-janus/src/main/java/org/onap/aai/champjanus/graph/impl/GraphSON.java create mode 100644 champ-lib/champ-janus/src/main/java/org/onap/aai/champjanus/graph/impl/JanusChampGraphImpl.java create mode 100644 champ-lib/champ-janus/src/test/java/org/onap/aai/champjanus/concurrency/ConcurrencyTest.java create mode 100644 champ-lib/champ-janus/src/test/java/org/onap/aai/champjanus/core/ChampAPITest.java create mode 100644 champ-lib/champ-janus/src/test/java/org/onap/aai/champjanus/core/ChampObjectIndexTest.java create mode 100644 champ-lib/champ-janus/src/test/java/org/onap/aai/champjanus/core/ChampRelationshipIndexTest.java create mode 100644 champ-lib/champ-janus/src/test/java/org/onap/aai/champjanus/core/ChampSchemaTest.java create mode 100644 champ-lib/champ-janus/src/test/java/org/onap/aai/champjanus/core/JanusChampSetupTest.java create mode 100644 champ-lib/champ-titan/License.txt create mode 100644 champ-lib/champ-titan/pom.xml create mode 100644 champ-lib/champ-titan/src/main/java/org/onap/aai/champtitan/graph/impl/GraphSON.java create mode 100644 champ-lib/champ-titan/src/main/java/org/onap/aai/champtitan/graph/impl/TitanChampGraphImpl.java rename {src/main/java/org/onap/aai/champ => champ-lib/champ-titan/src/main/java/org/onap/aai/champtitan}/perf/ChampAPIPerformanceTest.java (76%) create mode 100644 champ-lib/champ-titan/src/test/java/org/onap/aai/champtitan/concurrency/ConcurrencyTest.java create mode 100644 champ-lib/champ-titan/src/test/java/org/onap/aai/champtitan/core/ChampAPITest.java create mode 100644 champ-lib/champ-titan/src/test/java/org/onap/aai/champtitan/core/ChampObjectIndexTest.java create mode 100644 champ-lib/champ-titan/src/test/java/org/onap/aai/champtitan/core/ChampRelationshipIndexTest.java create mode 100644 champ-lib/champ-titan/src/test/java/org/onap/aai/champtitan/core/ChampSchemaTest.java create mode 100644 champ-lib/champ-titan/src/test/java/org/onap/aai/champtitan/core/ChampTransactionTest.java create mode 100644 champ-lib/champ-titan/src/test/java/org/onap/aai/champtitan/core/TitanChampSetupTest.java create mode 100644 champ-lib/pom.xml create mode 100644 champ-service-deps-janus/pom.xml create mode 100644 champ-service-deps-titan/pom.xml create mode 100644 champ-service/License.txt create mode 100644 champ-service/ajsc-shared-config/etc/logback.xml create mode 100644 champ-service/antBuild/build.xml create mode 100644 champ-service/appconfig-local/auth/champion-service_policy.json-REPLACE create mode 100644 champ-service/appconfig-local/auth/tomcat_keystore-REPLACE create mode 100644 champ-service/appconfig-local/champ-api.properties-REPLACE create mode 100644 champ-service/bundleconfig-local/etc/appprops/AAFUserRoles.properties create mode 100644 champ-service/bundleconfig-local/etc/appprops/PostProcessorInterceptors.properties create mode 100644 champ-service/bundleconfig-local/etc/appprops/PreProcessorInterceptors.properties create mode 100644 champ-service/bundleconfig-local/etc/appprops/app-intercepts.properties create mode 100644 champ-service/bundleconfig-local/etc/appprops/methodMapper.properties create mode 100644 champ-service/bundleconfig-local/etc/sysprops/sys-props.properties create mode 100644 champ-service/pom.xml create mode 100644 champ-service/src/main/ajsc/champ-service_v1/champ-service/v1/conf/jaxrsBeans.groovy create mode 100644 champ-service/src/main/ajsc/champ-service_v1/champ-service/v1/docs/README.txt create mode 100644 champ-service/src/main/ajsc/champ-service_v1/champ-service/v1/lib/README.txt create mode 100644 champ-service/src/main/ajsc/champ-service_v1/champ-service/v1/routes/champ.route create mode 100644 champ-service/src/main/ajsc/champ-service_v1/champ-service/v1/routes/jaxrsExample.route create mode 100644 champ-service/src/main/assemble/ajsc_module_assembly.xml create mode 100644 champ-service/src/main/assemble/ajsc_props_assembly.xml create mode 100644 champ-service/src/main/assemble/ajsc_runtime_assembly.xml create mode 100644 champ-service/src/main/bin/start.sh create mode 100644 champ-service/src/main/config/ajsc-chef.jks create mode 100644 champ-service/src/main/config/ajsc-jetty.xml create mode 100644 champ-service/src/main/config/ajsc-override-web.xml create mode 100644 champ-service/src/main/config/ajscJetty.jks create mode 100644 champ-service/src/main/config/cadi.properties create mode 100644 champ-service/src/main/config/jul-redirect.properties create mode 100644 champ-service/src/main/config/keyfile create mode 100644 champ-service/src/main/config/runner-web.xml create mode 100644 champ-service/src/main/docker/Dockerfile create mode 100644 champ-service/src/main/java/org/onap/champ/ChampRESTAPI.java create mode 100644 champ-service/src/main/java/org/onap/champ/async/ChampAsyncRequestProcessor.java create mode 100644 champ-service/src/main/java/org/onap/champ/async/ChampAsyncResponsePublisher.java create mode 100644 champ-service/src/main/java/org/onap/champ/entity/ChampObjectDeserializer.java create mode 100644 champ-service/src/main/java/org/onap/champ/entity/ChampObjectSerializer.java create mode 100644 champ-service/src/main/java/org/onap/champ/entity/ChampRelationshipDeserializer.java create mode 100644 champ-service/src/main/java/org/onap/champ/entity/ChampRelationshipSerializer.java create mode 100644 champ-service/src/main/java/org/onap/champ/event/GraphEvent.java create mode 100644 champ-service/src/main/java/org/onap/champ/event/GraphEventEdge.java create mode 100644 champ-service/src/main/java/org/onap/champ/event/GraphEventVertex.java create mode 100644 champ-service/src/main/java/org/onap/champ/exception/ChampServiceException.java create mode 100644 champ-service/src/main/java/org/onap/champ/service/ChampDataService.java create mode 100644 champ-service/src/main/java/org/onap/champ/service/ChampThreadFactory.java create mode 100644 champ-service/src/main/java/org/onap/champ/service/ChampTransactionCache.java create mode 100644 champ-service/src/main/java/org/onap/champ/service/ChampUUIDService.java create mode 100644 champ-service/src/main/java/org/onap/champ/service/EchoService.java create mode 100644 champ-service/src/main/java/org/onap/champ/service/logging/ChampMsgs.java create mode 100644 champ-service/src/main/java/org/onap/champ/service/logging/LoggingUtil.java create mode 100644 champ-service/src/main/java/org/onap/champ/util/ChampProperties.java create mode 100644 champ-service/src/main/java/org/onap/champ/util/ChampServiceConstants.java create mode 100644 champ-service/src/main/resources/META-INF/services/javax.ws.rs.client.ClientBuilder create mode 100644 champ-service/src/main/resources/logging/ChampMsgs.properties create mode 100644 champ-service/src/main/runtime/context/__module.ajsc.namespace.name__#__module.ajsc.namespace.version__.context create mode 100644 champ-service/src/main/runtime/context/default#0.context create mode 100644 champ-service/src/main/runtime/deploymentPackage/__module.ajsc.namespace.name__#__module.ajsc.namespace.version__.json create mode 100644 champ-service/src/main/runtime/shiroRole/ajscadmin.json create mode 100644 champ-service/src/main/runtime/shiroRole/contextadmin#__module.ajsc.namespace.name__.json create mode 100644 champ-service/src/main/runtime/shiroRole/contextadmin#default.json create mode 100644 champ-service/src/main/runtime/shiroUser/ajsc.json create mode 100644 champ-service/src/main/runtime/shiroUserRole/ajsc#ajscadmin.json create mode 100644 champ-service/src/main/runtime/shiroUserRole/ajsc#contextadmin#__module.ajsc.namespace.name__.json create mode 100644 champ-service/src/main/runtime/shiroUserRole/ajsc#contextadmin#default.json delete mode 100644 src/main/java/org/onap/aai/champ/ChampGraph.java delete mode 100644 src/main/java/org/onap/aai/champ/graph/impl/AbstractGremlinChampGraph.java delete mode 100644 src/main/java/org/onap/aai/champ/graph/impl/AbstractTinkerpopChampGraph.java delete mode 100644 src/main/java/org/onap/aai/champ/graph/impl/AbstractValidatingChampGraph.java delete mode 100644 src/main/java/org/onap/aai/champ/graph/impl/TitanChampGraphImpl.java delete mode 100644 src/main/java/org/onap/aai/champ/model/ChampObject.java delete mode 100644 src/test/java/org/onap/aai/champ/concurrency/ConcurrencyTest.java delete mode 100644 src/test/java/org/onap/aai/champ/core/BaseChampAPITest.java delete mode 100644 src/test/java/org/onap/aai/champ/core/ChampAPITest.java delete mode 100644 src/test/java/org/onap/aai/champ/core/ChampObjectTest.java delete mode 100644 src/test/java/org/onap/aai/champ/core/ChampPartitionTest.java delete mode 100644 src/test/java/org/onap/aai/champ/core/ChampRelationshipIndexTest.java delete mode 100644 src/test/java/org/onap/aai/champ/core/ChampRelationshipTest.java diff --git a/README.md b/README.md index 08489f2..98e47f5 100644 --- a/README.md +++ b/README.md @@ -9,392 +9,704 @@ Champ is an abstraction from underlying graph storage systems that A&AI would ot Building Champ -------------- -Good ol' 'mvn clean install' does the trick. +To build Champ run the following maven command from the project's root level pom directory: + + mvn clean install + +Deploying The Microservice +-------------------------- + +Push the Docker image that you have built to your Docker repository and pull it down to the location from which you will be running the service. + +**Create the following directories on the host machine:** + + ../logs + ../appconfig + ../appconfig/auth + ../dynamic/conf + +You will be mounting these as data volumes when you start the Docker container. + +#### Configuring the Microservice + +Create beans file **../dynamic/conf/champ-beans.xml** + +Example: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Create configuration file **../appconfig/auth/champ-policy.json** + +This policy file defines which client certificates are authorized to use the service's APIs. An example policy file follows: + + { + "roles": [ + { + "name": "admin", + "functions": [ + { + "name": "search", "methods": [ { "name": "GET" },{ "name": "DELETE" }, { "name": "PUT" }, { "name": "POST" } ] + } + ], + "users": [ + { + "username": "CN=admin, OU=My Organization Unit, O=, L=Sometown, ST=SomeProvince, C=CA" + } + ] + } + ] + } + +Create keystore file **../appconfig/auth/tomcat\_keystore** +_tomcat\_keystore_ + +Create a keystore with this name containing whatever CA certificates that you want your instance of the CHAMP service to accept for HTTPS traffic. + +#### Start the service + +You can now start the Docker container in the following manner: + + docker run -d \ + -p 9520:9520 \ + -e CONFIG_HOME=/opt/app/champ-service/config/ \ + -e KEY_STORE_PASSWORD={{obfuscated password}} \ + -e KEY_MANAGER_PASSWORD=OBF:{{obfuscated password}} \ + -v //logs:/opt/aai/logroot/AAI-CHAMP \ + -v //appconfig:/opt/app/champ-service/config \ + --name champ-service \ + {{your docker repo}}/champ-service + +Where, + + {{your docker repo}} = The Docker repository you have published your CHAMP Service image to. + {{obfuscated password}} = The password for your key store/key manager after running it through the Jetty obfuscation tool. API Specification ----------------- -Champ has CRUD methods for: +Champ has methods for: 1) Objects 2) Relationships -3) Partitions (subgraphs) -3) Indices (on object and relationship properties) -4) Schemas +3) Transactions -For each of these types, we offer builders and a more user-friendly fluent interface. - -In the future we plan on adding in traversals, but at the moment that is outside the scope of Champ. If you have suggestions on how this should be implemented, we look forward to your pull request. +In the future we plan on adding in partitions, indicies, schemas, and traversals, but at the moment that is outside the scope of Champ. If you have suggestions on how this should be implemented, we look forward to your pull request. API Implementations ------------------- -Champ ships with a simple in-memory implementation as well as a Titan implementation. We recommend the in-memory implementation for unit testing and prototyping. If you would like to have your implementation referenced in this readme, please create a pull-request. Please note that all implementations will reside in their own repository - not in the Champ repository. - -Usage ------ - -### ChampAPI - -The ChampAPI interface is basically just for tracking and properly shutting down multiple graph instances. If you need this functionality, use the ChampAPI. However, if you only ever access 1 graph, you may choose to use a single ChampGraph. - -For getting started quickly, use the ChampAPI.Factory or ChampGraph.Factory to create either an In-memory implementation (for dev/test) or if you're running Titan locally, you can start a Titan instance. For complex environments, each ChampGraph implementation will vary - the Titan implementation is described below. - -### ChampGraph - -This is the meat and potatoes of Champ. It contains all of the CRUD methods mentioned above for Objects, Relationships, Partitions, Indices, and Schemas. Each implementation varies in how you instantiate it. The ones that ship with Champ are described below. - -#### In-memory ChampGraph - -Simply: - -``` -final ChampGraph graph = ChampGraph.Factory.newInstance(ChampGraph.Type.IN_MEMORY, "someGraphName"); - -//Do stuff with graph +Champ ships with both Titan and Janus implementations. These are switchable after deployment, but the champ-beans.xml file needs to be changed and the champ-service must be restarted. -graph.shutdown(); +Event Generation +---------------- -``` +Champ can be configured to generate a notification whenever it is used to modify data in the graph. The notification comes in the form of an event which is posted to the **champRawEvents** Event Bus topic. This event stream allows downstream clients to be notified about objects and relationships which are added/modified/deleted in the graph. -or: +The following configuration parameters define the behaviour of the event generation feature: -``` -final ChampAPI api = ChampAPI.Factory.newInstance(ChampGraph.Type.IN_MEMORY); -final ChampGraph dogsGraph = api.getGraph("dogsGraph"); -final ChampGraph catsGraph = api.getGraph("catsGraph"); +- **champ.event.stream.publisher**: _EventClientPublisher_ instance to use for forwarding events to the event stream (see below). +- **champ.event.stream.publisher-pool-size**: Optional: number of worker threads to use for event publishing. +- **champ.event.stream.buffer.capacity**: Optional: maximum number of events which may be enqueued waiting to be published at any given time. + -api.shutdown(); //This will shutdown all graphs started by api.getGraph(String) +The following examples illustrate snippets of typical spring-beans configuration file which instantiate a producer (if your client is not spring enabled then you may just directly instantiate an _EventBusPublisher_ - refer to the _ECOMP Event Bus Client_ library for details): -``` +_Instantiating an event producer backed by a native Kafka implementation:_ -#### Titan ChampGraph + + + + + -For a Titan instance running on top of Cassandra locally, simply: +_Instantiating an event producer backed by a DMaaP Client implementation:_ -``` -final ChampGraph graph = ChampGraph.Factory.newInstance(ChampGraph.Type.TITAN, "dogsGraph"); + + + + + + -//Do stuff with graph + -graph.shutdown(); - -``` -or: - -``` -final ChampAPI api = ChampAPI.Factory.newInstance(ChampGraph.Type.TITAN); -final ChampGraph dogsGraph = api.getGraph("dogsGraph"); -final ChampGraph cats Graph = api.getGraph("catsGraph"); - -api.shutdown(); //This will shutdown all graph started by api.getGraph(String); - -``` - -For more complex/customized configurations: +Usage +----- -``` - final ChampGraph graph = new TitanChampGraphImpl.Builder(graphName) - .property("storage.backend", "cassandrathrift") - .property("storage.hostname", "localhost") - .build(); -``` +### Echo -The calls to .property(String, String) accept all configuration options found [here](http://s3.thinkaurelius.com/docs/titan/1.0.0/titan-config-ref.html) + URL: https://:9522/services/echo-service/echo/ + Method: GET + Success Response: 200 OK -You could also implement the ChampAPI interface to manage multiple graphs connected to this Titan cluster. See the ChampAPIImpl class for an example of how to do this. -### Creating Objects +### Objects #### Create a new object - -``` -ChampObject.create() - .ofType("foo") //The "foo" type of object can be constrained by a ChampObjectConstraint - .withoutKey() //No key for this object indicates that the underlying Champ implementation should create this object - .withProperty("bar", "string") //Zero or more properties can be set on a ChampObject - .withProperty("baz", 30) - .build() -``` - -#### Copy an existing object - -``` -ChampObject.create() - .from(foo) //'foo' is a reference to a ChampObject - .withoutKey() - .withProperty("pi", 3.14f) - .build() -``` - -#### Persisting an object - -``` -final ChampGraph graph = ChampGraph.Factory.newInstance(graphType, "neighborhoodDogsGraph"); -graph.storeObject(foo); //'foo' is a reference to a ChampObject -graph.shutdown(); //The ChampGraph is thread-safe, and only one needs to be created - //Once your application is finished using it, call shutdown() - //to cleanup any loose ends -``` +Inserts a new object into the graph with the type and properties from the body of the request. Returns the object that was created, along with its assigned key and timestamps. + + URL: https://:9522/services/champ-service/v1/objects + Method: POST + Body: + { + "type" : "test", + "properties" : { + "key1" : "val1", + "key2" : "val2" + } + } + + Success Response: + Code: 201 + Content: + { + "key": "890c8b3f-892f-48e3-85cd-748ebf0426a5", + "type": "test", + "properties": { + "key1": "val1", + "key2": "val2", + "aai-uuid": "890c8b3f-892f-48e3-85cd-748ebf0426a5", + "aai-created-ts": 1516731449014, + "aai-last-mod-ts": 1516731449014 + } + } #### Retrieve an object - -``` -final ChampGraph graph = ChampGraph.Factory.newInstance(graphType, "neighborhoodDogsGraph"); -final Optional object = graph.retrieveObject("329847"); //Note that the key is usually only known by virtue of previously storing/retrieving/querying it - -graph.shutdown(); - -``` - -#### Query objects - -``` -final ChampGraph graph = ChampGraph.Factory.newInstance(graphType, "neighborhoodDogsGraph"); -final Stream objects = graph.queryObjects(Collection.singletonMap("favoriteDog", "Ace")); - -objects.close(); //You must close the stream when you are finished with it -graph.shutdown(); - -``` - -### Creating Relationships +A GET request that returns the object with the given key + + URL: https://:9522/services/champ-service/v1/objects/ + Method: GET + Success Response: + Code: 200 OK + Content: + { + "key": "890c8b3f-892f-48e3-85cd-748ebf0426a5", + "type": "test", + "properties": { + "key1": "val1", + "key2": "val2", + "aai-uuid": "890c8b3f-892f-48e3-85cd-748ebf0426a5", + "aai-created-ts": 1516731449014, + "aai-last-mod-ts": 1516731449014 + } + } + +#### Updating an object +Replace any of the properties with a PUT request, get the updated object back. Inclusion of timestamps is optional, but the request will be rejected if they do not match the DB. + + URL: https://:9522/services/champ-service/v1/objects/ + Method: PUT + Content: + { + "key": "890c8b3f-892f-48e3-85cd-748ebf0426a5", + "type": "test", + "properties": { + "key1": "val3", + "key2": "val2", + "aai-uuid": "890c8b3f-892f-48e3-85cd-748ebf0426a5", + "key4": "val4", + "aai-created-ts": 1516731449014 + } + } + + Response: + Code: 200 OK + Content: + { + "key": "890c8b3f-892f-48e3-85cd-748ebf0426a5", + "type": "test", + "properties": { + "key1": "val3", + "key2": "val2", + "aai-uuid": "890c8b3f-892f-48e3-85cd-748ebf0426a5", + "key4": "val4", + "aai-created-ts": 1516731449014, + "aai-last-mod-ts": 1516730919213 + } + } + +#### Delete objects +Deletes the object from the graph if there are no connected relationships + + URL: https://:9522/services/champ-service/v1/objects/ + Method: DELETE + Success Response: + Code: 200 OK + + + +#### Filtered object search +Get a list of objects filtered by key/value pairs + + URL: https://:9522/services/champ-service/v1/objects/filter?= + Method: GET + Success Response: + [ + { + "key": "e0d3a253-4a1b-4ca4-a862-8a52b1e3fdfb", + "type": "test2", + "properties": {} + } + ] + +Get a list of objects filtered by key/value pairs with specific properties + + URL: https://:9522/services/champ-service/v1/objects/filter?=&properties=&properties= + Method: GET + Success Response: + [ + { + "key": "e0d3a253-4a1b-4ca4-a862-8a52b1e3fdfb", + "type": "test2", + "properties": { + "key1": "val1", + "filter-sample": "yes" + } + } + ] + +Get a list of objects filtered by key/value pairs with all properties + + URL: https://:9522/services/champ-service/v1/objects/filter?=&properties=all + Method: GET + Success Response: + [ + { + "key": "e0d3a253-4a1b-4ca4-a862-8a52b1e3fdfb", + "type": "test2", + "properties": { + "key1": "val1", + "aai-uuid": "e0d3a253-4a1b-4ca4-a862-8a52b1e3fdfb", + "filter-sample": "yes" + } + } + ] + +### Relationships +Relationships are used to create a connection between two pre-existing objects. #### Create a new relationship - -In this example we create the relationship: - -dog eats dogPellets - -``` -ChampRelationship.create() - .ofType("eats") - .withoutKey() - .withSource() - .ofType("dog") - .withoutKey() - .withProperty("name", "champ") - .build() - .withTarget() - .ofType("dogPellets") - .withoutKey() - .withProperty("brand", "costco") - .build() - .withProperty("at", System.currentTimeMillis()) - .build() -``` - -#### Persisting a relationship - -``` -final ChampGraph graph = ChampGraph.Factory.newInstance(graphType, "neighborhoodDogsGraph"); -graph.storeRelationship(champEatsCostcoFood); //'champEatsCostcoFood' is a reference to a ChampRelationship -graph.shutdown(); //The ChampGraph is thread-safe, and only one needs to be created - //Once your application is finished using it, call shutdown() - //to cleanup any loose ends -``` - -#### Retrieving incident relationships - -``` -final ChampGraph graph = ChampGraph.Factory.newInstance(graphType, "neighborhoodDogsGraph"); -final Stream relationships = graph.retrieveRelationships(ChampObject.create().withKey("foo").build()); - -relationships.close(); //You must close the stream when you are done with it -graph.shutdown(); //The ChampGraph is thread-safe, and only one needs to be created - -``` - -#### Querying relationship - -``` -final ChampGraph graph = ChampGraph.Factory.newInstance(graphType, "neighborhoodDogsGraph"); -final Stream relationships = graph.queryRelationships(Collections.singletonMap("favoriteHydrant", 42); - -relationships.close(); //You must close the stream when you are done with it -graph.shutdown(); //The ChampGraph is thread-safe, and only one needs to be created - -``` - -### Creating partitions -#### Create a new partition - -Champ partitions are subgraphs (i.e. a collection of objects and relationships) -** Note: We are still in the proces of creating a fluent API for partitions ** - - -``` -ChampPartition.create() - .withObject( - ChampObject.create() - .ofType("dog") - .withoutKey() - .build() - ) - .withObject( - ChampObject.create() - .ofType("cat") - .withoutKey() - .build() - .withObject( - ChampObject.create() - .ofType("bird") - .withoutKey() - .build() - ) - .withRelationship( - ChampRelationship.create() - ... - .build() - ) - .build() -``` - -#### Persisting a partition - -``` -final ChampGraph graph = ChampGraph.Factory.newInstance(graphType, "neighborhoodDogsGraph"); -graph.storePartition(dogsOnMyBlock); //'dogsOnMyBlock' is a reference to a ChampPartition -graph.shutdown(); //The ChampGraph is thread-safe, and only one needs to be created - //Once your application is finished using it, call shutdown() - //to cleanup any loose ends -``` - -### Creating indices -#### Create an object index - -``` -ChampObjectIndex.create() - .ofName("dogName") - .onType("dog") - .forField("name") - .build() -``` - -#### Create a relationship index - -``` -ChampRelationshipIndex.create() - .ofName("eatsAtTime") - .onType("eats") - .forField("at") - .build() -``` - -#### Persisting an object index - -``` -final ChampGraph graph = ChampGraph.Factory.newInstance(graphType, "neighborhoodDogsGraph"); -graph.storeObjectIndex(dogName); //'dogName' is a reference to a ChampObjectIndex -graph.shutdown(); //The ChampGraph is thread-safe, and only one needs to be created - //Once your application is finished using it, call shutdown() - //to cleanup any loose ends -``` - -#### Persisting a relationship index - -``` -final ChampGraph graph = ChampGraph.Factory.newInstance(graphType, "neighborhoodDogsGraph"); -graph.storeRelationshipIndex(eatsAtTime); //'eatsAtTime' is a reference to a ChampObjectIndex -graph.shutdown(); //The ChampGraph is thread-safe, and only one needs to be created - //Once your application is finished using it, call shutdown() - //to cleanup any loose ends -``` -#### Retrieving an object index - -``` -final ChampGraph graph = ChampGraph.Factory.newInstance(graphType, "neighborhoodDogsGraph"); -graph.retrieveObjectIndex("dogName"); -graph.shutdown(); - -``` - -#### Retrieving a relationship index - -``` -final ChampGraph graph = ChampGraph.Factory.newInstance(graphType, "neighborhoodDogsGraph"); -graph.retrieveRelationshipIndex("eatsAtTime"); -graph.shutdown(); - -``` - -### Creating schemas -#### Create a schema - -The following schema restricts objects of type foo to have a required property "property1" as an Integer, and optional property "property2" as a String (Strings are the default type for object properties). It also restricts relationships of type bar to only be allowed to originate from the object type foo. - -``` -ChampSchema.create() - .withObjectConstraint() - .onType("foo") - .withPropertyConstraint() - .onField("property1") - .ofType(Integer.class) - .required() - .build() - .withPropertyConstraint() - .onField("property2") - .optional() - .build() - .build() - .withRelationshipConstraint() - .onType("bar") - .withPropertyConstraint() - .onField("at") - .ofType(String.class) - .optional() - .build() - .withConnectionConstraint() - .sourcedFrom("foo") - .targetToAny() - .build() - .build() - .build(); -``` - -#### Persisting a schema - -``` -final ChampGraph graph = ChampGraph.Factory.newInstance(graphType, "neighborhoodDogsGraph"); -graph.storeSchema(neighborhoodDogsSchema); //'neighborhoodDogsSchema' is a reference to a ChampObjectIndex -graph.updateSchema(neighborhoodDogConstraint); //'neighborhoosDogConstraint' is a reference to a ChampObjectConstraint -graph.updateSchema(eatsAtConstraint); //'eatsAtConstraint' is a reference to a ChampRelationshipIndex -graph.shutdown(); //The ChampGraph is thread-safe, and only one needs to be created - //Once your application is finished using it, call shutdown() - //to cleanup any loose ends -``` - -#### Retrieving a schema - -``` -final ChampGraph graph = ChampGraph.Factory.newInstance(graphType, "neighborhoodDogsGraph"); - -final ChampSchema schema = graph.retrieveSchema(); - -graph.shutdown(); - -``` - -### Champ Performance Testing - -There is a jar-with-dependencies provided in maven that contains a performance test you can move around and get some idea of how well Champ is running on a cluster of your choice. At the moment, the test only runs against a Titan implementation. - -#### Example running an in-memory test - -``` - -java -cp champ-0.0.1-SNAPSHOT-jar-with-dependencies.jar org.onap.aai.champ.perf.ChampAPIPerformanceTest --champ.graph.type=IN_MEMORY - - -``` - -#### Example running a Titan test - -Note that after the --champ.graph.type=TITAN parameter is provided, you may provide any configuration that is specified by Titan (see link above for the documentation) - -``` - -java -cp champ-0.0.1-SNAPSHOT-jar-with-dependencies.jar org.onap.aai.champ.perf.ChampAPIPerformanceTest --champ.graph.type=TITAN --storage.backend=cassandrathrift --storage.hostname=localhost - - -``` +Creates a new relationship with the specified properties. "source" and "target" must be objects that have already been created, specified by their keys. Returns the created relationship with its key and timestamps. + + URL: https://:9522/services/champ-service/v1/relationships + Method: POST + Content: + { + "type": "testOnTest2", + "properties": { + "beep": "boop", + "a": "b" + }, + "source": { + "key": "890c8b3f-892f-48e3-85cd-748ebf0426a5", + "type": "test", + "properties": { + "key1": "val3", + "key2": "val2", + "aai-uuid": "890c8b3f-892f-48e3-85cd-748ebf0426a5", + "key4": "val4" + } + }, + "target": { + "key": "559855df-62e2-4b06-a1ae-18e0d5ac9826", + "type": "test2", + "properties": { + "key1": "val1", + "key2": "val2", + "aai-uuid": "559855df-62e2-4b06-a1ae-18e0d5ac9826", + "key4": "val4" + } + } + } + + Response: + Code: 201 Created + Content: + { + "key": "7a3282d0-6904-40f2-ae1e-8246bb1f49c1", + "type": "testOnTest2", + "properties": { + "beep": "boop", + "a": "b", + "aai-uuid": "7a3282d0-6904-40f2-ae1e-8246bb1f49c1" + "aai-last-mod-ts": 1516730919213, + "aai-created-ts": 1516730919213 + }, + "source": { + "key": "890c8b3f-892f-48e3-85cd-748ebf0426a5", + "type": "test", + "properties": { + "key1": "val3", + "key2": "val2", + "aai-uuid": "890c8b3f-892f-48e3-85cd-748ebf0426a5", + "key4": "val4" + } + }, + "target": { + "key": "559855df-62e2-4b06-a1ae-18e0d5ac9826", + "type": "test2", + "properties": { + "key1": "val1", + "key2": "val2", + "aai-uuid": "559855df-62e2-4b06-a1ae-18e0d5ac9826", + "key4": "val4" + } + } + } + +#### Retrieving relationships +Returns the relationship, looked up by key. + + URL: https://:9522/services/champ-service/v1/relationships/ + Method: GET + Response: + Code: 200 OK + Content: + { + "key": "7a3282d0-6904-40f2-ae1e-8246bb1f49c1", + "type": "testOnTest2", + "properties": { + "beep": "boop", + "a": "b", + "aai-uuid": "7a3282d0-6904-40f2-ae1e-8246bb1f49c1" + "aai-last-mod-ts": 1516730919213, + "aai-created-ts": 1516730919213 + }, + "source": { + "key": "890c8b3f-892f-48e3-85cd-748ebf0426a5", + "type": "test", + "properties": { + "key1": "val3", + "key2": "val2", + "aai-uuid": "890c8b3f-892f-48e3-85cd-748ebf0426a5", + "key4": "val4" + } + }, + "target": { + "key": "559855df-62e2-4b06-a1ae-18e0d5ac9826", + "type": "test2", + "properties": { + "key1": "val1", + "key2": "val2", + "aai-uuid": "559855df-62e2-4b06-a1ae-18e0d5ac9826", + "key4": "val4" + } + } + } + + #### Get relationships for an object + Given an object, returns all connected relationships. + + URL: https://:9522/services/champ-service/v1/objects/relationships/ + Method: GET + Success Response: + Code: 200 OK + Content: + [ + { + "key": "4ba8dcc2-806d-4312-aecb-503435f355e5", + "type": "testOnTest2", + "properties": { + "beep": "fdsa", + "a": "c", + "aai-uuid": "4ba8dcc2-806d-4312-aecb-503435f355e5" + }, + "source": { + "key": "890c8b3f-892f-48e3-85cd-748ebf0426a5", + "type": "test", + "properties": { + "key1": "val3", + "key2": "val2", + "aai-uuid": "890c8b3f-892f-48e3-85cd-748ebf0426a5", + "key4": "val4" + } + }, + "target": { + "key": "559855df-62e2-4b06-a1ae-18e0d5ac9826", + "type": "test2", + "properties": { + "key1": "val1", + "key2": "val2", + "aai-uuid": "559855df-62e2-4b06-a1ae-18e0d5ac9826", + "key4": "val4" + } + } + }, + { + "key": "a3096bb8-dc66-4a9c-ab33-a1183f784fbb", + "type": "testOnTest2", + "properties": { + "beep": "fdsa", + "a": "c", + "aai-uuid": "a3096bb8-dc66-4a9c-ab33-a1183f784fbb" + }, + "source": { + "key": "890c8b3f-892f-48e3-85cd-748ebf0426a5", + "type": "test", + "properties": { + "key1": "val3", + "key2": "val2", + "aai-uuid": "890c8b3f-892f-48e3-85cd-748ebf0426a5", + "key4": "val4" + } + }, + "target": { + "key": "559855df-62e2-4b06-a1ae-18e0d5ac9826", + "type": "test2", + "properties": { + "key1": "val1", + "key2": "val2", + "aai-uuid": "559855df-62e2-4b06-a1ae-18e0d5ac9826", + "key4": "val4" + } + } + } + ] + +#### Updating relationships +Update the relationship properties. Passing timestamps is optional, but the request will be rejected if they are incorrect. + + URL: https://:9522/services/champ-service/v1/relationships/ + Method: PUT + Content: + { + "key": "7a3282d0-6904-40f2-ae1e-8246bb1f49c1", + "type": "testOnTest2", + "properties": { + "beep": "borp", + "a": "c", + "aai-uuid": "7a3282d0-6904-40f2-ae1e-8246bb1f49c1" + }, + "source": { + "key": "890c8b3f-892f-48e3-85cd-748ebf0426a5", + "type": "test", + "properties": { + "key1": "val3", + "key2": "val2", + "aai-uuid": "890c8b3f-892f-48e3-85cd-748ebf0426a5", + "key4": "val4" + } + }, + "target": { + "key": "559855df-62e2-4b06-a1ae-18e0d5ac9826", + "type": "test2", + "properties": { + "key1": "val1", + "key2": "val2", + "aai-uuid": "559855df-62e2-4b06-a1ae-18e0d5ac9826", + "key4": "val4" + } + } + } + + Response: + Code: 200 OK + Content: + { + "key": "7a3282d0-6904-40f2-ae1e-8246bb1f49c1", + "type": "testOnTest2", + "properties": { + "beep": "borp", + "a": "c", + "aai-uuid": "7a3282d0-6904-40f2-ae1e-8246bb1f49c1", + "aai-last-mod-ts": 1516734987294, + "aai-created-ts": 1516730919213 + }, + "source": { + "key": "890c8b3f-892f-48e3-85cd-748ebf0426a5", + "type": "test", + "properties": { + "key1": "val3", + "key2": "val2", + "aai-uuid": "890c8b3f-892f-48e3-85cd-748ebf0426a5", + "key4": "val4" + } + }, + "target": { + "key": "559855df-62e2-4b06-a1ae-18e0d5ac9826", + "type": "test2", + "properties": { + "key1": "val1", + "key2": "val2", + "aai-uuid": "559855df-62e2-4b06-a1ae-18e0d5ac9826", + "key4": "val4" + } + } + } + +#### Deleting relationships +Deletes the relationship specified by key. + + URL: https://:9522/services/champ-service/v1/relationships/ + Method: Delete + Response: 200 OK + +#### Filtered Relationship +Returns a list of relationships that have key/value properties matching the filter + + URL: https://:9522/services/champ-service/v1/objects/filter?= + Method: GET + Success Response: + [ + { + "key": "a4d51cd9-f271-4201-975d-168ec6bde501", + "type": "testOnTest2", + "properties": { + "beep": "yes", + "a": "c", + "aai-uuid": "a4d51cd9-f271-4201-975d-168ec6bde501" + }, + "source": { + "key": "890c8b3f-892f-48e3-85cd-748ebf0426a5", + "type": "test", + "properties": { + "key1": "val3", + "key2": "val2", + "aai-uuid": "890c8b3f-892f-48e3-85cd-748ebf0426a5", + "key4": "val4" + } + }, + "target": { + "key": "559855df-62e2-4b06-a1ae-18e0d5ac9826", + "type": "test2", + "properties": { + "key1": "val1", + "key2": "val2", + "aai-uuid": "559855df-62e2-4b06-a1ae-18e0d5ac9826", + "key4": "val4" + } + } + } + ] + +### Transactions +Transactions allow multiple graph operations to be grouped into a logical, sandboxed context, so that the option exists to either persist ALL of the grouped changes together, or NONE of them. + +Explicit use of transactions is entirely optional for the client. Calling the API methods described below without supplying a transaction +object results in a transaction being implicitly opened for the single operation, and then automatically committed. + +However, all of the API calls described above related to persisting, retrieving, and deleting vertices, edges and graph partitions also +expose a version of the call which optionally accepts a transaction id (acquired by explicitly calling the /transaction API endpoint). +In this case, the supplied transaction is used for the operation, and no automatic commit occurs. It is the responsibility of +the client to explicitly commit or rollback the transaction at his or her discretion. + +#### Open a new transaction +To use explicit transaction the client must request a transaction id from the Champ service by making a request to open a new transaction. + + URL: https://:9522/services/champ-service/v1/transaction/ + Method: POST + Response: + Code: 200 OK + Content: 5d90f5ae-1f1e-4c3e-b20b-2f7c45f822eb + +#### Working within a transaction +Operations can be done within a transaction by putting the transactionId in the query string. + + Query string: transactionId= + +Example object creation: + + URL: https://:9522/services/champ-service/v1/objects?transactionId=5d90f5ae-1f1e-4c3e-b20b-2f7c45f822eb + +Example relationship update: + + URL: https://:9522/services/champ-service/v1/relationships/?transactionId=5d90f5ae-1f1e-4c3e-b20b-2f7c45f822eb + +#### Checking a transaction +If you wish to check the status of a transaction, you can do a get on it + + URL: https://:9522/services/champ-service/v1/transaction/ + Method: GET +If the transaction is currently open: + + Response: + Code: 200 OK + Content: "fa0890d9-6ac4-40aa-9838-745a25a61fa6 is OPEN" +If the transaction is not open: + + Response: + Code: 404 Not Found + Content: {} + + +#### Committing a transaction +Operations performed within the context of a transaction are not visible outside of that context +until the client explicitly commits the transaction. Up until that point, there is always the +option to just roll back the changes. + + URL: https://:9522/services/champ-service/v1/transaction/ + Method: PUT + Content: {"method":"commit"} + + Response: + Code: 200 OK + Content: COMMITED + +### Rolling back a transaction. +In the event that a sequence of graph operations which were performed within the same transactional context need to be aborted (for example one of the operations in the sequence encountered a failure of some kind) the entire transaction can be aborted by rolling back the transaction. This effectively undoes all of the operations which were performed within the open transaction. + +Note, once a transaction has been committed, it is no longer possible to rollback the contents of the transaction. + + URL: https://:9522/services/champ-service/v1/transaction/ + Method: PUT + Content: {"method":"rollback"} + + Response: + Code: 200 OK + Content: ROLLED BACK diff --git a/License.txt b/champ-lib/License.txt similarity index 100% rename from License.txt rename to champ-lib/License.txt diff --git a/champ-lib/champ-core/License.txt b/champ-lib/champ-core/License.txt new file mode 100644 index 0000000..469f362 --- /dev/null +++ b/champ-lib/champ-core/License.txt @@ -0,0 +1,21 @@ +============LICENSE_START========================================== +org.onap.aai +=================================================================== +Copyright © 2017 AT&T Intellectual Property. All rights reserved. +Copyright © 2017 Amdocs +=================================================================== +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +============LICENSE_END============================================ +ECOMP is a trademark and service mark of AT&T Intellectual Property. + + diff --git a/champ-lib/champ-core/pom.xml b/champ-lib/champ-core/pom.xml new file mode 100644 index 0000000..b52f408 --- /dev/null +++ b/champ-lib/champ-core/pom.xml @@ -0,0 +1,119 @@ + + + 4.0.0 + + + champ-lib + org.onap.aai + 1.2.0-SNAPSHOT + + + champ-core + + + + + org.onap.aai.event-client + event-client-api + ${event.client.version} + + + org.onap.aai.event-client + event-client-dmaap + ${event.client.version} + + + org.onap.aai.event-client + event-client-kafka + ${event.client.version} + + + + + org.codehaus.groovy + groovy + 2.4.12 + + + com.fasterxml.jackson.core + jackson-databind + 2.5.3 + + + org.apache.tinkerpop + gremlin-core + 3.2.3 + true + + + org.slf4j + slf4j-log4j12 + + + org.slf4j + jcl-over-slf4j + + + + + org.apache.tinkerpop + tinkergraph-gremlin + 3.2.3 + true + + + com.google.code.gson + gson + 2.8.2 + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 3.0.2 + + + + test-jar + + + + + + com.mycila + license-maven-plugin + 3.0 + +
License.txt
+ + **/*.java + **/*.ksh + **/*.sh + **/*.ftl + **/*.xsd + **/*.xjb + **/*.yml + **/*.yaml + **/aai*.xml + **/*logback*.xml + **/*aaiconfig*.properties + **/*titan*.properties + +
+ + + + format + + process-sources + + +
+
+
+
diff --git a/src/main/java/org/onap/aai/champ/ChampAPI.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/ChampAPI.java similarity index 90% rename from src/main/java/org/onap/aai/champ/ChampAPI.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/ChampAPI.java index 364f8e9..719306f 100644 --- a/src/main/java/org/onap/aai/champ/ChampAPI.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/ChampAPI.java @@ -19,9 +19,9 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ; +package org.onap.aai.champcore; -import org.onap.aai.champ.graph.impl.ChampAPIImpl; +import org.onap.aai.champcore.graph.impl.ChampAPIImpl; public interface ChampAPI { @@ -33,14 +33,14 @@ public interface ChampAPI { public static final class Factory { private Factory() { throw new RuntimeException("Cannot instantiate ChampAPI.Factory"); } - public static ChampAPI newInstance(ChampGraph.Type type) { + public static ChampAPI newInstance(String type) { return new ChampAPIImpl(type); } } public ChampGraph getGraph(String graphName); - public ChampGraph.Type getType(); + public String getType(); /** * Shutdown the ChampAPI. It is up to the caller to synchronize access to the ChampAPI diff --git a/src/main/java/org/onap/aai/champ/ChampCapabilities.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/ChampCapabilities.java similarity index 97% rename from src/main/java/org/onap/aai/champ/ChampCapabilities.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/ChampCapabilities.java index c7ded86..b0c62cb 100644 --- a/src/main/java/org/onap/aai/champ/ChampCapabilities.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/ChampCapabilities.java @@ -19,7 +19,7 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ; +package org.onap.aai.champcore; public interface ChampCapabilities { diff --git a/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/ChampGraph.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/ChampGraph.java new file mode 100644 index 0000000..74c1cf8 --- /dev/null +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/ChampGraph.java @@ -0,0 +1,627 @@ +/** + * ============LICENSE_START========================================== + * org.onap.aai + * =================================================================== + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 Amdocs + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END============================================ + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.champcore; + +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.stream.Stream; + +import org.onap.aai.champcore.exceptions.ChampIndexNotExistsException; +import org.onap.aai.champcore.exceptions.ChampMarshallingException; +import org.onap.aai.champcore.exceptions.ChampObjectNotExistsException; +import org.onap.aai.champcore.exceptions.ChampRelationshipNotExistsException; +import org.onap.aai.champcore.exceptions.ChampSchemaViolationException; +import org.onap.aai.champcore.exceptions.ChampTransactionException; +import org.onap.aai.champcore.exceptions.ChampUnmarshallingException; +import org.onap.aai.champcore.model.ChampObject; +import org.onap.aai.champcore.model.ChampObjectConstraint; +import org.onap.aai.champcore.model.ChampObjectIndex; +import org.onap.aai.champcore.model.ChampPartition; +import org.onap.aai.champcore.model.ChampRelationship; +import org.onap.aai.champcore.model.ChampRelationshipConstraint; +import org.onap.aai.champcore.model.ChampRelationshipIndex; +import org.onap.aai.champcore.model.ChampSchema; + +public interface ChampGraph { + + /** + * Opens a transaction within the graph data store. + * + * @return - A transaction object. + */ + public ChampTransaction openTransaction(); + + /** + * Attempts to commit the supplied open transaction. + * + * @param transaction - The transaction to be committed. + * + * @throws ChampTransactionException - If an attempt to commit or rollback the transaction failed. + */ + public void commitTransaction(ChampTransaction transaction) throws ChampTransactionException; + + /** + * Attempts to roll back the supplied open transaction. + * + * @param transaction - The transaction to be committed. + * + * @throws ChampTransactionException - If an attempt to commit or rollback the transaction failed. + */ + public void rollbackTransaction(ChampTransaction transaction) throws ChampTransactionException; + + /** + * Create/Update an object. + *

+ * If the ChampObject key is present, an update will be attempted, + * otherwise a create will be attempted. Each implementation has different guarantees on + * validation - see the specific implementation for more details on this. + * + * @param object - The ChampObject that you wish to store in the graph + * + * @return The ChampObject as it was stored + * + * @throws ChampMarshallingException If the {@code object} is not able to be marshalled into the backend representation + * @throws ChampSchemaViolationException If the {@code object} violates the constraints specifed by {@link ChampGraph#retrieveSchema} + * @throws ChampObjectNotExistsException If {@link org.onap.aai.champcore.model.ChampObject#getKey}.isPresent() but the object cannot be found in the graph + * @throws ChampTransactionException If an attempt to commit or rollback the transaction failed. + */ + public ChampObject storeObject(ChampObject object) throws ChampMarshallingException, ChampSchemaViolationException, ChampObjectNotExistsException, ChampTransactionException; + + /** + * Create/Update an object. + *

+ * If the ChampObject key is present, an update will be attempted, + * otherwise a create will be attempted. Each implementation has different guarantees on + * validation - see the specific implementation for more details on this. + *

+ * If a transaction context is not provided, then a transaction will be automatically + * created and committed for this operation only, otherwise, the supplied transaction + * will be used and it will be up to the caller to commit the transaction at its + * discretion. + * + * @param object - The ChampObject that you wish to store in the graph + * @param transaction - Optional transaction context to perform the operation in. + * + * @return The ChampObject as it was stored + * + * @throws ChampMarshallingException If the {@code object} is not able to be marshalled into the backend representation + * @throws ChampSchemaViolationException If the {@code object} violates the constraints specifed by {@link ChampGraph#retrieveSchema} + * @throws ChampObjectNotExistsException If {@link org.onap.aai.champcore.model.ChampObject#getKey}.isPresent() but the object cannot be found in the graph + * @throws ChampTransactionException If an attempt to commit or rollback the transaction failed. + */ + public ChampObject storeObject(ChampObject object, Optional transaction) throws ChampMarshallingException, ChampSchemaViolationException, ChampObjectNotExistsException, ChampTransactionException; + + /** + * Replace an object. ChampObject key is mandatory + *

+ * Each implementation has different guarantees on validation - see the specific implementation + * for more details on this. + * + * @param object - The ChampObject that you wish to replace in the graph + * + * @return The ChampObject as it was stored + * + * @throws ChampMarshallingException If the {@code object} is not able to be marshalled into the backend representation + * @throws ChampSchemaViolationException If the {@code object} violates the constraints specifed by {@link ChampGraph#retrieveSchema} + * @throws ChampObjectNotExistsException If {@link org.onap.aai.champcore.model.ChampObject#getKey} is not present or object not found in the graph + * @throws ChampTransactionException If an attempt to commit or rollback the transaction failed. + */ + public ChampObject replaceObject(ChampObject object) throws ChampMarshallingException, ChampSchemaViolationException, ChampObjectNotExistsException, ChampTransactionException; + + /** + * Replace an object. ChampObject key is mandatory + *

+ * Each implementation has different guarantees on validation - see the specific implementation + * for more details on this. + *

+ * If a transaction context is not provided, then a transaction will be automatically + * created and committed for this operation only, otherwise, the supplied transaction + * will be used and it will be up to the caller to commit the transaction at its + * discretion. + * + * @param object - The ChampObject that you wish to replace in the graph + * @param transaction - Optional transaction context to perform the operation in. + * + * @return The ChampObject as it was stored + * + * @throws ChampMarshallingException If the {@code object} is not able to be marshalled into the backend representation + * @throws ChampSchemaViolationException If the {@code object} violates the constraints specifed by {@link ChampGraph#retrieveSchema} + * @throws ChampObjectNotExistsException If {@link org.onap.aai.champcore.model.ChampObject#getKey} is not present or object not found in the graph + * @throws ChampTransactionException If an attempt to commit or rollback the transaction failed. + */ + public ChampObject replaceObject(ChampObject object, Optional transaction) throws ChampMarshallingException, ChampSchemaViolationException, ChampObjectNotExistsException, ChampTransactionException; + + /** + * Retrieve an object by its key. + * + * @param key - The key of the ChampObject in the graph {@link org.onap.aai.champcore.model.ChampObject#getKey()} + * + * @return The {@link org.onap.aai.champcore.model.ChampObject} if it was present, otherwise {@link Optional#empty()} + * + * @throws ChampUnmarshallingException If the object was found, but could not be unmarshalled + * @throws ChampTransactionException If an attempt to commit or rollback the transaction failed. + */ + public Optional retrieveObject(Object key) throws ChampUnmarshallingException, ChampTransactionException; + + + /** + * Retrieve an object by its key. + *

+ * If a transaction context is not provided, then a transaction will be automatically + * created and committed for this operation only, otherwise, the supplied transaction + * will be used and it will be up to the caller to commit the transaction at its + * discretion. + * + * @param key - The key of the ChampObject in the graph {@link org.onap.aai.champcore.model.ChampObject#getKey()} + * @param transaction - Optional transaction context to perform the operation in. + * + * @return The {@link org.onap.aai.champcore.model.ChampObject} if it was present, otherwise {@link Optional#empty()} + * + * @throws ChampUnmarshallingException If the object was found, but could not be unmarshalled + * @throws ChampTransactionException If an attempt to commit or rollback the transaction failed. + */ + public Optional retrieveObject(Object key, Optional transaction) throws ChampUnmarshallingException, ChampTransactionException; + + /** + * Delete an object by its key. + * + * @param key - The key of the ChampObject in the graph {@link ChampObject#getKey} + * + * @throws ChampObjectNotExistsException If the object did not exist in the graph + * @throws ChampTransactionException If an attempt to commit or rollback the transaction failed. + */ + public void deleteObject(Object key) throws ChampObjectNotExistsException, ChampTransactionException; + + /** + * Delete an object by its key. + *

+ * If a transaction context is not provided, then a transaction will be automatically + * created and committed for this operation only, otherwise, the supplied transaction + * will be used and it will be up to the caller to commit the transaction at its + * discretion. + * + * @param key - The key of the ChampObject in the graph {@link ChampObject#getKey} + * @param transaction - Optional transaction context to perform the operation in. + * + * @throws ChampObjectNotExistsException If the object did not exist in the graph + * @throws ChampTransactionException If an attempt to commit or rollback the transaction failed. + */ + public void deleteObject(Object key, Optional transaction) throws ChampObjectNotExistsException, ChampTransactionException; + + /** + * Retrieve all the objects whose properties match the given {@code queryParams} + * + * @param queryParams - The key/value pairs which are found in {@link ChampObject#getProperties} + * + * @return - A {@link Stream} where each {@link ChampObject#getProperties} contains the {@code queryParams} + * + * @throws ChampTransactionException If an attempt to commit or rollback the transaction failed. + */ + public Stream queryObjects(Map queryParams) throws ChampTransactionException; + + + /** + * Retrieve all the objects whose properties match the given {@code queryParams} + *

+ * If a transaction context is not provided, then a transaction will be automatically + * created and committed for this operation only, otherwise, the supplied transaction + * will be used and it will be up to the caller to commit the transaction at its + * discretion. + * + * @param queryParams - The key/value pairs which are found in {@link ChampObject#getProperties} + * @param transaction - Optional transaction context to perform the operation in. + * + * @return - A {@link Stream} where each {@link ChampObject#getProperties} contains the {@code queryParams} + * + * @throws ChampTransactionException If an attempt to commit or rollback the transaction failed. + */ + public Stream queryObjects(Map queryParams, Optional transaction) throws ChampTransactionException; + + /** + * Create/Update a relationship. + *

+ * If the ChampRelationship key is present, an update will be attempted, + * otherwise a create will be attempted. Each implementation has different guarantees on + * validation - see the specific implementation for more details on this. + * + * @param relationship - The ChampRelationship that you wish to store in the graph + * + * @return The ChampRelationship as it was stored + * + * @throws ChampMarshallingException If the {@code relationship} is not able to be marshalled into the backend representation + * @throws ChampSchemaViolationException If the {@code relationship} violates the constraints specifed by {@link ChampGraph#retrieveSchema} + * @throws ChampObjectNotExistsException If either the source or target object referenced by this relationship does not exist in the graph + * @throws ChampRelationshipNotExistsException If {@link org.onap.aai.champcore.model.ChampRelationship#getKey}.isPresent() but the object cannot be found in the graph + * @throws ChampUnmarshallingException If the edge which was created could not be unmarshalled into a ChampRelationship + * @throws ChampTransactionException If an attempt to commit or rollback the transaction failed. + */ + public ChampRelationship storeRelationship(ChampRelationship relationship) throws ChampMarshallingException, ChampObjectNotExistsException, ChampSchemaViolationException, ChampRelationshipNotExistsException, ChampUnmarshallingException, ChampTransactionException; + + + /** + * Create/Update a relationship. + *

+ * If the ChampRelationship key is present, an update will be attempted, + * otherwise a create will be attempted. Each implementation has different guarantees on + * validation - see the specific implementation for more details on this. + *

+ * If a transaction context is not provided, then a transaction will be automatically + * created and committed for this operation only, otherwise, the supplied transaction + * will be used and it will be up to the caller to commit the transaction at its + * discretion. + * + * @param relationship - The ChampRelationship that you wish to store in the graph + * @param transaction - Optional transaction context to perform the operation in. + * + * @return The ChampRelationship as it was stored + * + * @throws ChampMarshallingException If the {@code relationship} is not able to be marshalled into the backend representation + * @throws ChampSchemaViolationException If the {@code relationship} violates the constraints specifed by {@link ChampGraph#retrieveSchema} + * @throws ChampObjectNotExistsException If either the source or target object referenced by this relationship does not exist in the graph + * @throws ChampRelationshipNotExistsException If {@link org.onap.aai.champcore.model.ChampRelationship#getKey}.isPresent() but the object cannot be found in the graph + * @throws ChampUnmarshallingException If the edge which was created could not be unmarshalled into a ChampRelationship + * @throws ChampTransactionException If an attempt to commit or rollback the transaction failed. + */ + public ChampRelationship storeRelationship(ChampRelationship relationship, Optional transaction) throws ChampMarshallingException, ChampObjectNotExistsException, ChampSchemaViolationException, ChampRelationshipNotExistsException, ChampUnmarshallingException, ChampTransactionException; + + /** + * Replace a relationship. + *

+ * ChampRelationship key is mandatory. The main purpose of this method is to replace the + * entire properties of an existing relationship. Source/Target can't be updated with this method. + *

+ * Each implementation has different guarantees on validation - see the specific implementation + * for more details on this. + * + * @param relationship - The ChampRelationship that you wish to replace in the graph + * + * @return The ChampRelationship as it was stored + * + * @throws ChampMarshallingException If the {@code relationship} is not able to be marshalled into the backend representation + * @throws ChampSchemaViolationException If the {@code relationship} violates the constraints specifed by {@link ChampGraph#retrieveSchema} + * @throws ChampRelationshipNotExistsException If {@link org.onap.aai.champcore.model.ChampRelationship#getKey} is not present or object not found in the graph + * @throws ChampUnmarshallingException If the edge which was created could not be unmarshalled into a ChampRelationship + * @throws ChampTransactionException If an attempt to commit or rollback the transaction failed. + */ + public ChampRelationship replaceRelationship(ChampRelationship relationship) throws ChampMarshallingException, ChampSchemaViolationException, ChampRelationshipNotExistsException, ChampUnmarshallingException, ChampTransactionException; + + /** + * Replace a relationship. + *

+ * ChampRelationship key is mandatory. The main purpose of this method is to replace the + * entire properties of an existing relationship. Source/Target can't be updated with this method. + *

+ * Each implementation has different guarantees on validation - see the specific implementation + * for more details on this. + *

+ * If a transaction context is not provided, then a transaction will be automatically + * created and committed for this operation only, otherwise, the supplied transaction + * will be used and it will be up to the caller to commit the transaction at its + * discretion. + * + * @param relationship - The ChampRelationship that you wish to replace in the graph + * @param transaction - Optional transaction context to perform the operation in. + * + * @return The ChampRelationship as it was stored + * + * @throws ChampMarshallingException If the {@code relationship} is not able to be marshalled into the backend representation + * @throws ChampSchemaViolationException If the {@code relationship} violates the constraints specifed by {@link ChampGraph#retrieveSchema} + * @throws ChampRelationshipNotExistsException If {@link org.onap.aai.champcore.model.ChampRelationship#getKey} is not present or object not found in the graph + * @throws ChampUnmarshallingException If the edge which was created could not be unmarshalled into a ChampRelationship + * @throws ChampTransactionException If an attempt to commit or rollback the transaction failed. + */ + public ChampRelationship replaceRelationship(ChampRelationship relationship, Optional transaction) throws ChampMarshallingException, ChampSchemaViolationException, ChampRelationshipNotExistsException, ChampUnmarshallingException, ChampTransactionException; + + /** + * Retrieve a relationship by its key. + * + * @param key - The key of the ChampRelationship in the graph + * {@link org.onap.aai.champcore.model.ChampRelationship#getKey()} + * + * @return The {@link org.onap.aai.champcore.model.ChampRelationship} if it was present, otherwise {@link Optional#empty()} + * + * @throws ChampUnmarshallingException If the relationship was found, but could not be unmarshalled + * @throws ChampTransactionException If an attempt to commit or rollback the transaction failed. + */ + public Optional retrieveRelationship(Object key) throws ChampUnmarshallingException, ChampTransactionException; + + + /** + * Retrieve a relationship by its key. + *

+ * If a transaction context is not provided, then a transaction will be automatically + * created and committed for this operation only, otherwise, the supplied transaction + * will be used and it will be up to the caller to commit the transaction at its + * discretion. + * + * @param key - The key of the ChampRelationship in the graph + * {@link org.onap.aai.champcore.model.ChampRelationship#getKey()} + * @param transaction - Optional transaction context to perform the operation in. + * + * @return The {@link org.onap.aai.champcore.model.ChampRelationship} if it was present, otherwise {@link Optional#empty()} + * + * @throws ChampUnmarshallingException If the relationship was found, but could not be unmarshalled + * @throws ChampTransactionException If an attempt to commit or rollback the transaction failed. + */ + public Optional retrieveRelationship(Object key, Optional transaction) throws ChampUnmarshallingException, ChampTransactionException; + + /** + * Delete a relationship by its key. + * + * @param relationship - The ChampRelationship in the graph ({@link ChampRelationship#getKey must be present}) + * + * @throws ChampRelationshipNotExistsException If the object did not exist in the graph + * @throws ChampTransactionException If an attempt to commit or rollback the transaction failed. + */ + public void deleteRelationship(ChampRelationship relationship) throws ChampRelationshipNotExistsException, ChampTransactionException; + + /** + * Delete a relationship by its key. + *

+ * If a transaction context is not provided, then a transaction will be automatically + * created and committed for this operation only, otherwise, the supplied transaction + * will be used and it will be up to the caller to commit the transaction at its + * discretion. + * + * @param relationship - The ChampRelationship in the graph ({@link ChampRelationship#getKey must be present}) + * @param transaction - Optional transaction context to perform the operation in. + * + * @throws ChampRelationshipNotExistsException If the object did not exist in the graph + * @throws ChampTransactionException If an attempt to commit or rollback the transaction failed. + */ + public void deleteRelationship(ChampRelationship relationship, Optional transaction) throws ChampRelationshipNotExistsException, ChampTransactionException; + + /** + * Retrieve the relationships which are incident to the {@code object} + * + * @param object - The object you wish to find incident relationships for + * + * @return A {@link Stream} where each {@link ChampRelationship} has this {@code object} as either a source or target object + * + * @throws ChampUnmarshallingException If any of the ChampRelationship objects could not be unmarshalled + * @throws ChampObjectNotExistsException If the {@code object} does not exist in this graph + * @throws ChampTransactionException If an attempt to commit or rollback the transaction failed. + */ + public Stream retrieveRelationships(ChampObject object) throws ChampUnmarshallingException, ChampObjectNotExistsException, ChampTransactionException; + + + /** + * Retrieve the relationships which are incident to the {@code object} + *

+ * If a transaction context is not provided, then a transaction will be automatically + * created and committed for this operation only, otherwise, the supplied transaction + * will be used and it will be up to the caller to commit the transaction at its + * discretion. + * + * @param object - The object you wish to find incident relationships for + * @param transaction - Optional transaction context to perform the operation in. + * + * @return A {@link Stream} where each {@link ChampRelationship} has this {@code object} as either a source or target object + * + * @throws ChampUnmarshallingException If any of the ChampRelationship objects could not be unmarshalled + * @throws ChampObjectNotExistsException If the {@code object} does not exist in this graph + * @throws ChampTransactionException If an attempt to commit or rollback the transaction failed. + */ + public Stream retrieveRelationships(ChampObject object, Optional transaction) throws ChampUnmarshallingException, ChampObjectNotExistsException, ChampTransactionException; + + /** + * Retrieve the relationships whose properties match the given {@code queryParams} + * + * @param queryParams - The key/value pairs to search for in the {@link ChampRelationship#getProperties} + * + * @return A {@link Stream} where each {@link ChampRelationship#getProperties} contains the {@code queryParams} + * + * @throws ChampTransactionException If an attempt to commit or rollback the transaction failed. + */ + public Stream queryRelationships(Map queryParams) throws ChampTransactionException; + + /** + * Retrieve the relationships whose properties match the given {@code queryParams} + *

+ * If a transaction context is not provided, then a transaction will be automatically + * created and committed for this operation only, otherwise, the supplied transaction + * will be used and it will be up to the caller to commit the transaction at its + * discretion. + * + * @param queryParams - The key/value pairs to search for in the {@link ChampRelationship#getProperties} + * @param transaction - Optional transaction context to perform the operation in. + * + * @return A {@link Stream} where each {@link ChampRelationship#getProperties} contains the {@code queryParams} + * + * @throws ChampTransactionException If an attempt to commit or rollback the transaction failed. + */ + public Stream queryRelationships(Map queryParams, Optional transaction) throws ChampTransactionException; + + /** + * Create/Update a {@link ChampPartition}. If any of the ChampObjects or ChampRelationships + * present in this ChampPartition already exist, an update will be attempted, otherwise a create + * will be attempted. + *

+ * Each implementation has different guarantees on validation - + * see the specific implementation details for more information on this. + * + * @param partition - The ChampPartition you wish to store in this graph + * + * @throws ChampMarshallingException If any of the objects or relationships contained in this + * partition could not be marshalled into its backed representation + * @throws ChampObjectNotExistsException If any of the objects being updated do not exist, or if a relationship + * contain objects which do not exist in the graph. + * @throws ChampSchemaViolationException If any of the objects or relationships violate the schema provided by {@link retrieveSchema} + * @throws ChampRelationshipNotExistsException If any of the relationships which are being updated do not exist + * @throws ChampTransactionException If an attempt to commit or rollback the transaction failed. + * + * @return The ChampPartition as is was stored in the graph (contains keys for each newly created object) + */ + public ChampPartition storePartition(ChampPartition partition) throws ChampMarshallingException, ChampObjectNotExistsException, ChampSchemaViolationException, ChampRelationshipNotExistsException, ChampTransactionException; + + /** + * Create/Update a {@link ChampPartition}. If any of the ChampObjects or ChampRelationships + * present in this ChampPartition already exist, an update will be attempted, otherwise a create + * will be attempted. + *

+ * Each implementation has different guarantees on validation - + * see the specific implementation details for more information on this. + *

+ * If a transaction context is not provided, then a transaction will be automatically + * created and committed for this operation only, otherwise, the supplied transaction + * will be used and it will be up to the caller to commit the transaction at its + * discretion. + * + * @param partition - The ChampPartition you wish to store in this graph + * @param transaction - Optional transaction context to perform the operation in. + * + * @throws ChampMarshallingException If any of the objects or relationships contained in this + * partition could not be marshalled into its backed representation + * @throws ChampObjectNotExistsException If any of the objects being updated do not exist, or if a relationship + * contain objects which do not exist in the graph. + * @throws ChampSchemaViolationException If any of the objects or relationships violate the schema provided by {@link retrieveSchema} + * @throws ChampRelationshipNotExistsException If any of the relationships which are being updated do not exist + * @throws ChampTransactionException If an attempt to commit or rollback the transaction failed. + * + * @return The ChampPartition as is was stored in the graph (contains keys for each newly created object) + */ + public ChampPartition storePartition(ChampPartition partition, Optional transaction) throws ChampMarshallingException, ChampObjectNotExistsException, ChampSchemaViolationException, ChampRelationshipNotExistsException, ChampTransactionException; + + /** + * Delete the {@code partition} from the graph. + * + * @param partition - The partition to delete from the graph + * + * @throws ChampTransactionException If an attempt to commit or rollback the transaction failed. + */ + public void deletePartition(ChampPartition partition) throws ChampTransactionException; + + /** + * Delete the {@code partition} from the graph. + *

+ * If a transaction context is not provided, then a transaction will be automatically + * created and committed for this operation only, otherwise, the supplied transaction + * will be used and it will be up to the caller to commit the transaction at its + * discretion. + * + * @param partition - The partition to delete from the graph + * @param transaction - Optional transaction context to perform the operation in. + * + * @throws ChampTransactionException If an attempt to commit or rollback the transaction failed. + */ + public void deletePartition(ChampPartition partition, Optional transaction) throws ChampTransactionException; + + /** + * Create/Update an object index on the graph + * @param index - The index to create on this {@code graph} + */ + public void storeObjectIndex(ChampObjectIndex index); + + /** + * Retrieve an object index on the graph by its {@code indexName} + * @param indexName The name of the index to retrieve from the graph + * @return The {@link ChampObjectIndex} which matches the given @{code indexName} in the graph + */ + public Optional retrieveObjectIndex(String indexName); + + /** + * Retrieve the object indices on the graph + * @return A {@link Stream} where each {@link ChampObjectIndex} exists in the graph + */ + public Stream retrieveObjectIndices(); + + /** + * Delete the object index on the graph by its {@code indexName} + * @param indexName The name of the index to delete from the graph + * @throws ChampIndexNotExistsException If an index does not exist with the given {@code indexName} in the graph + */ + public void deleteObjectIndex(String indexName) throws ChampIndexNotExistsException; + + /** + * Create/Update a relationship index on the graph + * @param index The relationship index to create on the graph + */ + public void storeRelationshipIndex(ChampRelationshipIndex index); + + /** + * Retrieve a relationship index from the graph + * @param indexName The name of the relationship index to retrieve from the graph + * @return The {@link ChampRelationshipIndex} which matches the given {@code indexName} in the graph + * or {@link Optional#empty} if no such relationship index exists + */ + public Optional retrieveRelationshipIndex(String indexName); + + /** + * Retrieve the relationship indices from the graph + * @return A {@link Stream} where each {@link ChampRelationshipIndex} exists in the graph + */ + public Stream retrieveRelationshipIndices(); + + /** + * Delete a relationship index from the graph + * @param indexName THe name of the index to delete from the graph + * @throws ChampIndexNotExistsException If an index does not exist with the give {@code indexName} in the graph + */ + public void deleteRelationshipIndex(String indexName) throws ChampIndexNotExistsException; + + /** + * Create/Update the schema for a graph + * @param schema The {@link ChampSchema} to create or update on the graph + * @throws ChampSchemaViolationException If this schema update would violate the current schema + */ + public void storeSchema(ChampSchema schema) throws ChampSchemaViolationException; + + /** + * Retrieve the schema for a graph + * @return The {@link ChampSchema} for the graph + */ + public ChampSchema retrieveSchema(); + + /** + * Create/Update an object constraint on a schema + * @param objectConstraint The object constraint you wish to create/update for the graph + * @throws ChampSchemaViolationException If this schema update would violate the current schema + */ + public void updateSchema(ChampObjectConstraint objectConstraint) throws ChampSchemaViolationException; + + /** + * Create/Update a relationship constraint on a schema + * @param schema The relationship constraint you wish to create/update for the graph + * @throws ChampSchemaViolationException If this schema update would violate the current schema + */ + public void updateSchema(ChampRelationshipConstraint schema) throws ChampSchemaViolationException; + + /** + * Delete the schema for a graph + */ + public void deleteSchema(); + + /** + * Shutdown the ChampAPI. It is up to the caller to synchronize access to the ChampAPI + * so that shutting it down does not interfere with concurrent operations. + */ + public void shutdown(); + + /** + * Used to determine what the outcome of certain ChampGraph operations will be. For example, + * if this graph is not capable of deleting object indices, you can expect those calls to fail. + * @see ChampCapabilities + * @return What this graph is capable of performing + */ + public ChampCapabilities capabilities(); +} diff --git a/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/ChampTransaction.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/ChampTransaction.java new file mode 100644 index 0000000..5dab092 --- /dev/null +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/ChampTransaction.java @@ -0,0 +1,73 @@ +/** + * ============LICENSE_START========================================== + * org.onap.aai + * =================================================================== + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 Amdocs + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END============================================ + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.champcore; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.UUID; + +import org.onap.aai.champcore.event.ChampEvent; +import org.onap.aai.champcore.exceptions.ChampTransactionException; + +/** + * This class defines the interface for a graph transaction object. + */ +public abstract class ChampTransaction { + + /** Unique identifier for this transaction (largely for logging purposes). */ + protected UUID id; + + protected List eventList = Collections.synchronizedList(new ArrayList()); + + public ChampTransaction() { + + // Create a unique identifier for this transaction. + id = UUID.randomUUID(); + } + + public String id() { + return id.toString(); + } + + public void logEvent(ChampEvent event) { + eventList.add(event); + } + + public List getEnqueuedEvents() { + return eventList; + } + + /** + * Finalize all updates to the graph which have been made within the context + * of this transaction. + */ + public abstract void commit() throws ChampTransactionException ; + + + /** + * Aborts all graph changes made within the context of this transaction, backing + * out all changes as if they had never happened. + */ + public abstract void rollback() throws ChampTransactionException ; + +} diff --git a/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/FormatMapper.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/FormatMapper.java new file mode 100644 index 0000000..6d4db09 --- /dev/null +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/FormatMapper.java @@ -0,0 +1,30 @@ +/** + * ============LICENSE_START========================================== + * org.onap.aai + * =================================================================== + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 Amdocs + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END============================================ + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.champcore; + +import com.google.gson.JsonObject; + +public interface FormatMapper { + JsonObject formatObject( Object var1) throws Exception; + + int parallelThreshold(); +} \ No newline at end of file diff --git a/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/Formatter.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/Formatter.java new file mode 100644 index 0000000..a6292f3 --- /dev/null +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/Formatter.java @@ -0,0 +1,77 @@ +/** + * ============LICENSE_START========================================== + * org.onap.aai + * =================================================================== + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 Amdocs + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END============================================ + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.champcore; + +import com.att.eelf.configuration.EELFLogger; +import com.att.eelf.configuration.EELFManager; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import java.util.List; +import java.util.Optional; +import java.util.stream.Stream; + +public class Formatter { + + private static final EELFLogger LOGGER = EELFManager.getInstance().getLogger(Formatter.class); + protected JsonParser parser = new JsonParser(); + protected final FormatMapper format; + + public Formatter(FormatMapper format) { + this.format = format; + } + + public JsonObject output(List vertices) { + Stream stream = null; + JsonObject result = new JsonObject(); + JsonArray body = new JsonArray(); + if (vertices.size() >= this.format.parallelThreshold()) { + stream = vertices.parallelStream(); + } else { + stream = vertices.stream(); + } + + boolean isParallel = stream.isParallel(); + stream.map((v) -> { + try { + return Optional.of(this.format.formatObject(v)); + } catch (Exception var3) { + LOGGER.warn("Failed to format vertex, returning a partial list", var3); + return Optional.empty(); + } + }).forEach((obj) -> { + if (obj.isPresent()) { + if (isParallel) { + synchronized(body) { + body.add((JsonElement)obj.get()); + } + } else { + body.add((JsonElement)obj.get()); + } + } + + }); + result.add("results", body); + return result.getAsJsonObject(); + } +} \ No newline at end of file diff --git a/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/NoOpTinkerPopTransaction.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/NoOpTinkerPopTransaction.java new file mode 100644 index 0000000..208b2d1 --- /dev/null +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/NoOpTinkerPopTransaction.java @@ -0,0 +1,57 @@ +/** + * ============LICENSE_START========================================== + * org.onap.aai + * =================================================================== + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 Amdocs + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END============================================ + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.champcore; + +import org.apache.tinkerpop.gremlin.structure.Graph; +import org.onap.aai.champcore.graph.impl.TinkerpopTransaction; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class NoOpTinkerPopTransaction extends TinkerpopTransaction { + + protected Graph graph; + + private static final Logger LOGGER = LoggerFactory.getLogger(NoOpTinkerPopTransaction.class); + + + public NoOpTinkerPopTransaction(Graph aGraphInstance) { + + this.graph = aGraphInstance; + } + + public Graph getGraphInstance() { + return graph; + } + + @Override + public void commit() { + // Do nothing. + } + + @Override + public void rollback() { + + + // Do nothing. + } + +} diff --git a/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/event/AbstractLoggingChampGraph.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/event/AbstractLoggingChampGraph.java new file mode 100644 index 0000000..79a7f3c --- /dev/null +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/event/AbstractLoggingChampGraph.java @@ -0,0 +1,792 @@ +/** + * ============LICENSE_START========================================== + * org.onap.aai + * =================================================================== + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 Amdocs + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END============================================ + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.champcore.event; + + +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.Stream; + +import org.onap.aai.champcore.ChampCapabilities; +import org.onap.aai.champcore.ChampGraph; +import org.onap.aai.champcore.ChampTransaction; +import org.onap.aai.champcore.event.ChampEvent.ChampOperation; +import org.onap.aai.champcore.exceptions.ChampIndexNotExistsException; +import org.onap.aai.champcore.exceptions.ChampMarshallingException; +import org.onap.aai.champcore.exceptions.ChampObjectNotExistsException; +import org.onap.aai.champcore.exceptions.ChampRelationshipNotExistsException; +import org.onap.aai.champcore.exceptions.ChampSchemaViolationException; +import org.onap.aai.champcore.exceptions.ChampTransactionException; +import org.onap.aai.champcore.exceptions.ChampUnmarshallingException; +import org.onap.aai.champcore.model.ChampObject; +import org.onap.aai.champcore.model.ChampObjectConstraint; +import org.onap.aai.champcore.model.ChampObjectIndex; +import org.onap.aai.champcore.model.ChampPartition; +import org.onap.aai.champcore.model.ChampRelationship; +import org.onap.aai.champcore.model.ChampRelationshipConstraint; +import org.onap.aai.champcore.model.ChampRelationshipIndex; +import org.onap.aai.champcore.model.ChampSchema; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.onap.aai.event.api.EventPublisher; + + + +/** + * This class provides the hooks to allow Champ operations to be logged to an event + * stream. + */ +public abstract class AbstractLoggingChampGraph implements ChampGraph { + + private static final Logger logger = LoggerFactory.getLogger(AbstractLoggingChampGraph.class); + + public abstract Optional retrieveObject(Object key) throws ChampUnmarshallingException, ChampTransactionException; + public abstract Optional retrieveObject(Object key, Optional transaction) throws ChampUnmarshallingException, ChampTransactionException; + public abstract Stream queryObjects(Map queryParams) throws ChampTransactionException; + public abstract Stream queryObjects(Map queryParams, Optional transaction) throws ChampTransactionException; + @Override + public abstract Optional retrieveRelationship(Object key) throws ChampUnmarshallingException, ChampTransactionException; + @Override + public abstract Optional retrieveRelationship(Object key, Optional transaction) throws ChampUnmarshallingException, ChampTransactionException; + public abstract Stream retrieveRelationships(ChampObject object) throws ChampUnmarshallingException, ChampObjectNotExistsException, ChampTransactionException; + public abstract Stream retrieveRelationships(ChampObject object, Optional transaction) throws ChampUnmarshallingException, ChampObjectNotExistsException, ChampTransactionException; + public abstract Stream queryRelationships(Map queryParams) throws ChampTransactionException; + public abstract Stream queryRelationships(Map queryParams, Optional transaction) throws ChampTransactionException; + + + /** + * Creates or updates a vertex in the graph data store. + *

+ * If a transaction context is not provided, then a transaction will be automatically + * created and committed for this operation only, otherwise, the supplied transaction + * will be used and it will be up to the caller to commit the transaction at its + * discretion. + * + * @param object - The vertex to be created or updated. + * @param transaction - Optional transaction context to perform the operation in. + * + * @return - The vertex, as created, marshaled as a {@link ChampObject} + * + * @throws ChampMarshallingException - If the {@code object} is not able to be marshalled + * into the backend representation + * @throws ChampSchemaViolationException - If the {@code object} violates the constraints specifed + * by {@link ChampGraph#retrieveSchema} + * @throws ChampObjectNotExistsException - If {@link org.onap.aai.champcore.model.ChampObject#getKey} + * is not present or object not found in the graph + * @throws ChampTransactionException - If an attempt to commit or rollback the transaction failed. + */ + public abstract ChampObject executeStoreObject(ChampObject object, Optional transaction) throws ChampMarshallingException, ChampSchemaViolationException, ChampObjectNotExistsException, ChampTransactionException; + + /** + * Updates an existing vertex in the graph store. + *

+ * If a transaction context is not provided, then a transaction will be automatically + * created and committed for this operation only, otherwise, the supplied transaction + * will be used and it will be up to the caller to commit the transaction at its + * discretion. + * + * @param object - The vertex to be created or updated. + * @param transaction - Optional transaction context to perform the operation in. + * + * @return - The updated vertex, marshaled as a {@link ChampObject} + * + * @throws ChampMarshallingException - If the {@code object} is not able to be marshalled into + * the backend representation + * @throws ChampSchemaViolationException - If the {@code object} violates the constraints specifed + * by {@link ChampGraph#retrieveSchema} + * @throws ChampObjectNotExistsException - If {@link org.onap.aai.champcore.model.ChampObject#getKey} + * is not present or object not found in the graph + * @throws ChampTransactionException - If an attempt to commit or rollback the transaction failed. + */ + public abstract ChampObject executeReplaceObject(ChampObject object, Optional transaction) throws ChampMarshallingException, ChampSchemaViolationException, ChampObjectNotExistsException, ChampTransactionException; + + /** + * Deletes an existing vertex from the graph store. + *

+ * If a transaction context is not provided, then a transaction will be automatically + * created and committed for this operation only, otherwise, the supplied transaction + * will be used and it will be up to the caller to commit the transaction at its + * discretion. + * + * @param key - The key of the ChampObject in the graph {@link ChampObject#getKey} + * @param transaction - Optional transaction context to perform the operation in. + * + * @throws ChampObjectNotExistsException - If {@link org.onap.aai.champcore.model.ChampObject#getKey} + * is not present or object not found in the graph + * @throws ChampTransactionException - If an attempt to commit or rollback the transaction failed. + */ + public abstract void executeDeleteObject(Object key, Optional transaction) throws ChampObjectNotExistsException, ChampTransactionException; + + /** + * Creates or updates an edge in the graph data store. + *

+ * If a transaction context is not provided, then a transaction will be automatically + * created and committed for this operation only, otherwise, the supplied transaction + * will be used and it will be up to the caller to commit the transaction at its + * discretion. + * + * @param relationship - The ChampRelationship that you wish to store in the graph + * @param transaction - Optional transaction context to perform the operation in. + * + * @return - The {@link ChampRelationship} as it was stored. + * + * @throws ChampUnmarshallingException - If the edge which was created could not be + * unmarshalled into a ChampRelationship + * @throws ChampMarshallingException - If the {@code relationship} is not able to be + * marshalled into the backend representation + * @throws ChampObjectNotExistsException - If either the source or target object referenced + * by this relationship does not exist in the graph + * @throws ChampSchemaViolationException - If the {@code relationship} violates the constraints + * specifed by {@link ChampGraph#retrieveSchema} + * @throws ChampRelationshipNotExistsException - If {@link org.onap.aai.champcore.model.ChampRelationship#getKey}.isPresent() + * but the object cannot be found in the graph + * @throws ChampTransactionException - If an attempt to commit or rollback the transaction failed. + */ + public abstract ChampRelationship executeStoreRelationship(ChampRelationship relationship, Optional transaction) throws ChampUnmarshallingException, ChampMarshallingException, ChampObjectNotExistsException, ChampSchemaViolationException, ChampRelationshipNotExistsException, ChampTransactionException; + + /** + * Replaces an existing edge in the graph data store. + *

+ * If a transaction context is not provided, then a transaction will be automatically + * created and committed for this operation only, otherwise, the supplied transaction + * will be used and it will be up to the caller to commit the transaction at its + * discretion. + * + * @param relationship - The ChampRelationship that you wish to replace in the graph + * @param transaction - Optional transaction context to perform the operation in. + * + * @return - The {@link ChampRelationship} as it was stored. + * + * @throws ChampUnmarshallingException - If the edge which was created could not be + * unmarshalled into a ChampRelationship + * @throws ChampMarshallingException - If the {@code relationship} is not able to be + * marshalled into the backend representation + * @throws ChampSchemaViolationException - If the {@code relationship} violates the constraints + * specifed by {@link ChampGraph#retrieveSchema} + * @throws ChampRelationshipNotExistsException - If {@link org.onap.aai.champcore.model.ChampRelationship#getKey}.isPresent() + * but the object cannot be found in the graph + * @throws ChampTransactionException - If an attempt to commit or rollback the transaction failed. + */ + public abstract ChampRelationship executeReplaceRelationship(ChampRelationship relationship, Optional transaction) throws ChampUnmarshallingException, ChampMarshallingException, ChampSchemaViolationException, ChampRelationshipNotExistsException, ChampTransactionException; + + /** + * Removes an edge from the graph data store. + *

+ * If a transaction context is not provided, then a transaction will be automatically + * created and committed for this operation only, otherwise, the supplied transaction + * will be used and it will be up to the caller to commit the transaction at its + * discretion. + * + * @param relationship - The ChampRelationship that you wish to remove from the graph. + * @param transaction - Optional transaction context to perform the operation in. + * + * @throws ChampRelationshipNotExistsException - If {@link org.onap.aai.champcore.model.ChampRelationship#getKey}.isPresent() + * but the object cannot be found in the graph + * @throws ChampTransactionException - If an attempt to commit or rollback the transaction failed. + */ + public abstract void executeDeleteRelationship(ChampRelationship relationship, Optional transaction) throws ChampRelationshipNotExistsException, ChampTransactionException; + + /** + * Create or update a {@link ChampPartition}. + *

+ * If a transaction context is not provided, then a transaction will be automatically + * created and committed for this operation only, otherwise, the supplied transaction + * will be used and it will be up to the caller to commit the transaction at its + * discretion. + * + * @param partition - The ChampPartition that you wish to create or update in the graph. + * @param transaction - Optional transaction context to perform the operation in. + * + * @return - The {@link ChampPartition} as it was stored. + * + * @throws ChampSchemaViolationException - If the {@code relationship} violates the constraints + * specifed by {@link ChampGraph#retrieveSchema} + * @throws ChampRelationshipNotExistsException - If {@link org.onap.aai.champcore.model.ChampRelationship#getKey}.isPresent() + * but the object cannot be found in the graph + * @throws ChampMarshallingException - If the {@code relationship} is not able to be + * marshalled into the backend representation + * @throws ChampObjectNotExistsException - If either the source or target object referenced + * by this relationship does not exist in the graph + * @throws ChampTransactionException - If an attempt to commit or rollback the transaction failed. + */ + public abstract ChampPartition executeStorePartition(ChampPartition partition, Optional transaction) throws ChampSchemaViolationException, ChampRelationshipNotExistsException, ChampMarshallingException, ChampObjectNotExistsException, ChampTransactionException; + + /** + * Removes a partition from the graph. + *

+ * If a transaction context is not provided, then a transaction will be automatically + * created and committed for this operation only, otherwise, the supplied transaction + * will be used and it will be up to the caller to commit the transaction at its + * discretion. + * + * @param graph - The partition to be removed. + * @param transaction - Optional transaction context to perform the operation in. + * + * @throws ChampTransactionException - If an attempt to commit or rollback the transaction failed. + */ + public abstract void executeDeletePartition(ChampPartition graph, Optional transaction) throws ChampTransactionException; + + /** + * Create or update an object index in the graph. + * + * @param index - The object index to be created/updated. + */ + public abstract void executeStoreObjectIndex(ChampObjectIndex index); + + public abstract Optional retrieveObjectIndex(String indexName); + public abstract Stream retrieveObjectIndices(); + public abstract void executeDeleteObjectIndex(String indexName) throws ChampIndexNotExistsException; + public abstract void executeStoreRelationshipIndex(ChampRelationshipIndex index); + public abstract Optional retrieveRelationshipIndex(String indexName); + public abstract Stream retrieveRelationshipIndices(); + public abstract void executeDeleteRelationshipIndex(String indexName) throws ChampIndexNotExistsException; + public abstract void storeSchema(ChampSchema schema) throws ChampSchemaViolationException; + public abstract ChampSchema retrieveSchema(); + public abstract void updateSchema(ChampObjectConstraint objectConstraint) throws ChampSchemaViolationException; + public abstract void updateSchema(ChampRelationshipConstraint schema) throws ChampSchemaViolationException; + public abstract void deleteSchema(); + public abstract ChampCapabilities capabilities(); + + + + public final static String PARAM_EVENT_QUEUE_CAPACITY = "champcore.event.stream.buffer.capacity"; + public final static Integer DEFAULT_EVENT_QUEUE_CAPACITY = 10000; + + public final static String PARAM_EVENT_STREAM_PUBLISHER_POOL_SIZE = "champcore.event.stream.publisher-pool-size"; + public final static Integer DEFAULT_EVENT_STREAM_PUBLISHER_POOL_SIZE = 5; + + public final static String PARAM_EVENT_STREAM_PRODUCER = "champcore.event.stream.publisher"; + + + + /** Number of events that can be queued up for publication before we begin dropping + * events. */ + private Integer eventQueueCapacity; + + /** Number of event publisher worker threads. */ + private Integer eventStreamPublisherPoolSize; + + /** Pool of worker threads that do the work of publishing the events to the event bus. */ + protected ThreadPoolExecutor publisherPool; + + /** Client used for publishing events to the event bus. */ + protected EventPublisher producer; + + /** Internal queue where outgoing events will be buffered until they can be serviced by + * the event publisher worker threads. */ + protected BlockingQueue eventQueue; + + + /** + * Thread factory for the event producer workers. + */ + private class ProducerWorkerThreadFactory implements ThreadFactory { + + private AtomicInteger threadNumber = new AtomicInteger(1); + + public Thread newThread(Runnable r) { + return new Thread(r, "champEventStreamPublisher-" + threadNumber.getAndIncrement()); + } + } + + + /** + * Create a new instance of the AbstractLoggingChampGraph. + * + * @param properties - Set of configuration properties for this graph instance. + */ + protected AbstractLoggingChampGraph(Map properties) { + + // Extract the necessary parameters from the configuration properties. + configure(properties); + + // Make sure we were passed an event producer as one of our properties, otherwise + // there is really nothing more we can do... + if(producer == null) { + logger.error("No event stream producer was supplied."); + logger.error("NOTE!! Champ events will NOT be published to the event stream!"); + return; + } + + // Create the blocking queue that we will use to buffer events that we want + // published to the event bus. + eventQueue = new ArrayBlockingQueue(eventQueueCapacity); + + // Create the executor pool that will do the work of publishing events to the event bus. + publisherPool = + (ThreadPoolExecutor) Executors.newFixedThreadPool(eventStreamPublisherPoolSize, + new ProducerWorkerThreadFactory()); + + try { + + // Start up the producer worker threads. + for(int i=0; i properties) { + + producer = (EventPublisher) properties.get(PARAM_EVENT_STREAM_PRODUCER); + + eventQueueCapacity = + (Integer) getProperty(properties, PARAM_EVENT_QUEUE_CAPACITY, DEFAULT_EVENT_QUEUE_CAPACITY); + eventStreamPublisherPoolSize = + (Integer) getProperty(properties, PARAM_EVENT_STREAM_PUBLISHER_POOL_SIZE, DEFAULT_EVENT_STREAM_PUBLISHER_POOL_SIZE); + } + + + public void setProducer(EventPublisher aProducer) { + + producer = aProducer; + } + + private Object getProperty(Map properties, String property, Object defaultValue) { + + if(properties.containsKey(property)) { + return properties.get(property); + } else { + return defaultValue; + } + } + + @Override + public void shutdown() { + + if(publisherPool != null) { + publisherPool.shutdown(); + + try { + publisherPool.awaitTermination(1000, TimeUnit.MILLISECONDS); + } catch (InterruptedException e) {} + } + + if(producer != null) { + + try { + producer.close(); + + } catch (Exception e) { + logger.error("Failed to stop event stream producer: " + e.getMessage()); + } + } + } + + @Override + public void commitTransaction(ChampTransaction transaction) throws ChampTransactionException { + + try { + + // Commit the transaction. + transaction.commit(); + + } catch (ChampTransactionException e) { + + logger.warn("Events associated with transaction " + transaction.id() + " not generated due to transaction commit failure."); + + List enqueuedEvents = transaction.getEnqueuedEvents(); + for(ChampEvent event : enqueuedEvents) { + + logger.debug("Graph event " + event.toString() + " not published."); + } + throw e; + } + + // Now that the transaction has been successfully committed, we need + // to log the events that were produced within that transaction's + // context. + List enqueuedEvents = transaction.getEnqueuedEvents(); + for(ChampEvent event : enqueuedEvents) { + logEvent(event); + } + } + + @Override + public void rollbackTransaction(ChampTransaction transaction) throws ChampTransactionException { + + // Rollback the transaction. + transaction.rollback(); + } + + @Override + public ChampObject storeObject(ChampObject object) throws ChampMarshallingException, ChampSchemaViolationException, ChampObjectNotExistsException, ChampTransactionException { + return storeObject(object, Optional.empty()); + } + + @Override + public ChampObject storeObject(ChampObject object, Optional transaction) throws ChampMarshallingException, ChampSchemaViolationException, ChampObjectNotExistsException, ChampTransactionException { + + ChampObject storedObject = executeStoreObject(object, transaction); + + if(storedObject != null) { + + logOrEnqueueEvent(ChampEvent.builder() + .operation(ChampOperation.STORE) + .entity(storedObject) + .build(), + transaction); + } + + return storedObject; + } + + @Override + public ChampObject replaceObject(ChampObject object) + throws ChampMarshallingException, ChampSchemaViolationException, ChampObjectNotExistsException, ChampTransactionException { + + return replaceObject(object, Optional.empty()); + } + + @Override + public ChampObject replaceObject(ChampObject object, Optional transaction) + throws ChampMarshallingException, ChampSchemaViolationException, ChampObjectNotExistsException, ChampTransactionException { + + ChampObject replacedObject = executeReplaceObject(object, transaction); + + if(replacedObject != null) { + + logOrEnqueueEvent(ChampEvent.builder() + .operation(ChampOperation.REPLACE) + .entity(replacedObject) + .build(), + transaction); + } + + return replacedObject; + } + + @Override + public void deleteObject(Object key) throws ChampObjectNotExistsException, ChampTransactionException { + deleteObject(key, Optional.empty()); + } + + @Override + public void deleteObject(Object key, Optional transaction) throws ChampObjectNotExistsException, ChampTransactionException { + + // Retrieve the object that we are deleting before it's gone, so that we can + // report it to the event stream. + Optional objectToDelete = Optional.empty(); + try { + objectToDelete = retrieveObject(key, transaction); + + } catch (ChampUnmarshallingException e) { + logger.error("Unable to generate delete object log: " + e.getMessage()); + } + + executeDeleteObject(key, transaction); + + if(objectToDelete.isPresent()) { + // Update the event stream with the current operation. + logOrEnqueueEvent(ChampEvent.builder() + .operation(ChampOperation.DELETE) + .entity(objectToDelete.get()) + .build(), + transaction); + } + } + + @Override + public ChampRelationship storeRelationship(ChampRelationship relationship) + throws ChampUnmarshallingException, + ChampMarshallingException, + ChampObjectNotExistsException, + ChampSchemaViolationException, + ChampRelationshipNotExistsException, ChampTransactionException { + return storeRelationship(relationship, Optional.empty()); + } + + @Override + public ChampRelationship storeRelationship(ChampRelationship relationship, Optional transaction) + throws ChampUnmarshallingException, + ChampMarshallingException, + ChampObjectNotExistsException, + ChampSchemaViolationException, + ChampRelationshipNotExistsException, ChampTransactionException { + + ChampRelationship storedRelationship = executeStoreRelationship(relationship, transaction); + + if(storedRelationship != null) { + + // Update the event stream with the current operation. + logOrEnqueueEvent(ChampEvent.builder() + .operation(ChampOperation.STORE) + .entity(storedRelationship) + .build(), + transaction); + } + + return storedRelationship; + } + + @Override + public ChampRelationship replaceRelationship(ChampRelationship relationship) + throws ChampUnmarshallingException, + ChampMarshallingException, + ChampSchemaViolationException, + ChampRelationshipNotExistsException, ChampTransactionException { + return replaceRelationship(relationship, Optional.empty()); + } + + @Override + public ChampRelationship replaceRelationship(ChampRelationship relationship, Optional transaction) + throws ChampUnmarshallingException, + ChampMarshallingException, + ChampSchemaViolationException, + ChampRelationshipNotExistsException, ChampTransactionException { + + ChampRelationship replacedRelationship = executeReplaceRelationship(relationship, transaction); + + if(replacedRelationship != null) { + + // Update the event stream with the current operation. + logOrEnqueueEvent(ChampEvent.builder() + .operation(ChampOperation.REPLACE) + .entity(replacedRelationship) + .build(), + transaction); + } + + return replacedRelationship; + } + + @Override + public void deleteRelationship(ChampRelationship relationship) throws ChampRelationshipNotExistsException, ChampTransactionException { + deleteRelationship(relationship, Optional.empty()); + } + + @Override + public void deleteRelationship(ChampRelationship relationship, Optional transaction) throws ChampRelationshipNotExistsException, ChampTransactionException { + + executeDeleteRelationship(relationship, transaction); + + // Update the event stream with the current operation. + logOrEnqueueEvent(ChampEvent.builder() + .operation(ChampOperation.DELETE) + .entity(relationship) + .build(), + transaction); + } + + @Override + public ChampPartition storePartition(ChampPartition partition) throws ChampSchemaViolationException, ChampRelationshipNotExistsException, ChampMarshallingException, ChampObjectNotExistsException, ChampTransactionException { + return storePartition(partition, Optional.empty()); + } + + @Override + public ChampPartition storePartition(ChampPartition partition, Optional transaction) throws ChampSchemaViolationException, ChampRelationshipNotExistsException, ChampMarshallingException, ChampObjectNotExistsException, ChampTransactionException { + + ChampPartition storedPartition = executeStorePartition(partition, transaction); + + if(storedPartition != null) { + + // Update the event stream with the current operation. + logOrEnqueueEvent(ChampEvent.builder() + .operation(ChampOperation.STORE) + .entity(storedPartition) + .build(), + transaction); + } + + return storedPartition; + } + + @Override + public void deletePartition(ChampPartition graph) throws ChampTransactionException{ + deletePartition(graph, Optional.empty()); + } + + @Override + public void deletePartition(ChampPartition graph, Optional transaction) throws ChampTransactionException { + + executeDeletePartition(graph, transaction); + + // Update the event stream with the current operation. + logOrEnqueueEvent(ChampEvent.builder() + .operation(ChampOperation.DELETE) + .entity(graph) + .build(), + transaction); + } + + @Override + public void storeObjectIndex(ChampObjectIndex index) { + + executeStoreObjectIndex(index); + + // Update the event stream with the current operation. + logEvent(ChampEvent.builder() + .operation(ChampOperation.STORE) + .entity(index) + .build()); + } + + + public void deleteObjectIndex(String indexName) throws ChampIndexNotExistsException { + + // Retrieve the index that we are deleting before it's gone, so that we can + // report it to the event stream. + Optional indexToDelete = retrieveObjectIndex(indexName); + + executeDeleteObjectIndex(indexName); + + if(indexToDelete.isPresent()) { + // Update the event stream with the current operation. + logEvent(ChampEvent.builder() + .operation(ChampOperation.DELETE) + .entity(indexToDelete.get()) + .build()); + } + } + + + public void storeRelationshipIndex(ChampRelationshipIndex index) { + + executeStoreRelationshipIndex(index); + + // Update the event stream with the current operation. + logEvent(ChampEvent.builder() + .operation(ChampOperation.STORE) + .entity(index) + .build()); + } + + + public void deleteRelationshipIndex(String indexName) throws ChampIndexNotExistsException { + + // Retrieve the index that we are deleting before it's gone, so that we can + // report it to the event stream. + Optional indexToDelete = retrieveRelationshipIndex(indexName); + + executeDeleteRelationshipIndex(indexName); + + if(indexToDelete.isPresent()) { + // Update the event stream with the current operation. + logEvent(ChampEvent.builder() + .operation(ChampOperation.DELETE) + .entity(indexToDelete.get()) + .build()); + } + } + + private void logOrEnqueueEvent(ChampEvent event, Optional transaction) { + + if(!transaction.isPresent()) { + // Update the event stream with the current operation. + logEvent(event); + } else { + + // when the TransactionID is present, add it to the event payload before logging/enqueing the event. + event.setDbTransactionId ( transaction.get ().id () ); + transaction.get().logEvent(event); + } + } + + /** + * Submits an event to be published to the event stream. + * + * @param anEvent - The event to be published. + */ + public void logEvent(ChampEvent anEvent) { + + if(eventQueue == null) { + return; + } + + logger.info("Log champcore event with transaction id: " + anEvent.getTransactionId() + " to event bus"); + if(logger.isDebugEnabled()) { + logger.debug("Event payload: " + anEvent.toString()); + } + + // Try to submit the event to be published to the event bus. + if(!eventQueue.offer(anEvent)) { + logger.error("Event could not be published to the event bus due to: Internal buffer capacity exceeded."); + } + } + + + /** + * This class implements the worker threads for our thread pool which are responsible for + * pulling the next outgoing event from the internal buffer and forwarding them to the event + * bus client. + *

+ * Each publish operation is performed synchronously, so that the thread will only move on + * to the next available event once it has actually published the current event to the bus. + */ + private class EventPublisherWorker implements Runnable { + + /** Partition key to use when publishing events to the event stream. We WANT all events + * to go to a single partition, so we are just using a hard-coded key for every event. */ + private static final String EVENTS_PARTITION_KEY = "champEventKey"; + + + @Override + public void run() { + + while(true) { + + ChampEvent event = null; + try { + + // Get the next event to be published from the queue. + event = eventQueue.take(); + + } catch (InterruptedException e) { + + // Restore the interrupted status. + Thread.currentThread().interrupt(); + } + + // Try publishing the event to the event bus. This call will block + // until + try { + producer.sendSync(EVENTS_PARTITION_KEY, event.toJson()); + + } catch (Exception e) { + + logger.error("Failed to publish event to event bus: " + e.getMessage()); + } + } + } + } +} diff --git a/src/main/java/org/onap/aai/champ/event/ChampEvent.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/event/ChampEvent.java similarity index 81% rename from src/main/java/org/onap/aai/champ/event/ChampEvent.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/event/ChampEvent.java index 639a03e..46f1b61 100644 --- a/src/main/java/org/onap/aai/champ/event/ChampEvent.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/event/ChampEvent.java @@ -19,18 +19,19 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.event; +package org.onap.aai.champcore.event; import java.io.IOException; -import org.onap.aai.champ.model.ChampObject; -import org.onap.aai.champ.model.ChampObjectIndex; -import org.onap.aai.champ.model.ChampPartition; -import org.onap.aai.champ.model.ChampRelationship; -import org.onap.aai.champ.model.ChampRelationshipIndex; +import org.onap.aai.champcore.model.ChampObject; +import org.onap.aai.champcore.model.ChampObjectIndex; +import org.onap.aai.champcore.model.ChampPartition; +import org.onap.aai.champcore.model.ChampRelationship; +import org.onap.aai.champcore.model.ChampRelationshipIndex; import com.fasterxml.jackson.annotation.JsonInclude.Include; +import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonMappingException; @@ -49,11 +50,13 @@ public class ChampEvent { private ChampOperation operation; private long timestamp; + private String transactionId = null; private ChampObject vertex = null; private ChampRelationship relationship = null; private ChampPartition partition = null; private ChampObjectIndex objectIndex = null; private ChampRelationshipIndex relationshipIndex = null; + private String dbTransactionId = null; public static Builder builder() { @@ -76,6 +79,15 @@ public class ChampEvent { this.timestamp = timestamp; } + @JsonProperty("transaction-id") + public String getTransactionId() { + return transactionId; + } + + public void setTransactionId(String transactionId) { + this.transactionId = transactionId; + } + public ChampObject getVertex() { return vertex; } @@ -115,7 +127,15 @@ public class ChampEvent { public void setRelationshipIndex(ChampRelationshipIndex relationshipIndex) { this.relationshipIndex = relationshipIndex; } - + + @JsonProperty("database-transaction-id") + public String getDbTransactionId () { return dbTransactionId; } + + + public void setDbTransactionId ( String id ) { this.dbTransactionId = id; } + + + public String toJson() { ObjectMapper mapper = new ObjectMapper(); @@ -135,6 +155,7 @@ public class ChampEvent { } @Override public String toString() { + return toJson(); } @@ -176,10 +197,16 @@ public class ChampEvent { event.relationshipIndex = relationshipIndex; return this; } + public ChampEvent build() { event.setTimestamp(System.currentTimeMillis()); + + // Set a unique transaction id on this event that can be used by downstream entities + // for log correlation. + event.setTransactionId(java.util.UUID.randomUUID().toString()); + return event; } } diff --git a/src/main/java/org/onap/aai/champ/exceptions/ChampIndexNotExistsException.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/exceptions/ChampIndexNotExistsException.java similarity index 97% rename from src/main/java/org/onap/aai/champ/exceptions/ChampIndexNotExistsException.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/exceptions/ChampIndexNotExistsException.java index ae97ea6..e969ce5 100644 --- a/src/main/java/org/onap/aai/champ/exceptions/ChampIndexNotExistsException.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/exceptions/ChampIndexNotExistsException.java @@ -19,7 +19,7 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.exceptions; +package org.onap.aai.champcore.exceptions; public final class ChampIndexNotExistsException extends Exception { diff --git a/src/main/java/org/onap/aai/champ/exceptions/ChampMarshallingException.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/exceptions/ChampMarshallingException.java similarity index 97% rename from src/main/java/org/onap/aai/champ/exceptions/ChampMarshallingException.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/exceptions/ChampMarshallingException.java index 2880960..09ede7a 100644 --- a/src/main/java/org/onap/aai/champ/exceptions/ChampMarshallingException.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/exceptions/ChampMarshallingException.java @@ -19,7 +19,7 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.exceptions; +package org.onap.aai.champcore.exceptions; public final class ChampMarshallingException extends Exception { diff --git a/src/main/java/org/onap/aai/champ/exceptions/ChampObjectNotExistsException.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/exceptions/ChampObjectNotExistsException.java similarity index 97% rename from src/main/java/org/onap/aai/champ/exceptions/ChampObjectNotExistsException.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/exceptions/ChampObjectNotExistsException.java index 09db181..cd63401 100644 --- a/src/main/java/org/onap/aai/champ/exceptions/ChampObjectNotExistsException.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/exceptions/ChampObjectNotExistsException.java @@ -19,7 +19,7 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.exceptions; +package org.onap.aai.champcore.exceptions; public final class ChampObjectNotExistsException extends Exception { diff --git a/src/main/java/org/onap/aai/champ/exceptions/ChampRelationshipNotExistsException.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/exceptions/ChampRelationshipNotExistsException.java similarity index 97% rename from src/main/java/org/onap/aai/champ/exceptions/ChampRelationshipNotExistsException.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/exceptions/ChampRelationshipNotExistsException.java index 944ee04..4cdde58 100644 --- a/src/main/java/org/onap/aai/champ/exceptions/ChampRelationshipNotExistsException.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/exceptions/ChampRelationshipNotExistsException.java @@ -19,7 +19,7 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.exceptions; +package org.onap.aai.champcore.exceptions; public final class ChampRelationshipNotExistsException extends Exception { diff --git a/src/main/java/org/onap/aai/champ/exceptions/ChampSchemaViolationException.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/exceptions/ChampSchemaViolationException.java similarity index 97% rename from src/main/java/org/onap/aai/champ/exceptions/ChampSchemaViolationException.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/exceptions/ChampSchemaViolationException.java index 44df636..b234bc4 100644 --- a/src/main/java/org/onap/aai/champ/exceptions/ChampSchemaViolationException.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/exceptions/ChampSchemaViolationException.java @@ -19,7 +19,7 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.exceptions; +package org.onap.aai.champcore.exceptions; public final class ChampSchemaViolationException extends Exception { diff --git a/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/exceptions/ChampTransactionException.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/exceptions/ChampTransactionException.java new file mode 100644 index 0000000..17251b2 --- /dev/null +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/exceptions/ChampTransactionException.java @@ -0,0 +1,41 @@ +/** + * ============LICENSE_START========================================== + * org.onap.aai + * =================================================================== + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 Amdocs + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END============================================ + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.champcore.exceptions; + +public class ChampTransactionException extends Exception { + + private static final long serialVersionUID = -5492385992668214838L; + + public ChampTransactionException() {} + + public ChampTransactionException(String message) { + super(message); + } + + public ChampTransactionException(Throwable cause) { + super(cause); + } + + public ChampTransactionException(String message, Throwable cause) { + super(message, cause); + } +} \ No newline at end of file diff --git a/src/main/java/org/onap/aai/champ/exceptions/ChampUnmarshallingException.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/exceptions/ChampUnmarshallingException.java similarity index 97% rename from src/main/java/org/onap/aai/champ/exceptions/ChampUnmarshallingException.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/exceptions/ChampUnmarshallingException.java index f63d879..b8383d8 100644 --- a/src/main/java/org/onap/aai/champ/exceptions/ChampUnmarshallingException.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/exceptions/ChampUnmarshallingException.java @@ -19,7 +19,7 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.exceptions; +package org.onap.aai.champcore.exceptions; public final class ChampUnmarshallingException extends Exception { diff --git a/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/graph/impl/AbstractTinkerpopChampGraph.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/graph/impl/AbstractTinkerpopChampGraph.java new file mode 100644 index 0000000..9a45e91 --- /dev/null +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/graph/impl/AbstractTinkerpopChampGraph.java @@ -0,0 +1,1068 @@ +/** + * ============LICENSE_START========================================== + * org.onap.aai + * =================================================================== + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 Amdocs + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END============================================ + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.champcore.graph.impl; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.NoSuchElementException; +import java.util.Optional; +import java.util.Set; +import java.util.Spliterator; +import java.util.Spliterators; +import java.util.Vector; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.stream.Stream; +import java.util.stream.StreamSupport; + +import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal; +import org.apache.tinkerpop.gremlin.structure.Direction; +import org.apache.tinkerpop.gremlin.structure.Edge; +import org.apache.tinkerpop.gremlin.structure.Graph; +import org.apache.tinkerpop.gremlin.structure.Property; +import org.apache.tinkerpop.gremlin.structure.Vertex; +import org.apache.tinkerpop.gremlin.structure.VertexProperty; +import org.onap.aai.champcore.ChampTransaction; +import org.onap.aai.champcore.NoOpTinkerPopTransaction; +import org.onap.aai.champcore.exceptions.ChampMarshallingException; +import org.onap.aai.champcore.exceptions.ChampObjectNotExistsException; +import org.onap.aai.champcore.exceptions.ChampRelationshipNotExistsException; +import org.onap.aai.champcore.exceptions.ChampSchemaViolationException; +import org.onap.aai.champcore.exceptions.ChampTransactionException; +import org.onap.aai.champcore.exceptions.ChampUnmarshallingException; +import org.onap.aai.champcore.model.ChampObject; +import org.onap.aai.champcore.model.ChampPartition; +import org.onap.aai.champcore.model.ChampRelationship; +import org.onap.aai.champcore.model.ChampSchema; +import org.onap.aai.champcore.model.fluent.partition.CreateChampPartitionable; +import org.onap.aai.champcore.transform.TinkerpopChampformer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; + +public abstract class AbstractTinkerpopChampGraph extends AbstractValidatingChampGraph { + + private static final Logger LOGGER = LoggerFactory.getLogger(AbstractTinkerpopChampGraph.class); + private static final TinkerpopChampformer TINKERPOP_CHAMPFORMER = new TinkerpopChampformer(); + private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); + + private volatile AtomicBoolean isShutdown; + + protected AbstractTinkerpopChampGraph(Map properties) { + super(properties); + + isShutdown = new AtomicBoolean(false); + Runtime.getRuntime().addShutdownHook(shutdownHook); + } + + private static final TinkerpopChampformer getChampformer() { + return TINKERPOP_CHAMPFORMER; + } + + private static final ObjectMapper getObjectMapper() { + return OBJECT_MAPPER; + } + + public abstract GraphTraversal hasLabel(GraphTraversal query, Object type); + + public ChampTransaction openTransaction() { + + return new TinkerpopTransaction(getGraph()); + } + + private Vertex writeVertex(ChampObject object, ChampTransaction transaction) throws ChampObjectNotExistsException, ChampMarshallingException { + final Vertex vertex; + + Graph graphInstance = ((TinkerpopTransaction)transaction).getGraphInstance(); + + if (object.getKey().isPresent()) { + final Iterator vertexIter = graphInstance.vertices(object.getKey().get()); + + if (vertexIter.hasNext()) { + vertex = vertexIter.next(); + } else throw new ChampObjectNotExistsException(); + } else { + vertex = graphInstance.addVertex(object.getType()); + } + + for (Entry property : object.getProperties().entrySet()) { + + if (property.getValue() instanceof List) { + for (Object subPropertyValue : (List) property.getValue()) { + vertex.property(VertexProperty.Cardinality.list, property.getKey(), subPropertyValue); + } + } else if (property.getValue() instanceof Set) { + for (Object subPropertyValue : (Set) property.getValue()) { + vertex.property(VertexProperty.Cardinality.set, property.getKey(), subPropertyValue); + } + } else { + vertex.property(property.getKey(), property.getValue()); + } + } + + return vertex; + } + + private Vertex replaceVertex(ChampObject object, ChampTransaction transaction) throws ChampObjectNotExistsException, ChampMarshallingException { + Vertex vertex; + + Graph graphInstance = ((TinkerpopTransaction)transaction).getGraphInstance(); + + if (object.getKey().isPresent()) { + final Iterator vertexIter = graphInstance.vertices(object.getKey().get()); + + if (vertexIter.hasNext()) { + vertex = vertexIter.next(); + } else throw new ChampObjectNotExistsException(); + } else { + throw new ChampObjectNotExistsException(); + } + + //clear all the existing properties + Iterator> it = vertex.properties(); + while (it.hasNext()) { + it.next().remove(); + } + + for (Entry property : object.getProperties().entrySet()) { + + if (property.getValue() instanceof List) { + for (Object subPropertyValue : (List) property.getValue()) { + vertex.property(VertexProperty.Cardinality.list, property.getKey(), subPropertyValue); + } + } else if (property.getValue() instanceof Set) { + for (Object subPropertyValue : (Set) property.getValue()) { + vertex.property(VertexProperty.Cardinality.set, property.getKey(), subPropertyValue); + } + } else { + vertex.property(property.getKey(), property.getValue()); + } + } + + return vertex; + } + + private Edge writeEdge(ChampRelationship relationship, ChampTransaction transaction) throws ChampObjectNotExistsException, ChampRelationshipNotExistsException, ChampMarshallingException { + + final Vertex source = writeVertex(relationship.getSource(), transaction); + final Vertex target = writeVertex(relationship.getTarget(), transaction); + final Edge edge; + + Graph graphInstance = ((TinkerpopTransaction)transaction).getGraphInstance(); + + if (relationship.getKey().isPresent()) { + final Iterator edgeIter = graphInstance.edges(relationship.getKey().get()); + + if (edgeIter.hasNext()) { + edge = edgeIter.next(); + } else throw new ChampRelationshipNotExistsException(); + } else { + edge = source.addEdge(relationship.getType(), target); + } + + for (Entry property : relationship.getProperties().entrySet()) { + edge.property(property.getKey(), property.getValue()); + } + + return edge; + } + + private Edge replaceEdge(ChampRelationship relationship, ChampTransaction tx) throws ChampRelationshipNotExistsException, ChampMarshallingException { + final Edge edge; + Graph graphInstance = ((TinkerpopTransaction)tx).getGraphInstance(); + + if(!relationship.getSource().getKey().isPresent() || !relationship.getTarget().getKey().isPresent()){ + throw new IllegalArgumentException("Invalid source/target"); + } + + if (relationship.getKey().isPresent()) { + final Iterator edgeIter = graphInstance.edges(relationship.getKey().get()); + + + if (edgeIter.hasNext()) { + edge = edgeIter.next(); + //validate if the source/target are the same as before. Throw error if not the same + if (!edge.outVertex().id().equals(relationship.getSource().getKey().get()) + || !edge.inVertex().id().equals(relationship.getTarget().getKey().get())) { + throw new IllegalArgumentException("source/target can't be updated"); + } + + } else throw new ChampRelationshipNotExistsException(); + } else { + throw new ChampRelationshipNotExistsException(); + } + + // clear all the existing properties + Iterator> it = edge.properties(); + while (it.hasNext()) { + it.next().remove(); + } + + for (Entry property : relationship.getProperties().entrySet()) { + edge.property(property.getKey(), property.getValue()); + } + + return edge; + } + + + protected abstract Graph getGraph(); + + + + private Thread shutdownHook = new Thread() { + @Override + public void run() { + try { + shutdown(); + } catch (IllegalStateException e) { + //Suppress, because shutdown() has already been called + } + } + }; + + protected boolean isShutdown() { + return isShutdown.get(); + } + + @Override + public Stream queryObjects(Map queryParams) throws ChampTransactionException { + return queryObjects(queryParams, Optional.empty()); + } + + + @Override + public Stream queryObjects(Map queryParams, Optional transaction) throws ChampTransactionException { + + if (isShutdown()) { + throw new IllegalStateException("Cannot use ChampAPI after calling shutdown()"); + } + + // If we were not provided a transaction object then automatically open a transaction + // now. + final ChampTransaction tx = getOrCreateTransactionInstance(transaction); + + // Use the graph instance associated with our transaction. + Graph graphInstance = ((TinkerpopTransaction)tx).getGraphInstance(); + + //If they provided the object key, do this the quick way rather than creating a traversal + if (queryParams.containsKey(ChampObject.ReservedPropertyKeys.CHAMP_OBJECT_KEY.toString())) { + + try { + final Optional object = + retrieveObject(queryParams.get(ChampObject.ReservedPropertyKeys.CHAMP_OBJECT_KEY.toString()), + transaction); + + if (object.isPresent()) { + return Stream.of(object.get()); + } else { + return Stream.empty(); + } + } catch (ChampUnmarshallingException e) { + LOGGER.warn("Failed to unmarshall object", e); + return Stream.empty(); + } + } + + final GraphTraversal query = graphInstance.traversal().V(); + + for (Entry filter : queryParams.entrySet()) { + if (filter.getKey().equals(ChampObject.ReservedPropertyKeys.CHAMP_OBJECT_TYPE.toString())) { + continue; //For performance reasons, the label is the last thing to be added + } else { + query.has(filter.getKey(), filter.getValue()); + } + } + + if (queryParams.containsKey(ChampObject.ReservedPropertyKeys.CHAMP_OBJECT_TYPE.toString())) { + hasLabel(query, queryParams.get(ChampObject.ReservedPropertyKeys.CHAMP_OBJECT_TYPE.toString())); + } + + final Iterator objIter = new Iterator () { + + private ChampObject next; + + + @Override + public boolean hasNext() { + while (query.hasNext()) { + try { + next = getChampformer().unmarshallObject(query.next()); + return true; + } catch (ChampUnmarshallingException e) { + LOGGER.warn("Failed to unmarshall tinkerpop vertex during query, returning partial results", e); + } + } + + // If we auto-created the transaction, then commit it now, otherwise it is up to the + // caller to decide when and if to do the commit. + if(!transaction.isPresent()) { + try { + tx.commit(); //Danger ahead if this iterator is not completely consumed + //then the transaction cache will hold stale values + } catch (ChampTransactionException e) { + LOGGER.warn("Failed transaction commit due to: " + e.getMessage()); + } + + } + + next = null; + return false; + } + + @Override + public ChampObject next() { + if (next == null) { + throw new NoSuchElementException(); + } + + return next; + } + }; + + return StreamSupport.stream(Spliterators.spliteratorUnknownSize(objIter, + Spliterator.ORDERED | Spliterator.NONNULL), + false); + } + + @Override + public Optional retrieveObject(Object key) throws ChampUnmarshallingException, ChampTransactionException { + return retrieveObject(key, Optional.empty()); + } + + @Override + public Optional retrieveObject(Object key, Optional transaction) throws ChampUnmarshallingException, ChampTransactionException { + + if (isShutdown()) { + throw new IllegalStateException("Cannot use ChampAPI after calling shutdown()"); + } + + // If we were not provided a transaction object then automatically open a transaction + // now. + ChampTransaction tx = getOrCreateTransactionInstance(transaction); + + // Use the graph instance associated with our transaction. + Graph graphInstance = ((TinkerpopTransaction)tx).getGraphInstance(); + + final Iterator vertices = graphInstance.vertices(key); + final Optional optionalObject; + + if (!vertices.hasNext()) { + optionalObject = Optional.empty(); + + } else { + optionalObject = Optional.of(getChampformer().unmarshallObject(vertices.next())); + } + + // If we auto-created the transaction, then commit it now, otherwise it is up to the + // caller to decide when and if to do the commit. + if(!transaction.isPresent()) { + tx.commit(); + } + + return optionalObject; + } + + @Override + public Stream retrieveRelationships(ChampObject source) throws ChampUnmarshallingException, ChampObjectNotExistsException, ChampTransactionException { + return retrieveRelationships(source, Optional.empty()); + } + + @Override + public Stream retrieveRelationships(ChampObject source, Optional transaction) throws ChampUnmarshallingException, ChampObjectNotExistsException, ChampTransactionException { + + if (isShutdown()) { + throw new IllegalStateException("Cannot use ChampAPI after calling shutdown()"); + } + + // If we were not provided a transaction object then automatically open a transaction + // now. + final ChampTransaction tx = getOrCreateTransactionInstance(transaction); + + // Use the graph instance associated with our transaction. + Graph graphInstance = ((TinkerpopTransaction)tx).getGraphInstance(); + + final Vertex sourceVertex; + + try { + sourceVertex = graphInstance.vertices(source.getKey().get()).next(); + + } catch (NoSuchElementException e) { + + // If we auto-created the transaction, then try to roll it back now, otherwise it is + // up to the caller to decide when and if to do so. + if(!transaction.isPresent()) { + tx.rollback(); + } + + throw new ChampObjectNotExistsException(); + } + + final Iterator edges = sourceVertex.edges(Direction.BOTH); + final Iterator relIter = new Iterator () { + + private ChampRelationship next; + + @Override + public boolean hasNext() { + while (edges.hasNext()) { + try { + next = getChampformer().unmarshallRelationship(edges.next()); + return true; + } catch (ChampUnmarshallingException e) { + LOGGER.warn("Failed to unmarshall tinkerpop edge during query, returning partial results", e); + } + } + + // If we auto-created the transaction, then commit it now, otherwise it is up to the + // caller to decide when and if to do the commit. + if(!transaction.isPresent()) { + try { + tx.commit(); //Danger ahead if this iterator is not completely + //consumed, then the transaction cache will be stale + + } catch (ChampTransactionException e) { + LOGGER.warn("Failed transaction commit due to: " + e.getMessage()); + } + + } + next = null; + return false; + } + + @Override + public ChampRelationship next() { + if (next == null) { + throw new NoSuchElementException(); + } + + return next; + } + }; + + return StreamSupport.stream(Spliterators.spliteratorUnknownSize( + relIter, Spliterator.ORDERED | Spliterator.NONNULL), false); + } + + + @Override + public ChampObject doStoreObject(ChampObject object, Optional transaction) throws ChampMarshallingException, ChampObjectNotExistsException, ChampTransactionException { + + ChampTransaction tx = null; + + try { + + // If we were not provided a transaction object then automatically open a transaction + // now. + tx = getOrCreateTransactionInstance(transaction); + + // Now, store the object that we were supplied. + final Vertex vertex = writeVertex(object, tx); + + // Only auto-commit this operation if we were NOT provided a transaction context, + // otherwise it is the caller's responsibility to commit the transaction when it + // is appropriate to do so. + if(!transaction.isPresent()) { + tx.commit(); + } + + // Marshal the resulting vertex into a ChampObject and return it to the caller. + return ChampObject.create() + .from(object) + .withKey(vertex.id()) + .build(); + + } catch (ChampObjectNotExistsException e) { + + // Something went wrong. If we auto-created the transaction, then try to roll it back + // now. If we were supplied a transaction context then it is the caller's responsibility + // to decide whether or not to roll it back. + if(!transaction.isPresent()) { + tx.rollback(); + } + + // Rethrow the exception. + throw e; + } + } + + @Override + public ChampObject doReplaceObject(ChampObject object, Optional transaction) throws ChampMarshallingException, ChampObjectNotExistsException, ChampTransactionException { + + ChampTransaction tx = null; + + try { + + // If we were not provided a transaction object then automatically open a transaction + // now. + tx = getOrCreateTransactionInstance(transaction); + + final Vertex vertex = replaceVertex(object, tx); + + // Only auto-commit this operation if we were NOT provided a transaction context, + // otherwise it is the caller's responsibility to commit the transaction when it + // is appropriate to do so. + if(!transaction.isPresent()) { + tx.commit(); + } + + // Marshal the resulting vertex into a ChampObject and return it to the caller. + return ChampObject.create() + .from(object) + .withKey(vertex.id()) + .build(); + + } catch (ChampObjectNotExistsException e) { + + // Something went wrong. If we auto-created the transaction, then try to roll it back + // now. If we were supplied a transaction context then it is the caller's responsibility + // to decide whether or not to roll it back. + if(!transaction.isPresent()) { + tx.rollback(); + } + + // Rethrow the exception. + throw e; + } + } + + @Override + public void executeDeleteObject(Object key, Optional transaction) throws ChampObjectNotExistsException, ChampTransactionException { + + if (isShutdown()) { + throw new IllegalStateException("Cannot use ChampAPI after calling shutdown()"); + } + + // If we were not provided a transaction object then automatically open a transaction + // now. + ChampTransaction tx = getOrCreateTransactionInstance(transaction); + + // Use the graph instance associated with our transaction. + Graph graphInstance = ((TinkerpopTransaction)tx).getGraphInstance(); + + final Iterator vertex = graphInstance.vertices(key); + + if (!vertex.hasNext()) { + + // If we auto-created the transaction, then roll it back now, otherwise it + // is up to the caller to make that determination. + if(!transaction.isPresent()) { + tx.rollback(); + } + + throw new ChampObjectNotExistsException(); + } + + // Remove the vertex. + vertex.next().remove(); + + // If we auto-created the transaction, then commit it now, otherwise it + // is up to the caller to decide if and when to commit. + if(!transaction.isPresent()) { + tx.commit(); + } + } + + @Override + public ChampRelationship doStoreRelationship(ChampRelationship relationship, Optional transaction) + throws ChampUnmarshallingException, + ChampObjectNotExistsException, + ChampRelationshipNotExistsException, + ChampMarshallingException, + ChampTransactionException { + + // If we were not provided a transaction object then automatically open a transaction + // now. + ChampTransaction tx = getOrCreateTransactionInstance(transaction); + + try { + + // Store the edge in the graph. + final Edge edge = writeEdge(relationship, tx); + + // Unmarshal the stored edge into a ChampRelationship object + ChampRelationship storedRelationship = getChampformer().unmarshallRelationship(edge); + + // If we auto-created the transaction, then commit it now, otherwise it + // is up to the caller to decide if and when to commit. + if(!transaction.isPresent()) { + tx.commit(); + } + + // Finally, return the result to the caller. + return storedRelationship; + + } catch (ChampObjectNotExistsException | + ChampRelationshipNotExistsException | + ChampUnmarshallingException | + ChampMarshallingException e) { + + // If we auto-create the transaction, then try to roll it back, otherwise + // it is up to the caller to decide when and if to do so. + if(!transaction.isPresent()) { + tx.rollback(); + } + throw e; + } + } + + + @Override + public ChampRelationship doReplaceRelationship(ChampRelationship relationship, Optional transaction) + throws ChampUnmarshallingException, + ChampRelationshipNotExistsException, + ChampMarshallingException, + ChampTransactionException { + + // If we were not provided a transaction object then automatically open a transaction + // now. + ChampTransaction tx = getOrCreateTransactionInstance(transaction); + + try { + final Edge edge = replaceEdge(relationship, tx); + + ChampRelationship unmarshalledRelationship = getChampformer().unmarshallRelationship(edge); + + // If we auto-created the transaction, then commit it now, otherwise it + // is up to the caller to decide if and when to commit. + if(!transaction.isPresent()) { + tx.commit(); + } + + return unmarshalledRelationship; + + } catch ( ChampRelationshipNotExistsException | ChampUnmarshallingException | ChampMarshallingException e) { + + // it is up to the caller to decide when and if to do so. + if(!transaction.isPresent()) { + tx.rollback(); + } + + throw e; + } + } + + @Override + public Stream queryRelationships(Map queryParams) throws ChampTransactionException { + return queryRelationships(queryParams, Optional.empty()); + } + + @Override + public Stream queryRelationships(Map queryParams, Optional transaction) throws ChampTransactionException { + + if (isShutdown()) { + throw new IllegalStateException("Cannot use ChampAPI after calling shutdown()"); + } + + // If we were not provided a transaction object then automatically open a transaction + // now. + final ChampTransaction tx = getOrCreateTransactionInstance(transaction); + + // Use the graph instance associated with our transaction. + Graph graphInstance = ((TinkerpopTransaction)tx).getGraphInstance(); + + // If they provided the relationship key, do this the quick way rather than creating a traversal + if (queryParams.containsKey(ChampRelationship.ReservedPropertyKeys.CHAMP_RELATIONSHIP_KEY.toString())) { + try { + final Optional relationship = retrieveRelationship(queryParams.get(ChampRelationship.ReservedPropertyKeys.CHAMP_RELATIONSHIP_KEY.toString()), + Optional.of(tx)); + + if (relationship.isPresent()) { + return Stream.of(relationship.get()); + + } else { + return Stream.empty(); + } + } catch (ChampUnmarshallingException e) { + + LOGGER.warn("Failed to unmarshall relationship", e); + return Stream.empty(); + } + } + + final GraphTraversal query = graphInstance.traversal().E(); + + for (Entry filter : queryParams.entrySet()) { + if (filter.getKey().equals(ChampRelationship.ReservedPropertyKeys.CHAMP_RELATIONSHIP_TYPE.toString())) { + continue; //Add the label last for performance reasons + } else { + query.has(filter.getKey(), filter.getValue()); + } + } + + if (queryParams.containsKey(ChampRelationship.ReservedPropertyKeys.CHAMP_RELATIONSHIP_TYPE.toString())) { + hasLabel(query, queryParams.get(ChampRelationship.ReservedPropertyKeys.CHAMP_RELATIONSHIP_TYPE.toString())); + } + + final Iterator objIter = new Iterator () { + + private ChampRelationship next; + + @Override + public boolean hasNext() { + while (query.hasNext()) { + try { + next = getChampformer().unmarshallRelationship(query.next()); + return true; + } catch (ChampUnmarshallingException e) { + LOGGER.warn("Failed to unmarshall tinkerpop vertex during query, returning partial results", e); + } + } + + // If we auto-created the transaction, then commit it now, otherwise it + // is up to the caller to decide if and when to commit. + if(!transaction.isPresent()) { + try { + tx.commit(); //Danger ahead if this iterator is not completely + //consumed, then the transaction cache will be stale + + } catch (ChampTransactionException e) { + LOGGER.warn("Failed transaction commit due to " + e.getMessage()); + } + + } + + next = null; + return false; + } + + @Override + public ChampRelationship next() { + if (next == null) { + throw new NoSuchElementException(); + } + + return next; + } + }; + + return StreamSupport.stream(Spliterators.spliteratorUnknownSize( + objIter, Spliterator.ORDERED | Spliterator.NONNULL), false); + } + + @Override + public Optional retrieveRelationship(Object key) + throws ChampUnmarshallingException, ChampTransactionException { + return retrieveRelationship(key, Optional.empty()); + } + + @Override + public Optional retrieveRelationship(Object key, Optional transaction) + throws ChampUnmarshallingException, ChampTransactionException { + + if (isShutdown()) { + throw new IllegalStateException("Cannot use ChampAPI after calling shutdown()"); + } + + // If we were not provided a transaction object then automatically open a transaction + // now. + ChampTransaction tx = getOrCreateTransactionInstance(transaction); + + // Use the graph instance associated with our transaction. + Graph graphInstance = ((TinkerpopTransaction)tx).getGraphInstance(); + + final Iterator edge = graphInstance.edges(key); + final Optional optionalRelationship; + + if (!edge.hasNext()) { + optionalRelationship = Optional.empty(); + } else { + optionalRelationship = Optional.of(getChampformer().unmarshallRelationship(edge.next())); + } + + // If we auto-created the transaction, then commit it now, otherwise it + // is up to the caller to decide if and when to commit. + if(!transaction.isPresent()) { + tx.commit(); + } + + return optionalRelationship; + } + + @Override + public void executeDeleteRelationship(ChampRelationship relationship, Optional transaction) throws ChampRelationshipNotExistsException, ChampTransactionException { + + if (isShutdown()) { + throw new IllegalStateException("Cannot use ChampAPI after calling shutdown()"); + } + + if (!relationship.getKey().isPresent()) { + throw new IllegalArgumentException("Key must be provided when deleting a relationship"); + } + + // If we were not provided a transaction object then automatically open a transaction + // now. + ChampTransaction tx = getOrCreateTransactionInstance(transaction); + + // Use the graph instance associated with our transaction. + Graph graphInstance = ((TinkerpopTransaction)tx).getGraphInstance(); + + final Iterator edge = graphInstance.edges(relationship.getKey().get()); + + if (!edge.hasNext()) { + + // If we auto-created the transaction, then try to roll it back now, otherwise it + // is up to the caller to decide if and when to do so. + if(!transaction.isPresent()) { + tx.rollback(); + } + + throw new ChampRelationshipNotExistsException(); + } + + edge.next().remove(); + + // If we auto-created the transaction, then commit it now, otherwise it + // is up to the caller to decide if and when to commit. + if(!transaction.isPresent()) { + tx.commit(); + } + } + + + @Override + public ChampPartition doStorePartition(ChampPartition submittedPartition, Optional transaction) throws ChampMarshallingException, ChampObjectNotExistsException, ChampRelationshipNotExistsException, ChampTransactionException { + + if (isShutdown()) { + throw new IllegalStateException("Cannot use ChampAPI after calling shutdown()"); + } + + // If we were not provided a transaction object then automatically open a transaction + // now. + ChampTransaction tx = getOrCreateTransactionInstance(transaction); + + try { + final HashMap objectsWithKeys = new HashMap (); + final CreateChampPartitionable storedPartition = ChampPartition.create(); + + for (ChampObject champObject : submittedPartition.getChampObjects()) { + final Vertex vertex = writeVertex(champObject, tx); + objectsWithKeys.put(champObject, ChampObject.create() + .from(champObject) + .withKey(vertex.id()) + .build()); + } + + for (ChampRelationship champRelationship : submittedPartition.getChampRelationships()) { + + if (!objectsWithKeys.containsKey(champRelationship.getSource())) { + final Vertex vertex = writeVertex(champRelationship.getSource(), tx); + + objectsWithKeys.put(champRelationship.getSource(), ChampObject.create() + .from(champRelationship.getSource()) + .withKey(vertex.id()) + .build()); + } + + if (!objectsWithKeys.containsKey(champRelationship.getTarget())) { + final Vertex vertex = writeVertex(champRelationship.getTarget(), tx); + + objectsWithKeys.put(champRelationship.getTarget(), ChampObject.create() + .from(champRelationship.getTarget()) + .withKey(vertex.id()) + .build()); + } + + final ChampRelationship.Builder relWithKeysBuilder = new ChampRelationship.Builder(objectsWithKeys.get(champRelationship.getSource()), + objectsWithKeys.get(champRelationship.getTarget()), + champRelationship.getType()); + + if (champRelationship.getKey().isPresent()) { + relWithKeysBuilder.key(champRelationship.getKey().get()); + } + + relWithKeysBuilder.properties(champRelationship.getProperties()); + + final Edge edge = writeEdge(relWithKeysBuilder.build(), tx); + + storedPartition.withRelationship(ChampRelationship.create() + .from(champRelationship) + .withKey(edge.id()) + .build()); + } + + for (ChampObject object : objectsWithKeys.values()) { + storedPartition.withObject(object); + } + + // If we auto-created the transaction, then commit it now, otherwise it + // is up to the caller to decide if and when to commit. + if(!transaction.isPresent()) { + tx.commit(); + } + + return storedPartition.build(); + + } catch (ChampObjectNotExistsException | ChampMarshallingException e) { + + // If we auto-created the transaction, then try to roll it back now, otherwise it + // is up to the caller to decide if and when to do so. + if(!transaction.isPresent()) { + tx.rollback(); + } + + throw e; + } + } + + @Override + public void executeDeletePartition(ChampPartition graph, Optional transaction) throws ChampTransactionException { + + if (isShutdown()) { + throw new IllegalStateException("Cannot use ChampAPI after calling shutdown()"); + } + + // If we were not provided a transaction object then automatically open a transaction + // now. + ChampTransaction tx = getOrCreateTransactionInstance(transaction); + + // Use the graph instance associated with our transaction. + Graph graphInstance = ((TinkerpopTransaction)tx).getGraphInstance(); + + for (ChampObject champObject : graph.getChampObjects()) { + try { + final Object vertexId = champObject.getKey().get(); + final Iterator vertex = graphInstance.vertices(vertexId); + + if (vertex.hasNext()) { + vertex.next().remove(); + } + } catch (NoSuchElementException e) { + + // If we auto-created the transaction, then try to roll it back now, otherwise it + // is up to the caller to decide if and when to do so. + if(!transaction.isPresent()) { + tx.rollback(); + } + + throw new IllegalArgumentException("Must pass a key to delete an object"); + } + } + + for (ChampRelationship champRelationship : graph.getChampRelationships()) { + try { + final Iterator edge = graphInstance.edges(champRelationship.getKey().get()); + + if (edge.hasNext()) { + edge.next().remove(); + } + } catch (NoSuchElementException e) { + + // If we auto-created the transaction, then try to roll it back now, otherwise it + // is up to the caller to decide if and when to do so. + if(!transaction.isPresent()) { + tx.rollback(); + } + + throw new IllegalArgumentException("Must pass a key to delete a relationship"); + } + } + + // If we auto-created the transaction, then commit it now, otherwise it + // is up to the caller to decide if and when to commit. + if(!transaction.isPresent()) { + tx.commit(); + } + } + + @Override + public void shutdown() { + + if (isShutdown.compareAndSet(false, true)) { + super.shutdown(); + try { + getGraph().close(); + } catch (Throwable t) { + LOGGER.error("Exception while shutting down graph", t); + } + } else { + throw new IllegalStateException("Cannot call shutdown() after shutdown() was already initiated"); + } + } + + @Override + public void storeSchema(ChampSchema schema) throws ChampSchemaViolationException { + if (isShutdown()) throw new IllegalStateException("Cannot call storeSchema() after shutdown has been initiated"); + + if (getGraph().features().graph().variables().supportsVariables()) { + try { + getGraph().variables().set("schema", getObjectMapper().writeValueAsBytes(schema)); + } catch (JsonProcessingException e) { + throw new RuntimeException(e); + } + } else { + super.storeSchema(schema); + } + } + + @Override + public ChampSchema retrieveSchema() { + if (isShutdown()) throw new IllegalStateException("Cannot call retrieveSchema() after shutdown has been initiated"); + + if (getGraph().features().graph().variables().supportsVariables()) { + final Optional schema = getGraph().variables().get("schema"); + + if (schema.isPresent()) { + try { + return getObjectMapper().readValue(schema.get(), ChampSchema.class); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + } + + return super.retrieveSchema(); + } + + @Override + public void deleteSchema() { + if (isShutdown()) throw new IllegalStateException("Cannot call deleteSchema() after shutdown has been initiated"); + + if (getGraph().features().graph().variables().supportsVariables()) { + getGraph().variables().remove("schema"); + } else { + super.deleteSchema(); + } + } + + public ChampTransaction getOrCreateTransactionInstance(Optional transaction) { + + ChampTransaction tx = null; + + // If we were not provided a transaction object then automatically open a transaction + // now. + if(!transaction.isPresent()) { + + tx = new TinkerpopTransaction(getGraph()); + + } else { + tx = transaction.get(); + } + + return tx; + } +} diff --git a/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/graph/impl/AbstractValidatingChampGraph.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/graph/impl/AbstractValidatingChampGraph.java new file mode 100644 index 0000000..4568bc3 --- /dev/null +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/graph/impl/AbstractValidatingChampGraph.java @@ -0,0 +1,293 @@ +/** + * ============LICENSE_START========================================== + * org.onap.aai + * =================================================================== + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 Amdocs + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END============================================ + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.champcore.graph.impl; + +import java.util.Map; +import java.util.Optional; + +import org.onap.aai.champcore.ChampTransaction; +import org.onap.aai.champcore.event.AbstractLoggingChampGraph; +import org.onap.aai.champcore.exceptions.ChampMarshallingException; +import org.onap.aai.champcore.exceptions.ChampObjectNotExistsException; +import org.onap.aai.champcore.exceptions.ChampRelationshipNotExistsException; +import org.onap.aai.champcore.exceptions.ChampSchemaViolationException; +import org.onap.aai.champcore.exceptions.ChampTransactionException; +import org.onap.aai.champcore.exceptions.ChampUnmarshallingException; +import org.onap.aai.champcore.model.ChampObject; +import org.onap.aai.champcore.model.ChampObjectConstraint; +import org.onap.aai.champcore.model.ChampPartition; +import org.onap.aai.champcore.model.ChampRelationship; +import org.onap.aai.champcore.model.ChampRelationshipConstraint; +import org.onap.aai.champcore.model.ChampSchema; +import org.onap.aai.champcore.schema.ChampSchemaEnforcer; + +public abstract class AbstractValidatingChampGraph extends AbstractLoggingChampGraph { + + private ChampSchema schema = ChampSchema.emptySchema(); + + protected abstract ChampSchemaEnforcer getSchemaEnforcer(); + protected abstract boolean isShutdown(); + + /** + * Updates an existing vertex in the graph data store. + *

+ * If a transaction context is not provided, then a transaction will be automatically + * created and committed for this operation only, otherwise, the supplied transaction + * will be used and it will be up to the caller to commit the transaction at its + * discretion. + *

+ * + * @param object - The vertex to be updated in the graph data store. + * @param transaction - Optional transaction context to perform the operation in. + * + * @return - The updated vertex, marshaled as a {@link ChampObject} + * + * @throws ChampMarshallingException - If the {@code relationship} is not able to be + * marshalled into the backend representation + * @throws ChampObjectNotExistsException - If {@link org.onap.aai.champcore.model.ChampObject#getKey} + * is not present or object not found in the graph + */ + protected abstract ChampObject doReplaceObject(ChampObject object, Optional transaction) throws ChampMarshallingException, ChampObjectNotExistsException, ChampTransactionException, ChampTransactionException; + + /** + * Creates or updates a vertex in the graph data store. + *

+ * If a transaction context is not provided, then a transaction will be automatically + * created and committed for this operation only, otherwise, the supplied transaction + * will be used and it will be up to the caller to commit the transaction at its + * discretion. + * + * @param object - The vertex to be stored in the graph data store. + * @param transaction - Optional transaction context to perform the operation in. + * + * @return - The vertex which was created, marshaled as a {@link ChampObject} + * + * @throws ChampMarshallingException - If the {@code relationship} is not able to be + * marshaled into the back end representation + * @throws ChampObjectNotExistsException - If {@link org.onap.aai.champcore.model.ChampObject#getKey} + * is not present or object not found in the graph + */ + protected abstract ChampObject doStoreObject(ChampObject object, Optional transaction) throws ChampMarshallingException, ChampObjectNotExistsException, ChampTransactionException; + + /** + * Replaces an edge in the graph data store. + *

+ * If a transaction context is not provided, then a transaction will be automatically + * created and committed for this operation only, otherwise, the supplied transaction + * will be used and it will be up to the caller to commit the transaction at its + * discretion. + * + * @param relationship - The edge to be replaced in the graph data store. + * @param transaction - Optional transaction context to perform the operation in. + * + * @return - The edge as it was replaced, marshaled as a {@link ChampRelationship} + * + * @throws ChampUnmarshallingException - If the edge which was created could not be + * unmarshaled into a ChampObject + * @throws ChampRelationshipNotExistsException - If {@link org.onap.aai.champcore.model.ChampRelationship#getKey}.isPresent() + * but the object cannot be found in the graph + * @throws ChampMarshallingException - If the {@code relationship} is not able to be + * marshaled into the back end representation + */ + protected abstract ChampRelationship doReplaceRelationship(ChampRelationship relationship, Optional transaction) throws ChampUnmarshallingException, ChampRelationshipNotExistsException, ChampMarshallingException, ChampTransactionException; + + /** + * Creates or updates a relationship in the graph data store. + *

+ * If a transaction context is not provided, then a transaction will be automatically + * created and committed for this operation only, otherwise, the supplied transaction + * will be used and it will be up to the caller to commit the transaction at its + * discretion. + * + * @param relationship - The relationship to be stored in the graph data store. + * @param transaction - Optional transaction context to perform the operation in. + * + * @return - The relationship that was stored. + * + * @throws ChampUnmarshallingException - If the edge which was created could not be + * unmarshalled into a ChampObject + * @throws ChampObjectNotExistsException - If {@link org.onap.aai.champcore.model.ChampObject#getKey} + * is not present or object not found in the graph + * @throws ChampRelationshipNotExistsException - If {@link org.onap.aai.champcore.model.ChampRelationship#getKey}.isPresent() + * but the object cannot be found in the graph + * @throws ChampMarshallingException - If the {@code relationship} is not able to be + * marshalled into the backend representation + */ + protected abstract ChampRelationship doStoreRelationship(ChampRelationship relationship, Optional transaction) throws ChampUnmarshallingException, ChampObjectNotExistsException, ChampRelationshipNotExistsException, ChampMarshallingException, ChampTransactionException; + + /** + * Creates or updates a partition in the graph data store. + * + * @param partition - The partition to be stored in the graph data store. + * @param transaction - Optional transaction context to perform the operation in. + * + * @return - The partition that was stored. + * + * @throws ChampRelationshipNotExistsException - If {@link org.onap.aai.champcore.model.ChampRelationship#getKey}.isPresent() + * but the object cannot be found in the graph + * @throws ChampMarshallingException - If the {@code relationship} is not able to be + * marshalled into the backend representation + * @throws ChampObjectNotExistsException - If {@link org.onap.aai.champcore.model.ChampObject#getKey} + * is not present or object not found in the graph + */ + protected abstract ChampPartition doStorePartition(ChampPartition partition, Optional transaction) throws ChampRelationshipNotExistsException, ChampMarshallingException, ChampObjectNotExistsException, ChampTransactionException; + + protected AbstractValidatingChampGraph(Map properties) { + super(properties); + } + + @Override + public ChampObject executeStoreObject(ChampObject object, Optional transaction) + throws ChampMarshallingException, ChampSchemaViolationException, ChampObjectNotExistsException, ChampTransactionException { + + if (isShutdown()) { + throw new IllegalStateException("Cannot use ChampAPI after calling shutdown()"); + } + + validate(object); + + return doStoreObject(object, transaction); + } + + + @Override + public ChampObject executeReplaceObject(ChampObject object, Optional transaction) + throws ChampMarshallingException, ChampSchemaViolationException, ChampObjectNotExistsException, ChampTransactionException { + + if (isShutdown()) { + throw new IllegalStateException("Cannot use ChampAPI after calling shutdown()"); + } + + validate(object); + + return doReplaceObject(object, transaction); + } + + @Override + public ChampRelationship executeStoreRelationship(ChampRelationship relationship, Optional transaction) + throws ChampUnmarshallingException, ChampMarshallingException, ChampObjectNotExistsException, ChampSchemaViolationException, ChampRelationshipNotExistsException, ChampTransactionException { + + if (isShutdown()) { + throw new IllegalStateException("Cannot use ChampAPI after calling shutdown()"); + } + + validate(relationship); + + return doStoreRelationship(relationship, transaction); + } + + @Override + public ChampRelationship executeReplaceRelationship(ChampRelationship relationship, Optional transaction) + throws ChampUnmarshallingException, ChampMarshallingException, ChampSchemaViolationException, ChampRelationshipNotExistsException, ChampTransactionException { + + if (isShutdown()) { + throw new IllegalStateException("Cannot use ChampAPI after calling shutdown()"); + } + + validate(relationship); + + return doReplaceRelationship(relationship, transaction); + } + + @Override + public ChampPartition executeStorePartition(ChampPartition partition, Optional transaction) throws ChampSchemaViolationException, ChampRelationshipNotExistsException, ChampMarshallingException, ChampObjectNotExistsException, ChampTransactionException { + + if (isShutdown()) { + throw new IllegalStateException("Cannot use ChampAPI after calling shutdown()"); + } + + validate(partition); + + return doStorePartition(partition, transaction); + } + + protected void validate(ChampObject object) throws ChampSchemaViolationException { + final Optional objectConstraint = retrieveSchema().getObjectConstraint(object.getType()); + + if (objectConstraint.isPresent()) getSchemaEnforcer().validate(object, objectConstraint.get()); + } + + protected void validate(ChampRelationship relationship) throws ChampSchemaViolationException { + final ChampSchema graphSchema = retrieveSchema(); + final Optional relationshipConstraint = graphSchema.getRelationshipConstraint(relationship.getType()); + final Optional sourceObjConstraint = graphSchema.getObjectConstraint(relationship.getSource().getType()); + final Optional targetObjConstraint = graphSchema.getObjectConstraint(relationship.getTarget().getType()); + + if (relationshipConstraint.isPresent()) getSchemaEnforcer().validate(relationship, relationshipConstraint.get()); + if (sourceObjConstraint.isPresent()) getSchemaEnforcer().validate(relationship.getSource(), sourceObjConstraint.get()); + if (targetObjConstraint.isPresent()) getSchemaEnforcer().validate(relationship.getTarget(), targetObjConstraint.get()); + } + + protected void validate(ChampPartition partition) throws ChampSchemaViolationException { + for (ChampObject object : partition.getChampObjects()) { + validate(object); + } + + for (ChampRelationship relationship : partition.getChampRelationships()) { + validate(relationship); + } + } + + @Override + public void storeSchema(ChampSchema schema) throws ChampSchemaViolationException { + if (isShutdown()) throw new IllegalStateException("Cannot call storeSchema() after shutdown has been initiated"); + + this.schema = schema; + } + + @Override + public ChampSchema retrieveSchema() { + if (isShutdown()) throw new IllegalStateException("Cannot call retrieveSchema() after shutdown has been initiated"); + + return schema; + } + + @Override + public void updateSchema(ChampObjectConstraint objectConstraint) throws ChampSchemaViolationException { + if (isShutdown()) throw new IllegalStateException("Cannot call updateSchema() after shutdown has been initiated"); + + final ChampSchema currentSchema = retrieveSchema(); + final ChampSchema updatedSchema = new ChampSchema.Builder(currentSchema) + .constraint(objectConstraint) + .build(); + + storeSchema(updatedSchema); + } + + @Override + public void updateSchema(ChampRelationshipConstraint relationshipConstraint) throws ChampSchemaViolationException { + if (isShutdown()) throw new IllegalStateException("Cannot call updateSchema() after shutdown has been initiated"); + + final ChampSchema currentSchema = retrieveSchema(); + final ChampSchema updatedSchema = new ChampSchema.Builder(currentSchema) + .constraint(relationshipConstraint) + .build(); + + storeSchema(updatedSchema); + } + + @Override + public void deleteSchema() { + if (isShutdown()) throw new IllegalStateException("Cannot call deleteSchema() after shutdown has been initiated"); + this.schema = ChampSchema.emptySchema(); + } +} diff --git a/src/main/java/org/onap/aai/champ/graph/impl/ChampAPIImpl.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/graph/impl/ChampAPIImpl.java similarity index 76% rename from src/main/java/org/onap/aai/champ/graph/impl/ChampAPIImpl.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/graph/impl/ChampAPIImpl.java index ed06429..607ba78 100644 --- a/src/main/java/org/onap/aai/champ/graph/impl/ChampAPIImpl.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/graph/impl/ChampAPIImpl.java @@ -19,14 +19,14 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.graph.impl; +package org.onap.aai.champcore.graph.impl; import java.util.Map.Entry; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicBoolean; -import org.onap.aai.champ.ChampAPI; -import org.onap.aai.champ.ChampGraph; +import org.onap.aai.champcore.ChampAPI; +import org.onap.aai.champcore.ChampGraph; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -35,32 +35,33 @@ public class ChampAPIImpl implements ChampAPI { private static final Logger LOGGER = LoggerFactory.getLogger(ChampAPIImpl.class); private final AtomicBoolean shutdown; - private final ChampGraph.Type type; + private final String type; private final ConcurrentHashMap graphs; - public ChampAPIImpl(ChampGraph.Type type) { + public ChampAPIImpl(String type) { this.type = type; this.graphs = new ConcurrentHashMap (); this.shutdown = new AtomicBoolean(false); } private ConcurrentHashMap getGraphs() { - return graphs; + return graphs; } @Override public ChampGraph getGraph(String graphName) { - if (shutdown.get()) throw new IllegalStateException("Cannot call getGraph() after shutdown() has been initiated"); + if (shutdown.get()) { + throw new IllegalStateException("Cannot call getGraph() after shutdown() has been initiated"); + } - if (getGraphs().containsKey(graphName)) return getGraphs().get(graphName); + if (getGraphs().containsKey(graphName)) { + return getGraphs().get(graphName); + } - final ChampGraph graph = ChampGraph.Factory.newInstance(type, graphName); - - final ChampGraph existingGraph = getGraphs().putIfAbsent(graphName, graph); - - if (existingGraph == null) return graph; - - return existingGraph; + // At this point, we know a graph with this name doesn't exist. Create and return it. + final ChampGraph graph = new InMemoryChampGraphImpl.Builder().build(); + graphs.put(graphName, graph); + return graph; } @Override @@ -80,7 +81,7 @@ public class ChampAPIImpl implements ChampAPI { } @Override - public ChampGraph.Type getType() { + public String getType() { return type; } diff --git a/src/main/java/org/onap/aai/champ/graph/impl/InMemoryChampGraphImpl.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/graph/impl/InMemoryChampGraphImpl.java similarity index 81% rename from src/main/java/org/onap/aai/champ/graph/impl/InMemoryChampGraphImpl.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/graph/impl/InMemoryChampGraphImpl.java index 7afb813..5773505 100644 --- a/src/main/java/org/onap/aai/champ/graph/impl/InMemoryChampGraphImpl.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/graph/impl/InMemoryChampGraphImpl.java @@ -19,28 +19,28 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.graph.impl; +package org.onap.aai.champcore.graph.impl; -import java.io.IOException; -import java.util.Collection; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Stream; +import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal; import org.apache.tinkerpop.gremlin.structure.Edge; import org.apache.tinkerpop.gremlin.structure.Vertex; import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraph; -import org.onap.aai.champ.ChampCapabilities; -import org.onap.aai.champ.exceptions.ChampIndexNotExistsException; -import org.onap.aai.champ.model.ChampObjectIndex; -import org.onap.aai.champ.model.ChampRelationshipIndex; -import org.onap.aai.champ.schema.ChampSchemaEnforcer; -import org.onap.aai.champ.schema.DefaultChampSchemaEnforcer; -import org.slf4j.Logger; - -import com.att.nsa.cambria.client.CambriaPublisher; +import org.onap.aai.champcore.ChampCapabilities; +import org.onap.aai.champcore.ChampTransaction; +import org.onap.aai.champcore.NoOpTinkerPopTransaction; +import org.onap.aai.champcore.exceptions.ChampIndexNotExistsException; +import org.onap.aai.champcore.model.ChampObject; +import org.onap.aai.champcore.model.ChampObjectIndex; +import org.onap.aai.champcore.model.ChampRelationshipIndex; +import org.onap.aai.champcore.schema.ChampSchemaEnforcer; +import org.onap.aai.champcore.schema.DefaultChampSchemaEnforcer; public final class InMemoryChampGraphImpl extends AbstractTinkerpopChampGraph { @@ -73,6 +73,13 @@ public final class InMemoryChampGraphImpl extends AbstractTinkerpopChampGraph { this.schemaEnforcer = builder.schemaEnforcer; } + @Override + public ChampTransaction getOrCreateTransactionInstance(Optional transaction) { + + return new NoOpTinkerPopTransaction(getGraph()); + + } + public static class Builder { private final Map graphConfiguration = new HashMap (); private ChampSchemaEnforcer schemaEnforcer = new DefaultChampSchemaEnforcer(); @@ -84,6 +91,18 @@ public final class InMemoryChampGraphImpl extends AbstractTinkerpopChampGraph { return this; } + public Builder properties(Map properties) { + + this.graphConfiguration.putAll(properties); + return this; + } + + public Builder property(String path, Object value) { + + graphConfiguration.put(path, value); + return this; + } + public InMemoryChampGraphImpl build() { return new InMemoryChampGraphImpl(this); } @@ -98,6 +117,7 @@ public final class InMemoryChampGraphImpl extends AbstractTinkerpopChampGraph { return graph; } + private ConcurrentHashMap getObjectIndices() { return objectIndices; } @@ -106,7 +126,9 @@ public final class InMemoryChampGraphImpl extends AbstractTinkerpopChampGraph { return relationshipIndices; } + @Override public void executeStoreObjectIndex(ChampObjectIndex index) { + if (isShutdown()) throw new IllegalStateException("Cannot call storeObjectIndex() after shutdown has been initiated"); getGraph().createIndex(index.getField().getName(), Vertex.class); @@ -179,4 +201,9 @@ public final class InMemoryChampGraphImpl extends AbstractTinkerpopChampGraph { public ChampCapabilities capabilities() { return CAPABILITIES; } + + @Override + public GraphTraversal hasLabel(GraphTraversal query, Object type) { + return query.hasLabel((String)type, (String)type); + } } diff --git a/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/graph/impl/TinkerpopTransaction.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/graph/impl/TinkerpopTransaction.java new file mode 100644 index 0000000..6ffeab7 --- /dev/null +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/graph/impl/TinkerpopTransaction.java @@ -0,0 +1,164 @@ +/** + * ============LICENSE_START========================================== + * org.onap.aai + * =================================================================== + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 Amdocs + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END============================================ + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.champcore.graph.impl; + +import java.util.UUID; + +import org.apache.tinkerpop.gremlin.structure.Graph; +import org.onap.aai.champcore.ChampTransaction; +import org.onap.aai.champcore.exceptions.ChampTransactionException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class TinkerpopTransaction extends ChampTransaction { + + private static final int COMMIT_RETRY_COUNT = 3; + + /** Threaded Tinkerpop transaction. */ + protected Graph threadedTransaction; + + + private static final Logger LOGGER = LoggerFactory.getLogger(TinkerpopTransaction.class); + + protected TinkerpopTransaction() { } + + + /** + * Creates a new transaction instance. + * + * @param aGraphInstance - Instance of the graph to request the transaction from. + */ + public TinkerpopTransaction(Graph aGraphInstance) { + super(); + + if(!aGraphInstance.features().graph().supportsTransactions()) { + throw new UnsupportedOperationException(); + } + + // Request a threaded transaction object from the graph. + this.threadedTransaction = aGraphInstance.tx().createThreadedTx(); + + LOGGER.info("Open transaction - id: " + id); + } + + @Override + public String id() { + return id.toString(); + } + + public Graph getGraphInstance() { + return threadedTransaction; + } + + @Override + public void commit() throws ChampTransactionException { + + LOGGER.debug("Commiting transaction - " + id); + + final long initialBackoff = (int) (Math.random() * 50); + + // If something goes wrong, we will retry a couple of times before + // giving up. + for (int i = 0; i < COMMIT_RETRY_COUNT; i++) { + + try { + + // Do the commit. + threadedTransaction.tx().commit(); + LOGGER.info("Committed transaction - id: " + id); + return; + + } catch (Throwable e) { + + LOGGER.debug("Transaction " + id + " failed to commit due to: " + e.getMessage()); + + // Have we used up all of our retries? + if (i == COMMIT_RETRY_COUNT - 1) { + + LOGGER.error("Maxed out commit attempt retries, client must handle exception and retry", e); + threadedTransaction.tx().rollback(); + throw new ChampTransactionException(e); + } + + // Calculate how long we will wait before retrying... + final long backoff = (long) Math.pow(2, i) * initialBackoff; + LOGGER.warn("Caught exception while retrying transaction commit, retrying in " + backoff + " ms"); + + // ...and sleep before trying the commit again. + try { + Thread.sleep(backoff); + + } catch (InterruptedException ie) { + + LOGGER.info("Interrupted while backing off on transaction commit"); + Thread.interrupted(); + return; + } + } + } + } + + @Override + public void rollback() throws ChampTransactionException { + + long initialBackoff = (int) (Math.random() * 50); + + + // If something goes wrong, we will retry a couple of times before + // giving up. + for (int i = 0; i < COMMIT_RETRY_COUNT; i++) { + + try { + + threadedTransaction.tx().rollback(); + LOGGER.info("Rolled back transaction - id: " + id); + return; + + } catch (Throwable e) { + + LOGGER.debug("Transaction " + id + " failed to roll back due to: " + e.getMessage()); + + // Have we used up all of our retries? + if (i == COMMIT_RETRY_COUNT - 1) { + + LOGGER.error("Maxed out rollback attempt retries, client must handle exception and retry", e); + throw new ChampTransactionException(e); + } + + // Calculate how long we will wait before retrying... + final long backoff = (long) Math.pow(2, i) * initialBackoff; + LOGGER.warn("Caught exception while retrying transaction roll back, retrying in " + backoff + " ms"); + + // ...and sleep before trying the commit again. + try { + Thread.sleep(backoff); + + } catch (InterruptedException ie) { + + LOGGER.info("Interrupted while backing off on transaction rollback"); + Thread.interrupted(); + return; + } + } + } + } +} diff --git a/src/main/java/org/onap/aai/champ/ie/Exporter.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/ie/Exporter.java similarity index 93% rename from src/main/java/org/onap/aai/champ/ie/Exporter.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/ie/Exporter.java index 5c96915..ddea9ec 100644 --- a/src/main/java/org/onap/aai/champ/ie/Exporter.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/ie/Exporter.java @@ -19,11 +19,11 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.ie; +package org.onap.aai.champcore.ie; import java.io.OutputStream; -import org.onap.aai.champ.ChampGraph; +import org.onap.aai.champcore.ChampGraph; public interface Exporter { diff --git a/src/main/java/org/onap/aai/champ/ie/GraphMLImporterExporter.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/ie/GraphMLImporterExporter.java similarity index 90% rename from src/main/java/org/onap/aai/champ/ie/GraphMLImporterExporter.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/ie/GraphMLImporterExporter.java index 4e108e9..71292ce 100644 --- a/src/main/java/org/onap/aai/champ/ie/GraphMLImporterExporter.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/ie/GraphMLImporterExporter.java @@ -19,7 +19,7 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.ie; +package org.onap.aai.champcore.ie; import java.io.IOException; import java.io.InputStream; @@ -42,16 +42,18 @@ import javax.xml.stream.XMLOutputFactory; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamWriter; -import org.onap.aai.champ.ChampAPI; -import org.onap.aai.champ.ChampGraph; -import org.onap.aai.champ.exceptions.ChampMarshallingException; -import org.onap.aai.champ.exceptions.ChampObjectNotExistsException; -import org.onap.aai.champ.exceptions.ChampRelationshipNotExistsException; -import org.onap.aai.champ.exceptions.ChampSchemaViolationException; -import org.onap.aai.champ.exceptions.ChampUnmarshallingException; -import org.onap.aai.champ.model.ChampObject; -import org.onap.aai.champ.model.ChampObjectIndex; -import org.onap.aai.champ.model.ChampRelationship; +import org.onap.aai.champcore.ChampAPI; +import org.onap.aai.champcore.ChampGraph; +import org.onap.aai.champcore.ChampTransaction; +import org.onap.aai.champcore.exceptions.ChampMarshallingException; +import org.onap.aai.champcore.exceptions.ChampObjectNotExistsException; +import org.onap.aai.champcore.exceptions.ChampRelationshipNotExistsException; +import org.onap.aai.champcore.exceptions.ChampSchemaViolationException; +import org.onap.aai.champcore.exceptions.ChampTransactionException; +import org.onap.aai.champcore.exceptions.ChampUnmarshallingException; +import org.onap.aai.champcore.model.ChampObject; +import org.onap.aai.champcore.model.ChampObjectIndex; +import org.onap.aai.champcore.model.ChampRelationship; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.w3c.dom.Document; @@ -183,25 +185,27 @@ public class GraphMLImporterExporter implements Importer, Exporter { final NodeList data = edge.getChildNodes(); final Object sourceKey = edgeAttributes.getNamedItem("source").getNodeValue(); final Object targetKey = edgeAttributes.getNamedItem("target").getNodeValue(); - final ChampObject sourceObject; - final ChampObject targetObject; - + ChampObject sourceObject=null; + ChampObject targetObject=null; + try { - final Optional source = graph.queryObjects(Collections.singletonMap("importAssignedId", sourceKey)).findFirst(); - final Optional target = graph.queryObjects(Collections.singletonMap("importAssignedId", targetKey)).findFirst(); + final Optional source = graph.queryObjects(Collections.singletonMap("importAssignedId", sourceKey), Optional.empty()).findFirst(); + final Optional target = graph.queryObjects(Collections.singletonMap("importAssignedId", targetKey), Optional.empty()).findFirst(); if (!source.isPresent()) { sourceObject = graph.storeObject(ChampObject.create() .ofType("undefined") .withoutKey() - .build()); + .build(), + Optional.empty()); } else sourceObject = source.get(); if (!target.isPresent()) { targetObject = graph.storeObject(ChampObject.create() .ofType("undefined") .withoutKey() - .build()); + .build(), + Optional.empty()); } else targetObject = target.get(); } catch (ChampMarshallingException e) { @@ -213,6 +217,8 @@ public class GraphMLImporterExporter implements Importer, Exporter { } catch (ChampObjectNotExistsException e) { LOGGER.error("Failed to update existing source/target ChampObject", e); return; + } catch (ChampTransactionException e) { + LOGGER.error("Failed to commit or rollback transaction", e); } final ChampRelationship.Builder champRelBuilder = new ChampRelationship.Builder(sourceObject, targetObject, "undefined"); @@ -256,7 +262,7 @@ public class GraphMLImporterExporter implements Importer, Exporter { final ChampRelationship relToStore = champRelBuilder.build(); try { - graph.storeRelationship(relToStore); + graph.storeRelationship(relToStore, Optional.empty()); } catch (ChampMarshallingException e) { LOGGER.warn("Failed to marshall ChampObject to backend type", e); } catch (ChampSchemaViolationException e) { @@ -267,7 +273,10 @@ public class GraphMLImporterExporter implements Importer, Exporter { LOGGER.error("Objects bound to relationship do not exist (should never happen)"); } catch (ChampUnmarshallingException e) { LOGGER.error("Failed to unmarshall ChampObject to backend type"); + } catch (ChampTransactionException e) { + LOGGER.error("Failed to commit or rollback transaction"); } + } private void writeNode(ChampGraph graph, Node node, Map> nodePropertyDefinitions, Set> nodeDefaults) { @@ -323,15 +332,17 @@ public class GraphMLImporterExporter implements Importer, Exporter { final ChampObject objectToStore = champObjBuilder.build(); - try { - graph.storeObject(objectToStore); + try { + graph.storeObject(objectToStore, Optional.empty()); } catch (ChampMarshallingException e) { LOGGER.warn("Failed to marshall ChampObject to backend type", e); } catch (ChampSchemaViolationException e) { LOGGER.error("Failed to store object (schema violated): " + objectToStore, e); } catch (ChampObjectNotExistsException e) { LOGGER.error("Failed to update existing ChampObject", e); - } + } catch (ChampTransactionException e) { + LOGGER.error("Failed to commit or rollback transaction"); + } } @Override @@ -354,7 +365,7 @@ public class GraphMLImporterExporter implements Importer, Exporter { final Map edgeKeys = new HashMap (); final AtomicInteger elementCount = new AtomicInteger(); - graph.queryObjects(Collections.emptyMap()).forEach(object -> { + graph.queryObjects(Collections.emptyMap(), Optional.empty()).forEach(object -> { nodes.add(object); for (Map.Entry property : object.getProperties().entrySet()) { @@ -366,7 +377,7 @@ public class GraphMLImporterExporter implements Importer, Exporter { nodeKeys.put("type", new GraphMLKey("d" + elementCount.incrementAndGet(), "type", String.class)); }); - graph.queryRelationships(Collections.emptyMap()).forEach(relationship -> { + graph.queryRelationships(Collections.emptyMap(), Optional.empty()).forEach(relationship -> { edges.add(relationship); for (Map.Entry property : relationship.getProperties().entrySet()) { @@ -453,7 +464,7 @@ public class GraphMLImporterExporter implements Importer, Exporter { writer.writeEndElement(); writer.writeEndDocument(); writer.flush(); - } catch (XMLStreamException e) { + } catch (XMLStreamException | ChampTransactionException e) { throw new RuntimeException(e); } } diff --git a/src/main/java/org/onap/aai/champ/ie/Importer.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/ie/Importer.java similarity index 93% rename from src/main/java/org/onap/aai/champ/ie/Importer.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/ie/Importer.java index d28da22..4fc22ba 100644 --- a/src/main/java/org/onap/aai/champ/ie/Importer.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/ie/Importer.java @@ -19,11 +19,11 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.ie; +package org.onap.aai.champcore.ie; import java.io.InputStream; -import org.onap.aai.champ.ChampAPI; +import org.onap.aai.champcore.ChampAPI; public interface Importer { diff --git a/src/main/java/org/onap/aai/champ/model/ChampCardinality.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/ChampCardinality.java similarity index 96% rename from src/main/java/org/onap/aai/champ/model/ChampCardinality.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/ChampCardinality.java index ab8f0a2..b1e72f7 100644 --- a/src/main/java/org/onap/aai/champ/model/ChampCardinality.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/ChampCardinality.java @@ -19,7 +19,7 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model; +package org.onap.aai.champcore.model; public enum ChampCardinality { SINGLE, diff --git a/src/main/java/org/onap/aai/champ/model/ChampConnectionConstraint.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/ChampConnectionConstraint.java similarity index 98% rename from src/main/java/org/onap/aai/champ/model/ChampConnectionConstraint.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/ChampConnectionConstraint.java index 4e6ff59..af44857 100644 --- a/src/main/java/org/onap/aai/champ/model/ChampConnectionConstraint.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/ChampConnectionConstraint.java @@ -19,7 +19,7 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model; +package org.onap.aai.champcore.model; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; diff --git a/src/main/java/org/onap/aai/champ/model/ChampConnectionMultiplicity.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/ChampConnectionMultiplicity.java similarity index 97% rename from src/main/java/org/onap/aai/champ/model/ChampConnectionMultiplicity.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/ChampConnectionMultiplicity.java index 1615a5a..d2742fe 100644 --- a/src/main/java/org/onap/aai/champ/model/ChampConnectionMultiplicity.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/ChampConnectionMultiplicity.java @@ -19,7 +19,7 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model; +package org.onap.aai.champcore.model; public enum ChampConnectionMultiplicity { NONE, //Cannot have any relationships of a type between two object types diff --git a/src/main/java/org/onap/aai/champ/model/ChampElement.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/ChampElement.java similarity index 91% rename from src/main/java/org/onap/aai/champ/model/ChampElement.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/ChampElement.java index d92669b..4e938f5 100644 --- a/src/main/java/org/onap/aai/champ/model/ChampElement.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/ChampElement.java @@ -19,7 +19,9 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model; +package org.onap.aai.champcore.model; + +import java.util.Map; public interface ChampElement { @@ -28,4 +30,6 @@ public interface ChampElement { public boolean isRelationship(); public ChampRelationship asRelationship(); + + public Map getProperties(); } diff --git a/src/main/java/org/onap/aai/champ/model/ChampField.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/ChampField.java similarity index 98% rename from src/main/java/org/onap/aai/champ/model/ChampField.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/ChampField.java index 1b6ec90..92c3ea0 100644 --- a/src/main/java/org/onap/aai/champ/model/ChampField.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/ChampField.java @@ -19,7 +19,7 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model; +package org.onap.aai.champcore.model; import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; diff --git a/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/ChampObject.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/ChampObject.java new file mode 100644 index 0000000..b4e7311 --- /dev/null +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/ChampObject.java @@ -0,0 +1,280 @@ +/** + * ============LICENSE_START========================================== + * org.onap.aai + * =================================================================== + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 Amdocs + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END============================================ + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.champcore.model; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; + +import org.onap.aai.champcore.model.fluent.object.CreateChampObjectable; +import org.onap.aai.champcore.model.fluent.object.impl.CreateChampObjectableImpl; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Optional; + +public final class ChampObject implements ChampElement { + + private String type; + private Optional key; + private Map properties; + + public static CreateChampObjectable create() { + return new CreateChampObjectableImpl(); + } + + public ChampObject() { + } + + private ChampObject(Builder builder) { + this.type = builder.type; + this.key = builder.key; + this.properties = builder.properties; + } + + @SuppressWarnings("unchecked") + public Optional getProperty(String key) { + if (!properties.containsKey(key)) { + return Optional.empty(); + } + + return Optional.of((T) properties.get(key)); + } + + public String getType() { + return type; + } + + @JsonIgnore + public Optional getKey() { + return key; + } + + public Map getProperties() { + return properties; + } + + @JsonProperty("key") + public Object getKeyValue() { + return key.orElse(""); + + } + + public ChampObject dropProperties(HashSet safeProperties) { + HashSet propertyKeys = new HashSet<>(properties.keySet()); + for (String key : propertyKeys) { + if (!safeProperties.contains(key)) { + properties.remove(key); + } + } + + return this; + } + + public static class Builder { + private final String type; + private final Map properties = new HashMap(); + + private Optional key = Optional.empty(); + + public Builder(String type) { + if (type == null) { + throw new IllegalArgumentException("Type cannot be null"); + } + + this.type = type; + } + + public Builder(ChampObject object) { + type = object.getType(); + key = object.getKey(); + properties(object.getProperties()); + } + + public Builder key(Object key) { + if (key == null) { + throw new IllegalArgumentException("Key cannot be set to null"); + } + + this.key = Optional.of(key); + return this; + } + + public Builder property(String key, Object value) { + if (key == null) { + throw new IllegalArgumentException("Property key cannot be null"); + } + if (value == null) { + throw new IllegalArgumentException("Property value cannot be null"); + } + + if (ReservedPropertyKeys.contains(key)) { + throw new IllegalArgumentException("Property key " + key + " is reserved"); + } + + properties.put(key, value); + return this; + } + + public Builder properties(Map properties) { + for (Entry property : properties.entrySet()) { + property(property.getKey(), property.getValue()); + } + + return this; + } + + public ChampObject build() { + return new ChampObject(this); + } + } + + @Override + public boolean equals(Object object) { + if (this == object) { + return true; + } + + if (object instanceof ChampObject) { + final ChampObject champObj = (ChampObject) object; + + if (getKey().isPresent() && champObj.getKey().isPresent()) { + + if (getKey().get().equals(champObj.getKey().get())) { + return true; + } + + } else if (!getKey().isPresent() && !champObj.getKey().isPresent()) { + if (getType().equals(champObj.getType()) && + getProperties().equals(champObj.getProperties())) { + return true; + } + } + } + + return false; + } + + @Override + public int hashCode() { + if (getKey().isPresent()) { + return getKey().get().hashCode(); + } + + final int returnValue = 31 * (getType().hashCode() + getProperties().hashCode()); + return returnValue; + } + + @Override + public String toString() { + return "{key: " + (getKey().isPresent() ? getKey().get() : "") + + ", type: " + getType() + + ", properties: " + getProperties() + "}"; + } + + public enum ReservedPropertyKeys { + CHAMP_OBJECT_TYPE("aai_node_type"), + CHAMP_OBJECT_KEY("key"); + + private final String text; + + private ReservedPropertyKeys(final String text) { + this.text = text; + } + + @Override + public String toString() { + return text; + } + + public static boolean contains(String key) { + for (ReservedPropertyKeys choice : ReservedPropertyKeys.values()) { + if (choice.toString().equals(key)) { + return true; + } + } + + return false; + } + } + + public enum IgnoreOnReadPropertyKeys { + CHAMP_IMPORT_ASSIGNED_ID("importAssignedId"); + + private final String text; + + private IgnoreOnReadPropertyKeys(final String text) { + this.text = text; + } + + @Override + public String toString() { + return text; + } + + public static boolean contains(String key) { + for (IgnoreOnReadPropertyKeys choice : IgnoreOnReadPropertyKeys.values()) { + if (choice.toString().equals(key)) { + return true; + } + } + + return false; + } + } + + public enum ReservedTypes { + ANY("ANY"); + + private final String text; + + private ReservedTypes(final String text) { + this.text = text; + } + + @Override + public String toString() { + return text; + } + } + + @Override + public boolean isObject() { + return true; + } + + @Override + public ChampObject asObject() { + return this; + } + + @Override + public boolean isRelationship() { + return false; + } + + @Override + public ChampRelationship asRelationship() { + throw new UnsupportedOperationException("Cannot call asRelationship() on ChampObject"); + } +} diff --git a/src/main/java/org/onap/aai/champ/model/ChampObjectConstraint.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/ChampObjectConstraint.java similarity index 98% rename from src/main/java/org/onap/aai/champ/model/ChampObjectConstraint.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/ChampObjectConstraint.java index 0423da4..1a91c7a 100644 --- a/src/main/java/org/onap/aai/champ/model/ChampObjectConstraint.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/ChampObjectConstraint.java @@ -19,7 +19,7 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model; +package org.onap.aai.champcore.model; import java.util.HashMap; import java.util.HashSet; diff --git a/src/main/java/org/onap/aai/champ/model/ChampObjectIndex.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/ChampObjectIndex.java similarity index 92% rename from src/main/java/org/onap/aai/champ/model/ChampObjectIndex.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/ChampObjectIndex.java index 7d52334..c16844c 100644 --- a/src/main/java/org/onap/aai/champ/model/ChampObjectIndex.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/ChampObjectIndex.java @@ -19,10 +19,10 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model; +package org.onap.aai.champcore.model; -import org.onap.aai.champ.model.fluent.index.CreateObjectIndexable; -import org.onap.aai.champ.model.fluent.index.impl.CreateObjectIndexableImpl; +import org.onap.aai.champcore.model.fluent.index.CreateObjectIndexable; +import org.onap.aai.champcore.model.fluent.index.impl.CreateObjectIndexableImpl; public final class ChampObjectIndex { diff --git a/src/main/java/org/onap/aai/champ/model/ChampPartition.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/ChampPartition.java similarity index 90% rename from src/main/java/org/onap/aai/champ/model/ChampPartition.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/ChampPartition.java index 2c5c1a5..0292694 100644 --- a/src/main/java/org/onap/aai/champ/model/ChampPartition.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/ChampPartition.java @@ -19,15 +19,15 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model; +package org.onap.aai.champcore.model; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; -import org.onap.aai.champ.model.fluent.partition.CreateChampPartitionable; -import org.onap.aai.champ.model.fluent.partition.impl.CreateChampPartionableImpl; +import org.onap.aai.champcore.model.fluent.partition.CreateChampPartitionable; +import org.onap.aai.champcore.model.fluent.partition.impl.CreateChampPartionableImpl; public final class ChampPartition { @@ -126,7 +126,9 @@ public final class ChampPartition { sb.append(","); } - if (sb.charAt(sb.length() - 1) == ',') sb.deleteCharAt(sb.length() - 1); //Delete last comma + if (sb.charAt(sb.length() - 1) == ',') { + sb.deleteCharAt(sb.length() - 1); //Delete last comma + } sb.append("], relationships: ["); @@ -135,7 +137,9 @@ public final class ChampPartition { sb.append(","); } - if (sb.charAt(sb.length() - 1) == ',') sb.deleteCharAt(sb.length() - 1); //Delete last comma + if (sb.charAt(sb.length() - 1) == ',') { + sb.deleteCharAt(sb.length() - 1); //Delete last comma + } sb.append("]}"); diff --git a/src/main/java/org/onap/aai/champ/model/ChampPropertyConstraint.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/ChampPropertyConstraint.java similarity index 98% rename from src/main/java/org/onap/aai/champ/model/ChampPropertyConstraint.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/ChampPropertyConstraint.java index a881cd9..6008d36 100644 --- a/src/main/java/org/onap/aai/champ/model/ChampPropertyConstraint.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/ChampPropertyConstraint.java @@ -19,7 +19,7 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model; +package org.onap.aai.champcore.model; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; diff --git a/src/main/java/org/onap/aai/champ/model/ChampRelationship.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/ChampRelationship.java similarity index 89% rename from src/main/java/org/onap/aai/champ/model/ChampRelationship.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/ChampRelationship.java index 2b4e61b..2d7f033 100644 --- a/src/main/java/org/onap/aai/champ/model/ChampRelationship.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/ChampRelationship.java @@ -19,33 +19,31 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model; +package org.onap.aai.champcore.model; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; - -import org.onap.aai.champ.model.fluent.relationship.CreateChampRelationshipable; -import org.onap.aai.champ.model.fluent.relationship.impl.CreateChampRelationshipableImpl; - import java.util.Optional; +import org.onap.aai.champcore.model.fluent.relationship.CreateChampRelationshipable; +import org.onap.aai.champcore.model.fluent.relationship.impl.CreateChampRelationshipableImpl; + import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; public final class ChampRelationship implements ChampElement { - private final String type; //AKA edge label - private final Optional key; - private final Map properties; - private final ChampObject source; - private final ChampObject target; + private String type; //AKA edge label + private Optional key; + private Map properties; + private ChampObject source; + private ChampObject target; public static CreateChampRelationshipable create() { return new CreateChampRelationshipableImpl(); } - private ChampRelationship() { //Not instantiable - throw new RuntimeException("Cannot call ChampRelationship() constructor"); + public ChampRelationship() { //Not instantiable } private ChampRelationship(Builder builder) { @@ -58,12 +56,16 @@ public final class ChampRelationship implements ChampElement { @JsonIgnore public Optional getKey() { - return key; + if (key == null) { + return Optional.empty (); + } else { + return key; + } } @JsonProperty("key") - public Object getKeyValue() { - return key.orElse(""); + public String getKeyValue() { + return (getKey().isPresent() ? getKey().get() : "").toString(); } public ChampObject getSource() { diff --git a/src/main/java/org/onap/aai/champ/model/ChampRelationshipConstraint.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/ChampRelationshipConstraint.java similarity index 99% rename from src/main/java/org/onap/aai/champ/model/ChampRelationshipConstraint.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/ChampRelationshipConstraint.java index ac030e9..b571205 100644 --- a/src/main/java/org/onap/aai/champ/model/ChampRelationshipConstraint.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/ChampRelationshipConstraint.java @@ -19,7 +19,7 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model; +package org.onap.aai.champcore.model; import java.util.HashMap; import java.util.HashSet; diff --git a/src/main/java/org/onap/aai/champ/model/ChampRelationshipIndex.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/ChampRelationshipIndex.java similarity index 92% rename from src/main/java/org/onap/aai/champ/model/ChampRelationshipIndex.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/ChampRelationshipIndex.java index 6b2cee5..03310ba 100644 --- a/src/main/java/org/onap/aai/champ/model/ChampRelationshipIndex.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/ChampRelationshipIndex.java @@ -19,10 +19,10 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model; +package org.onap.aai.champcore.model; -import org.onap.aai.champ.model.fluent.index.CreateRelationshipIndexable; -import org.onap.aai.champ.model.fluent.index.impl.CreateRelationshipIndexableImpl; +import org.onap.aai.champcore.model.fluent.index.CreateRelationshipIndexable; +import org.onap.aai.champcore.model.fluent.index.impl.CreateRelationshipIndexableImpl; public final class ChampRelationshipIndex { diff --git a/src/main/java/org/onap/aai/champ/model/ChampSchema.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/ChampSchema.java similarity index 96% rename from src/main/java/org/onap/aai/champ/model/ChampSchema.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/ChampSchema.java index bd612df..81b97bd 100644 --- a/src/main/java/org/onap/aai/champ/model/ChampSchema.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/ChampSchema.java @@ -19,17 +19,16 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model; +package org.onap.aai.champcore.model; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; - -import org.onap.aai.champ.model.fluent.schema.CreateChampSchemable; -import org.onap.aai.champ.model.fluent.schema.impl.CreateChampSchemableImpl; - import java.util.Optional; +import org.onap.aai.champcore.model.fluent.schema.CreateChampSchemable; +import org.onap.aai.champcore.model.fluent.schema.impl.CreateChampSchemableImpl; + import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder; diff --git a/src/main/java/org/onap/aai/champ/model/fluent/BuildStep.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/BuildStep.java similarity index 96% rename from src/main/java/org/onap/aai/champ/model/fluent/BuildStep.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/BuildStep.java index 97f7445..6619b90 100644 --- a/src/main/java/org/onap/aai/champ/model/fluent/BuildStep.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/BuildStep.java @@ -19,7 +19,7 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model.fluent; +package org.onap.aai.champcore.model.fluent; public interface BuildStep { public T build(); diff --git a/src/main/java/org/onap/aai/champ/model/fluent/KeyStep.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/KeyStep.java similarity index 96% rename from src/main/java/org/onap/aai/champ/model/fluent/KeyStep.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/KeyStep.java index 6b34de1..0be4ac3 100644 --- a/src/main/java/org/onap/aai/champ/model/fluent/KeyStep.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/KeyStep.java @@ -19,9 +19,9 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model.fluent; +package org.onap.aai.champcore.model.fluent; public interface KeyStep { public T withKey(Object key); public T withoutKey(); -} +} \ No newline at end of file diff --git a/src/main/java/org/onap/aai/champ/model/fluent/PropertiesStep.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/PropertiesStep.java similarity index 96% rename from src/main/java/org/onap/aai/champ/model/fluent/PropertiesStep.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/PropertiesStep.java index 44b8ada..bac8878 100644 --- a/src/main/java/org/onap/aai/champ/model/fluent/PropertiesStep.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/PropertiesStep.java @@ -19,7 +19,7 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model.fluent; +package org.onap.aai.champcore.model.fluent; import java.util.Map; diff --git a/src/main/java/org/onap/aai/champ/model/fluent/index/CreateObjectIndexable.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/index/CreateObjectIndexable.java similarity index 95% rename from src/main/java/org/onap/aai/champ/model/fluent/index/CreateObjectIndexable.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/index/CreateObjectIndexable.java index 57372e5..ccace48 100644 --- a/src/main/java/org/onap/aai/champ/model/fluent/index/CreateObjectIndexable.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/index/CreateObjectIndexable.java @@ -19,7 +19,7 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model.fluent.index; +package org.onap.aai.champcore.model.fluent.index; public interface CreateObjectIndexable { diff --git a/src/main/java/org/onap/aai/champ/model/fluent/index/CreateRelationshipIndexable.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/index/CreateRelationshipIndexable.java similarity index 95% rename from src/main/java/org/onap/aai/champ/model/fluent/index/CreateRelationshipIndexable.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/index/CreateRelationshipIndexable.java index 16048ca..e40a86a 100644 --- a/src/main/java/org/onap/aai/champ/model/fluent/index/CreateRelationshipIndexable.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/index/CreateRelationshipIndexable.java @@ -19,7 +19,7 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model.fluent.index; +package org.onap.aai.champcore.model.fluent.index; public interface CreateRelationshipIndexable { diff --git a/src/main/java/org/onap/aai/champ/model/fluent/index/ObjectIndexFieldStep.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/index/ObjectIndexFieldStep.java similarity index 87% rename from src/main/java/org/onap/aai/champ/model/fluent/index/ObjectIndexFieldStep.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/index/ObjectIndexFieldStep.java index 4450e84..869cdd6 100644 --- a/src/main/java/org/onap/aai/champ/model/fluent/index/ObjectIndexFieldStep.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/index/ObjectIndexFieldStep.java @@ -19,12 +19,12 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model.fluent.index; +package org.onap.aai.champcore.model.fluent.index; -import org.onap.aai.champ.model.ChampObjectIndex; -import org.onap.aai.champ.model.fluent.BuildStep; +import org.onap.aai.champcore.model.ChampObjectIndex; +import org.onap.aai.champcore.model.fluent.BuildStep; public interface ObjectIndexFieldStep { public BuildStep forField(String fieldName); -} +} \ No newline at end of file diff --git a/src/main/java/org/onap/aai/champ/model/fluent/index/ObjectIndexTypeStep.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/index/ObjectIndexTypeStep.java similarity index 95% rename from src/main/java/org/onap/aai/champ/model/fluent/index/ObjectIndexTypeStep.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/index/ObjectIndexTypeStep.java index 71b201f..fc8db8a 100644 --- a/src/main/java/org/onap/aai/champ/model/fluent/index/ObjectIndexTypeStep.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/index/ObjectIndexTypeStep.java @@ -19,7 +19,7 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model.fluent.index; +package org.onap.aai.champcore.model.fluent.index; public interface ObjectIndexTypeStep { diff --git a/src/main/java/org/onap/aai/champ/model/fluent/index/RelationshipIndexFieldStep.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/index/RelationshipIndexFieldStep.java similarity index 87% rename from src/main/java/org/onap/aai/champ/model/fluent/index/RelationshipIndexFieldStep.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/index/RelationshipIndexFieldStep.java index f2bd33f..babd59e 100644 --- a/src/main/java/org/onap/aai/champ/model/fluent/index/RelationshipIndexFieldStep.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/index/RelationshipIndexFieldStep.java @@ -19,12 +19,12 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model.fluent.index; +package org.onap.aai.champcore.model.fluent.index; -import org.onap.aai.champ.model.ChampRelationshipIndex; -import org.onap.aai.champ.model.fluent.BuildStep; +import org.onap.aai.champcore.model.ChampRelationshipIndex; +import org.onap.aai.champcore.model.fluent.BuildStep; public interface RelationshipIndexFieldStep { public BuildStep forField(String fieldName); -} +} \ No newline at end of file diff --git a/src/main/java/org/onap/aai/champ/model/fluent/index/RelationshipIndexTypeStep.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/index/RelationshipIndexTypeStep.java similarity index 95% rename from src/main/java/org/onap/aai/champ/model/fluent/index/RelationshipIndexTypeStep.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/index/RelationshipIndexTypeStep.java index add1063..094f872 100644 --- a/src/main/java/org/onap/aai/champ/model/fluent/index/RelationshipIndexTypeStep.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/index/RelationshipIndexTypeStep.java @@ -19,7 +19,7 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model.fluent.index; +package org.onap.aai.champcore.model.fluent.index; public interface RelationshipIndexTypeStep { diff --git a/src/main/java/org/onap/aai/champ/model/fluent/index/impl/CreateObjectIndexableImpl.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/index/impl/CreateObjectIndexableImpl.java similarity index 82% rename from src/main/java/org/onap/aai/champ/model/fluent/index/impl/CreateObjectIndexableImpl.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/index/impl/CreateObjectIndexableImpl.java index f9b58c9..1e0eb1b 100644 --- a/src/main/java/org/onap/aai/champ/model/fluent/index/impl/CreateObjectIndexableImpl.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/index/impl/CreateObjectIndexableImpl.java @@ -19,15 +19,15 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model.fluent.index.impl; +package org.onap.aai.champcore.model.fluent.index.impl; -import org.onap.aai.champ.model.ChampField; -import org.onap.aai.champ.model.ChampObject; -import org.onap.aai.champ.model.ChampObjectIndex; -import org.onap.aai.champ.model.fluent.BuildStep; -import org.onap.aai.champ.model.fluent.index.CreateObjectIndexable; -import org.onap.aai.champ.model.fluent.index.ObjectIndexFieldStep; -import org.onap.aai.champ.model.fluent.index.ObjectIndexTypeStep; +import org.onap.aai.champcore.model.ChampField; +import org.onap.aai.champcore.model.ChampObject; +import org.onap.aai.champcore.model.ChampObjectIndex; +import org.onap.aai.champcore.model.fluent.BuildStep; +import org.onap.aai.champcore.model.fluent.index.CreateObjectIndexable; +import org.onap.aai.champcore.model.fluent.index.ObjectIndexFieldStep; +import org.onap.aai.champcore.model.fluent.index.ObjectIndexTypeStep; public final class CreateObjectIndexableImpl implements CreateObjectIndexable { diff --git a/src/main/java/org/onap/aai/champ/model/fluent/index/impl/CreateRelationshipIndexableImpl.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/index/impl/CreateRelationshipIndexableImpl.java similarity index 79% rename from src/main/java/org/onap/aai/champ/model/fluent/index/impl/CreateRelationshipIndexableImpl.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/index/impl/CreateRelationshipIndexableImpl.java index 7c21a62..40d105e 100644 --- a/src/main/java/org/onap/aai/champ/model/fluent/index/impl/CreateRelationshipIndexableImpl.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/index/impl/CreateRelationshipIndexableImpl.java @@ -19,14 +19,14 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model.fluent.index.impl; +package org.onap.aai.champcore.model.fluent.index.impl; -import org.onap.aai.champ.model.ChampField; -import org.onap.aai.champ.model.ChampRelationshipIndex; -import org.onap.aai.champ.model.fluent.BuildStep; -import org.onap.aai.champ.model.fluent.index.CreateRelationshipIndexable; -import org.onap.aai.champ.model.fluent.index.RelationshipIndexFieldStep; -import org.onap.aai.champ.model.fluent.index.RelationshipIndexTypeStep; +import org.onap.aai.champcore.model.ChampField; +import org.onap.aai.champcore.model.ChampRelationshipIndex; +import org.onap.aai.champcore.model.fluent.BuildStep; +import org.onap.aai.champcore.model.fluent.index.CreateRelationshipIndexable; +import org.onap.aai.champcore.model.fluent.index.RelationshipIndexFieldStep; +import org.onap.aai.champcore.model.fluent.index.RelationshipIndexTypeStep; public final class CreateRelationshipIndexableImpl implements CreateRelationshipIndexable { diff --git a/src/main/java/org/onap/aai/champ/model/fluent/object/CreateChampObjectable.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/object/CreateChampObjectable.java similarity index 88% rename from src/main/java/org/onap/aai/champ/model/fluent/object/CreateChampObjectable.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/object/CreateChampObjectable.java index 8c586f5..b062a09 100644 --- a/src/main/java/org/onap/aai/champ/model/fluent/object/CreateChampObjectable.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/object/CreateChampObjectable.java @@ -19,10 +19,10 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model.fluent.object; +package org.onap.aai.champcore.model.fluent.object; -import org.onap.aai.champ.model.ChampObject; -import org.onap.aai.champ.model.fluent.KeyStep; +import org.onap.aai.champcore.model.ChampObject; +import org.onap.aai.champcore.model.fluent.KeyStep; public interface CreateChampObjectable { public KeyStep ofType(String type); diff --git a/src/main/java/org/onap/aai/champ/model/fluent/object/ObjectBuildOrPropertiesStep.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/object/ObjectBuildOrPropertiesStep.java similarity index 84% rename from src/main/java/org/onap/aai/champ/model/fluent/object/ObjectBuildOrPropertiesStep.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/object/ObjectBuildOrPropertiesStep.java index 42db899..d982b81 100644 --- a/src/main/java/org/onap/aai/champ/model/fluent/object/ObjectBuildOrPropertiesStep.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/object/ObjectBuildOrPropertiesStep.java @@ -19,11 +19,11 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model.fluent.object; +package org.onap.aai.champcore.model.fluent.object; -import org.onap.aai.champ.model.ChampObject; -import org.onap.aai.champ.model.fluent.BuildStep; -import org.onap.aai.champ.model.fluent.PropertiesStep; +import org.onap.aai.champcore.model.ChampObject; +import org.onap.aai.champcore.model.fluent.BuildStep; +import org.onap.aai.champcore.model.fluent.PropertiesStep; public interface ObjectBuildOrPropertiesStep extends BuildStep, PropertiesStep { diff --git a/src/main/java/org/onap/aai/champ/model/fluent/object/ObjectBuildOrPropertiesStepImpl.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/object/ObjectBuildOrPropertiesStepImpl.java similarity index 91% rename from src/main/java/org/onap/aai/champ/model/fluent/object/ObjectBuildOrPropertiesStepImpl.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/object/ObjectBuildOrPropertiesStepImpl.java index b28045c..7938346 100644 --- a/src/main/java/org/onap/aai/champ/model/fluent/object/ObjectBuildOrPropertiesStepImpl.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/object/ObjectBuildOrPropertiesStepImpl.java @@ -19,12 +19,12 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model.fluent.object; +package org.onap.aai.champcore.model.fluent.object; import java.util.Map; -import org.onap.aai.champ.model.ChampObject; -import org.onap.aai.champ.model.ChampObject.Builder; +import org.onap.aai.champcore.model.ChampObject; +import org.onap.aai.champcore.model.ChampObject.Builder; public final class ObjectBuildOrPropertiesStepImpl implements ObjectBuildOrPropertiesStep { diff --git a/src/main/java/org/onap/aai/champ/model/fluent/object/ObjectKeyStepImpl.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/object/ObjectKeyStepImpl.java similarity index 87% rename from src/main/java/org/onap/aai/champ/model/fluent/object/ObjectKeyStepImpl.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/object/ObjectKeyStepImpl.java index f926b66..d05c84d 100644 --- a/src/main/java/org/onap/aai/champ/model/fluent/object/ObjectKeyStepImpl.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/object/ObjectKeyStepImpl.java @@ -19,11 +19,11 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model.fluent.object; +package org.onap.aai.champcore.model.fluent.object; -import org.onap.aai.champ.model.ChampObject; -import org.onap.aai.champ.model.ChampObject.Builder; -import org.onap.aai.champ.model.fluent.KeyStep; +import org.onap.aai.champcore.model.ChampObject; +import org.onap.aai.champcore.model.ChampObject.Builder; +import org.onap.aai.champcore.model.fluent.KeyStep; public final class ObjectKeyStepImpl implements KeyStep { diff --git a/src/main/java/org/onap/aai/champ/model/fluent/object/impl/CreateChampObjectableImpl.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/object/impl/CreateChampObjectableImpl.java similarity index 78% rename from src/main/java/org/onap/aai/champ/model/fluent/object/impl/CreateChampObjectableImpl.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/object/impl/CreateChampObjectableImpl.java index d6b7e48..242c4c8 100644 --- a/src/main/java/org/onap/aai/champ/model/fluent/object/impl/CreateChampObjectableImpl.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/object/impl/CreateChampObjectableImpl.java @@ -19,13 +19,13 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model.fluent.object.impl; +package org.onap.aai.champcore.model.fluent.object.impl; -import org.onap.aai.champ.model.ChampObject; -import org.onap.aai.champ.model.fluent.KeyStep; -import org.onap.aai.champ.model.fluent.object.CreateChampObjectable; -import org.onap.aai.champ.model.fluent.object.ObjectBuildOrPropertiesStep; -import org.onap.aai.champ.model.fluent.object.ObjectKeyStepImpl; +import org.onap.aai.champcore.model.ChampObject; +import org.onap.aai.champcore.model.fluent.KeyStep; +import org.onap.aai.champcore.model.fluent.object.CreateChampObjectable; +import org.onap.aai.champcore.model.fluent.object.ObjectBuildOrPropertiesStep; +import org.onap.aai.champcore.model.fluent.object.ObjectKeyStepImpl; public final class CreateChampObjectableImpl implements CreateChampObjectable { diff --git a/src/main/java/org/onap/aai/champ/model/fluent/partition/CreateChampPartitionable.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/partition/CreateChampPartitionable.java similarity index 83% rename from src/main/java/org/onap/aai/champ/model/fluent/partition/CreateChampPartitionable.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/partition/CreateChampPartitionable.java index 785bd88..e65ca4f 100644 --- a/src/main/java/org/onap/aai/champ/model/fluent/partition/CreateChampPartitionable.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/partition/CreateChampPartitionable.java @@ -19,12 +19,12 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model.fluent.partition; +package org.onap.aai.champcore.model.fluent.partition; -import org.onap.aai.champ.model.ChampObject; -import org.onap.aai.champ.model.ChampPartition; -import org.onap.aai.champ.model.ChampRelationship; -import org.onap.aai.champ.model.fluent.BuildStep; +import org.onap.aai.champcore.model.ChampObject; +import org.onap.aai.champcore.model.ChampPartition; +import org.onap.aai.champcore.model.ChampRelationship; +import org.onap.aai.champcore.model.fluent.BuildStep; public interface CreateChampPartitionable extends BuildStep { diff --git a/src/main/java/org/onap/aai/champ/model/fluent/partition/impl/CreateChampPartionableImpl.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/partition/impl/CreateChampPartionableImpl.java similarity index 84% rename from src/main/java/org/onap/aai/champ/model/fluent/partition/impl/CreateChampPartionableImpl.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/partition/impl/CreateChampPartionableImpl.java index f6774fc..cfd284e 100644 --- a/src/main/java/org/onap/aai/champ/model/fluent/partition/impl/CreateChampPartionableImpl.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/partition/impl/CreateChampPartionableImpl.java @@ -19,12 +19,12 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model.fluent.partition.impl; +package org.onap.aai.champcore.model.fluent.partition.impl; -import org.onap.aai.champ.model.ChampObject; -import org.onap.aai.champ.model.ChampPartition; -import org.onap.aai.champ.model.ChampRelationship; -import org.onap.aai.champ.model.fluent.partition.CreateChampPartitionable; +import org.onap.aai.champcore.model.ChampObject; +import org.onap.aai.champcore.model.ChampPartition; +import org.onap.aai.champcore.model.ChampRelationship; +import org.onap.aai.champcore.model.fluent.partition.CreateChampPartitionable; public final class CreateChampPartionableImpl implements CreateChampPartitionable { diff --git a/src/main/java/org/onap/aai/champ/model/fluent/relationship/CreateChampRelationshipable.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/relationship/CreateChampRelationshipable.java similarity index 88% rename from src/main/java/org/onap/aai/champ/model/fluent/relationship/CreateChampRelationshipable.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/relationship/CreateChampRelationshipable.java index d59a4f0..bb89c21 100644 --- a/src/main/java/org/onap/aai/champ/model/fluent/relationship/CreateChampRelationshipable.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/relationship/CreateChampRelationshipable.java @@ -19,10 +19,10 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model.fluent.relationship; +package org.onap.aai.champcore.model.fluent.relationship; -import org.onap.aai.champ.model.ChampRelationship; -import org.onap.aai.champ.model.fluent.KeyStep; +import org.onap.aai.champcore.model.ChampRelationship; +import org.onap.aai.champcore.model.fluent.KeyStep; public interface CreateChampRelationshipable { public KeyStep ofType(String type); diff --git a/src/main/java/org/onap/aai/champ/model/fluent/relationship/RelationshipBuildOrPropertiesStep.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/relationship/RelationshipBuildOrPropertiesStep.java similarity index 83% rename from src/main/java/org/onap/aai/champ/model/fluent/relationship/RelationshipBuildOrPropertiesStep.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/relationship/RelationshipBuildOrPropertiesStep.java index 5c103cd..44ee875 100644 --- a/src/main/java/org/onap/aai/champ/model/fluent/relationship/RelationshipBuildOrPropertiesStep.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/relationship/RelationshipBuildOrPropertiesStep.java @@ -19,11 +19,11 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model.fluent.relationship; +package org.onap.aai.champcore.model.fluent.relationship; -import org.onap.aai.champ.model.ChampRelationship; -import org.onap.aai.champ.model.fluent.BuildStep; -import org.onap.aai.champ.model.fluent.PropertiesStep; +import org.onap.aai.champcore.model.ChampRelationship; +import org.onap.aai.champcore.model.fluent.BuildStep; +import org.onap.aai.champcore.model.fluent.PropertiesStep; public interface RelationshipBuildOrPropertiesStep extends BuildStep, PropertiesStep { } diff --git a/src/main/java/org/onap/aai/champ/model/fluent/relationship/SourceBuildOrPropertiesStep.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/relationship/SourceBuildOrPropertiesStep.java similarity index 95% rename from src/main/java/org/onap/aai/champ/model/fluent/relationship/SourceBuildOrPropertiesStep.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/relationship/SourceBuildOrPropertiesStep.java index 8650b8a..5e02fa6 100644 --- a/src/main/java/org/onap/aai/champ/model/fluent/relationship/SourceBuildOrPropertiesStep.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/relationship/SourceBuildOrPropertiesStep.java @@ -19,7 +19,7 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model.fluent.relationship; +package org.onap.aai.champcore.model.fluent.relationship; public interface SourceBuildOrPropertiesStep { diff --git a/src/main/java/org/onap/aai/champ/model/fluent/relationship/SourceFromStep.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/relationship/SourceFromStep.java similarity index 91% rename from src/main/java/org/onap/aai/champ/model/fluent/relationship/SourceFromStep.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/relationship/SourceFromStep.java index d7b2601..18f1da6 100644 --- a/src/main/java/org/onap/aai/champ/model/fluent/relationship/SourceFromStep.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/relationship/SourceFromStep.java @@ -19,9 +19,9 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model.fluent.relationship; +package org.onap.aai.champcore.model.fluent.relationship; -import org.onap.aai.champ.model.ChampObject; +import org.onap.aai.champcore.model.ChampObject; public interface SourceFromStep { diff --git a/src/main/java/org/onap/aai/champ/model/fluent/relationship/SourceKeyStep.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/relationship/SourceKeyStep.java similarity index 95% rename from src/main/java/org/onap/aai/champ/model/fluent/relationship/SourceKeyStep.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/relationship/SourceKeyStep.java index 03991db..8e475e8 100644 --- a/src/main/java/org/onap/aai/champ/model/fluent/relationship/SourceKeyStep.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/relationship/SourceKeyStep.java @@ -19,7 +19,7 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model.fluent.relationship; +package org.onap.aai.champcore.model.fluent.relationship; public interface SourceKeyStep { diff --git a/src/main/java/org/onap/aai/champ/model/fluent/relationship/SourceStep.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/relationship/SourceStep.java similarity index 95% rename from src/main/java/org/onap/aai/champ/model/fluent/relationship/SourceStep.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/relationship/SourceStep.java index 5b6d737..843cf4f 100644 --- a/src/main/java/org/onap/aai/champ/model/fluent/relationship/SourceStep.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/relationship/SourceStep.java @@ -19,7 +19,7 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model.fluent.relationship; +package org.onap.aai.champcore.model.fluent.relationship; public interface SourceStep { public SourceTypeOrFromStep withSource(); diff --git a/src/main/java/org/onap/aai/champ/model/fluent/relationship/SourceTypeOrFromStep.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/relationship/SourceTypeOrFromStep.java similarity index 95% rename from src/main/java/org/onap/aai/champ/model/fluent/relationship/SourceTypeOrFromStep.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/relationship/SourceTypeOrFromStep.java index 932b480..5ae8550 100644 --- a/src/main/java/org/onap/aai/champ/model/fluent/relationship/SourceTypeOrFromStep.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/relationship/SourceTypeOrFromStep.java @@ -19,7 +19,7 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model.fluent.relationship; +package org.onap.aai.champcore.model.fluent.relationship; public interface SourceTypeOrFromStep extends SourceTypeStep, SourceFromStep { diff --git a/src/main/java/org/onap/aai/champ/model/fluent/relationship/SourceTypeStep.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/relationship/SourceTypeStep.java similarity index 95% rename from src/main/java/org/onap/aai/champ/model/fluent/relationship/SourceTypeStep.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/relationship/SourceTypeStep.java index 1466143..bff8902 100644 --- a/src/main/java/org/onap/aai/champ/model/fluent/relationship/SourceTypeStep.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/relationship/SourceTypeStep.java @@ -19,7 +19,7 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model.fluent.relationship; +package org.onap.aai.champcore.model.fluent.relationship; public interface SourceTypeStep { diff --git a/src/main/java/org/onap/aai/champ/model/fluent/relationship/TargetBuildOrPropertiesStep.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/relationship/TargetBuildOrPropertiesStep.java similarity index 95% rename from src/main/java/org/onap/aai/champ/model/fluent/relationship/TargetBuildOrPropertiesStep.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/relationship/TargetBuildOrPropertiesStep.java index a6b5a32..1a8ec49 100644 --- a/src/main/java/org/onap/aai/champ/model/fluent/relationship/TargetBuildOrPropertiesStep.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/relationship/TargetBuildOrPropertiesStep.java @@ -19,7 +19,7 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model.fluent.relationship; +package org.onap.aai.champcore.model.fluent.relationship; public interface TargetBuildOrPropertiesStep { diff --git a/src/main/java/org/onap/aai/champ/model/fluent/relationship/TargetFromStep.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/relationship/TargetFromStep.java similarity index 91% rename from src/main/java/org/onap/aai/champ/model/fluent/relationship/TargetFromStep.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/relationship/TargetFromStep.java index 5c296d9..cd1551c 100644 --- a/src/main/java/org/onap/aai/champ/model/fluent/relationship/TargetFromStep.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/relationship/TargetFromStep.java @@ -19,9 +19,9 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model.fluent.relationship; +package org.onap.aai.champcore.model.fluent.relationship; -import org.onap.aai.champ.model.ChampObject; +import org.onap.aai.champcore.model.ChampObject; public interface TargetFromStep { diff --git a/src/main/java/org/onap/aai/champ/model/fluent/relationship/TargetKeyStep.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/relationship/TargetKeyStep.java similarity index 95% rename from src/main/java/org/onap/aai/champ/model/fluent/relationship/TargetKeyStep.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/relationship/TargetKeyStep.java index 41e6922..a834edc 100644 --- a/src/main/java/org/onap/aai/champ/model/fluent/relationship/TargetKeyStep.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/relationship/TargetKeyStep.java @@ -19,7 +19,7 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model.fluent.relationship; +package org.onap.aai.champcore.model.fluent.relationship; public interface TargetKeyStep { diff --git a/src/main/java/org/onap/aai/champ/model/fluent/relationship/TargetStep.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/relationship/TargetStep.java similarity index 95% rename from src/main/java/org/onap/aai/champ/model/fluent/relationship/TargetStep.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/relationship/TargetStep.java index 25d38ed..372d298 100644 --- a/src/main/java/org/onap/aai/champ/model/fluent/relationship/TargetStep.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/relationship/TargetStep.java @@ -19,7 +19,7 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model.fluent.relationship; +package org.onap.aai.champcore.model.fluent.relationship; public interface TargetStep { public TargetTypeOrFromStep withTarget(); diff --git a/src/main/java/org/onap/aai/champ/model/fluent/relationship/TargetTypeOrFromStep.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/relationship/TargetTypeOrFromStep.java similarity index 95% rename from src/main/java/org/onap/aai/champ/model/fluent/relationship/TargetTypeOrFromStep.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/relationship/TargetTypeOrFromStep.java index 35a16c3..1631d88 100644 --- a/src/main/java/org/onap/aai/champ/model/fluent/relationship/TargetTypeOrFromStep.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/relationship/TargetTypeOrFromStep.java @@ -19,7 +19,7 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model.fluent.relationship; +package org.onap.aai.champcore.model.fluent.relationship; public interface TargetTypeOrFromStep extends TargetTypeStep, TargetFromStep { diff --git a/src/main/java/org/onap/aai/champ/model/fluent/relationship/TargetTypeStep.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/relationship/TargetTypeStep.java similarity index 95% rename from src/main/java/org/onap/aai/champ/model/fluent/relationship/TargetTypeStep.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/relationship/TargetTypeStep.java index 6de8915..32f4f3d 100644 --- a/src/main/java/org/onap/aai/champ/model/fluent/relationship/TargetTypeStep.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/relationship/TargetTypeStep.java @@ -19,7 +19,7 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model.fluent.relationship; +package org.onap.aai.champcore.model.fluent.relationship; public interface TargetTypeStep { diff --git a/src/main/java/org/onap/aai/champ/model/fluent/relationship/impl/ChampRelationshipKeyStepImpl.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/relationship/impl/ChampRelationshipKeyStepImpl.java similarity index 87% rename from src/main/java/org/onap/aai/champ/model/fluent/relationship/impl/ChampRelationshipKeyStepImpl.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/relationship/impl/ChampRelationshipKeyStepImpl.java index 0a69413..ebc194e 100644 --- a/src/main/java/org/onap/aai/champ/model/fluent/relationship/impl/ChampRelationshipKeyStepImpl.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/relationship/impl/ChampRelationshipKeyStepImpl.java @@ -19,11 +19,11 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model.fluent.relationship.impl; +package org.onap.aai.champcore.model.fluent.relationship.impl; -import org.onap.aai.champ.model.ChampRelationship; -import org.onap.aai.champ.model.fluent.KeyStep; -import org.onap.aai.champ.model.fluent.relationship.SourceStep; +import org.onap.aai.champcore.model.ChampRelationship; +import org.onap.aai.champcore.model.fluent.KeyStep; +import org.onap.aai.champcore.model.fluent.relationship.SourceStep; public final class ChampRelationshipKeyStepImpl implements KeyStep { diff --git a/src/main/java/org/onap/aai/champ/model/fluent/relationship/impl/CreateChampRelationshipableImpl.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/relationship/impl/CreateChampRelationshipableImpl.java similarity index 81% rename from src/main/java/org/onap/aai/champ/model/fluent/relationship/impl/CreateChampRelationshipableImpl.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/relationship/impl/CreateChampRelationshipableImpl.java index 6125dcd..caf1763 100644 --- a/src/main/java/org/onap/aai/champ/model/fluent/relationship/impl/CreateChampRelationshipableImpl.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/relationship/impl/CreateChampRelationshipableImpl.java @@ -19,13 +19,13 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model.fluent.relationship.impl; +package org.onap.aai.champcore.model.fluent.relationship.impl; -import org.onap.aai.champ.model.ChampRelationship; -import org.onap.aai.champ.model.fluent.KeyStep; -import org.onap.aai.champ.model.fluent.relationship.CreateChampRelationshipable; -import org.onap.aai.champ.model.fluent.relationship.RelationshipBuildOrPropertiesStep; -import org.onap.aai.champ.model.fluent.relationship.SourceStep; +import org.onap.aai.champcore.model.ChampRelationship; +import org.onap.aai.champcore.model.fluent.KeyStep; +import org.onap.aai.champcore.model.fluent.relationship.CreateChampRelationshipable; +import org.onap.aai.champcore.model.fluent.relationship.RelationshipBuildOrPropertiesStep; +import org.onap.aai.champcore.model.fluent.relationship.SourceStep; public final class CreateChampRelationshipableImpl implements CreateChampRelationshipable { diff --git a/src/main/java/org/onap/aai/champ/model/fluent/relationship/impl/RelationshipBuildOrPropertiesStepImpl.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/relationship/impl/RelationshipBuildOrPropertiesStepImpl.java similarity index 89% rename from src/main/java/org/onap/aai/champ/model/fluent/relationship/impl/RelationshipBuildOrPropertiesStepImpl.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/relationship/impl/RelationshipBuildOrPropertiesStepImpl.java index bb37e3b..74d0ffb 100644 --- a/src/main/java/org/onap/aai/champ/model/fluent/relationship/impl/RelationshipBuildOrPropertiesStepImpl.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/relationship/impl/RelationshipBuildOrPropertiesStepImpl.java @@ -19,12 +19,12 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model.fluent.relationship.impl; +package org.onap.aai.champcore.model.fluent.relationship.impl; import java.util.Map; -import org.onap.aai.champ.model.ChampRelationship; -import org.onap.aai.champ.model.fluent.relationship.RelationshipBuildOrPropertiesStep; +import org.onap.aai.champcore.model.ChampRelationship; +import org.onap.aai.champcore.model.fluent.relationship.RelationshipBuildOrPropertiesStep; public final class RelationshipBuildOrPropertiesStepImpl implements RelationshipBuildOrPropertiesStep { diff --git a/src/main/java/org/onap/aai/champ/model/fluent/relationship/impl/SourceBuildOrPropertiesStepImpl.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/relationship/impl/SourceBuildOrPropertiesStepImpl.java similarity index 85% rename from src/main/java/org/onap/aai/champ/model/fluent/relationship/impl/SourceBuildOrPropertiesStepImpl.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/relationship/impl/SourceBuildOrPropertiesStepImpl.java index c218472..70d1deb 100644 --- a/src/main/java/org/onap/aai/champ/model/fluent/relationship/impl/SourceBuildOrPropertiesStepImpl.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/relationship/impl/SourceBuildOrPropertiesStepImpl.java @@ -19,12 +19,12 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model.fluent.relationship.impl; +package org.onap.aai.champcore.model.fluent.relationship.impl; -import org.onap.aai.champ.model.ChampObject; -import org.onap.aai.champ.model.ChampRelationship; -import org.onap.aai.champ.model.fluent.relationship.SourceBuildOrPropertiesStep; -import org.onap.aai.champ.model.fluent.relationship.TargetStep; +import org.onap.aai.champcore.model.ChampObject; +import org.onap.aai.champcore.model.ChampRelationship; +import org.onap.aai.champcore.model.fluent.relationship.SourceBuildOrPropertiesStep; +import org.onap.aai.champcore.model.fluent.relationship.TargetStep; public final class SourceBuildOrPropertiesStepImpl implements SourceBuildOrPropertiesStep { diff --git a/src/main/java/org/onap/aai/champ/model/fluent/relationship/impl/SourceKeyStepImpl.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/relationship/impl/SourceKeyStepImpl.java similarity index 83% rename from src/main/java/org/onap/aai/champ/model/fluent/relationship/impl/SourceKeyStepImpl.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/relationship/impl/SourceKeyStepImpl.java index 7612b55..d1a6184 100644 --- a/src/main/java/org/onap/aai/champ/model/fluent/relationship/impl/SourceKeyStepImpl.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/relationship/impl/SourceKeyStepImpl.java @@ -19,13 +19,13 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model.fluent.relationship.impl; +package org.onap.aai.champcore.model.fluent.relationship.impl; -import org.onap.aai.champ.model.ChampObject; -import org.onap.aai.champ.model.ChampRelationship; -import org.onap.aai.champ.model.ChampObject.Builder; -import org.onap.aai.champ.model.fluent.relationship.SourceBuildOrPropertiesStep; -import org.onap.aai.champ.model.fluent.relationship.SourceKeyStep; +import org.onap.aai.champcore.model.ChampObject; +import org.onap.aai.champcore.model.ChampObject.Builder; +import org.onap.aai.champcore.model.ChampRelationship; +import org.onap.aai.champcore.model.fluent.relationship.SourceBuildOrPropertiesStep; +import org.onap.aai.champcore.model.fluent.relationship.SourceKeyStep; public final class SourceKeyStepImpl implements SourceKeyStep { diff --git a/src/main/java/org/onap/aai/champ/model/fluent/relationship/impl/SourceStepImpl.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/relationship/impl/SourceStepImpl.java similarity index 85% rename from src/main/java/org/onap/aai/champ/model/fluent/relationship/impl/SourceStepImpl.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/relationship/impl/SourceStepImpl.java index cc432d0..492264f 100644 --- a/src/main/java/org/onap/aai/champ/model/fluent/relationship/impl/SourceStepImpl.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/relationship/impl/SourceStepImpl.java @@ -19,11 +19,11 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model.fluent.relationship.impl; +package org.onap.aai.champcore.model.fluent.relationship.impl; -import org.onap.aai.champ.model.ChampRelationship; -import org.onap.aai.champ.model.fluent.relationship.SourceStep; -import org.onap.aai.champ.model.fluent.relationship.SourceTypeOrFromStep; +import org.onap.aai.champcore.model.ChampRelationship; +import org.onap.aai.champcore.model.fluent.relationship.SourceStep; +import org.onap.aai.champcore.model.fluent.relationship.SourceTypeOrFromStep; public final class SourceStepImpl implements SourceStep { diff --git a/src/main/java/org/onap/aai/champ/model/fluent/relationship/impl/SourceTypeOrFromStepImpl.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/relationship/impl/SourceTypeOrFromStepImpl.java similarity index 83% rename from src/main/java/org/onap/aai/champ/model/fluent/relationship/impl/SourceTypeOrFromStepImpl.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/relationship/impl/SourceTypeOrFromStepImpl.java index 9cc0ca2..6ba248f 100644 --- a/src/main/java/org/onap/aai/champ/model/fluent/relationship/impl/SourceTypeOrFromStepImpl.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/relationship/impl/SourceTypeOrFromStepImpl.java @@ -19,13 +19,13 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model.fluent.relationship.impl; +package org.onap.aai.champcore.model.fluent.relationship.impl; -import org.onap.aai.champ.model.ChampObject; -import org.onap.aai.champ.model.ChampRelationship; -import org.onap.aai.champ.model.fluent.relationship.SourceBuildOrPropertiesStep; -import org.onap.aai.champ.model.fluent.relationship.SourceKeyStep; -import org.onap.aai.champ.model.fluent.relationship.SourceTypeOrFromStep; +import org.onap.aai.champcore.model.ChampObject; +import org.onap.aai.champcore.model.ChampRelationship; +import org.onap.aai.champcore.model.fluent.relationship.SourceBuildOrPropertiesStep; +import org.onap.aai.champcore.model.fluent.relationship.SourceKeyStep; +import org.onap.aai.champcore.model.fluent.relationship.SourceTypeOrFromStep; public final class SourceTypeOrFromStepImpl implements SourceTypeOrFromStep { diff --git a/src/main/java/org/onap/aai/champ/model/fluent/relationship/impl/TargetBuildOrPropertiesStepImpl.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/relationship/impl/TargetBuildOrPropertiesStepImpl.java similarity index 87% rename from src/main/java/org/onap/aai/champ/model/fluent/relationship/impl/TargetBuildOrPropertiesStepImpl.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/relationship/impl/TargetBuildOrPropertiesStepImpl.java index 3b0d7a4..1407703 100644 --- a/src/main/java/org/onap/aai/champ/model/fluent/relationship/impl/TargetBuildOrPropertiesStepImpl.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/relationship/impl/TargetBuildOrPropertiesStepImpl.java @@ -19,12 +19,12 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model.fluent.relationship.impl; +package org.onap.aai.champcore.model.fluent.relationship.impl; -import org.onap.aai.champ.model.ChampObject; -import org.onap.aai.champ.model.ChampRelationship; -import org.onap.aai.champ.model.fluent.relationship.RelationshipBuildOrPropertiesStep; -import org.onap.aai.champ.model.fluent.relationship.TargetBuildOrPropertiesStep; +import org.onap.aai.champcore.model.ChampObject; +import org.onap.aai.champcore.model.ChampRelationship; +import org.onap.aai.champcore.model.fluent.relationship.RelationshipBuildOrPropertiesStep; +import org.onap.aai.champcore.model.fluent.relationship.TargetBuildOrPropertiesStep; public final class TargetBuildOrPropertiesStepImpl implements TargetBuildOrPropertiesStep { diff --git a/src/main/java/org/onap/aai/champ/model/fluent/relationship/impl/TargetKeyStepImpl.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/relationship/impl/TargetKeyStepImpl.java similarity index 86% rename from src/main/java/org/onap/aai/champ/model/fluent/relationship/impl/TargetKeyStepImpl.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/relationship/impl/TargetKeyStepImpl.java index 5400142..36e49a6 100644 --- a/src/main/java/org/onap/aai/champ/model/fluent/relationship/impl/TargetKeyStepImpl.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/relationship/impl/TargetKeyStepImpl.java @@ -19,12 +19,12 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model.fluent.relationship.impl; +package org.onap.aai.champcore.model.fluent.relationship.impl; -import org.onap.aai.champ.model.ChampObject; -import org.onap.aai.champ.model.ChampRelationship; -import org.onap.aai.champ.model.fluent.relationship.TargetBuildOrPropertiesStep; -import org.onap.aai.champ.model.fluent.relationship.TargetKeyStep; +import org.onap.aai.champcore.model.ChampObject; +import org.onap.aai.champcore.model.ChampRelationship; +import org.onap.aai.champcore.model.fluent.relationship.TargetBuildOrPropertiesStep; +import org.onap.aai.champcore.model.fluent.relationship.TargetKeyStep; public final class TargetKeyStepImpl implements TargetKeyStep { diff --git a/src/main/java/org/onap/aai/champ/model/fluent/relationship/impl/TargetStepImpl.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/relationship/impl/TargetStepImpl.java similarity index 84% rename from src/main/java/org/onap/aai/champ/model/fluent/relationship/impl/TargetStepImpl.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/relationship/impl/TargetStepImpl.java index 7b2b582..0721fca 100644 --- a/src/main/java/org/onap/aai/champ/model/fluent/relationship/impl/TargetStepImpl.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/relationship/impl/TargetStepImpl.java @@ -19,12 +19,12 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model.fluent.relationship.impl; +package org.onap.aai.champcore.model.fluent.relationship.impl; -import org.onap.aai.champ.model.ChampObject; -import org.onap.aai.champ.model.ChampRelationship; -import org.onap.aai.champ.model.fluent.relationship.TargetStep; -import org.onap.aai.champ.model.fluent.relationship.TargetTypeOrFromStep; +import org.onap.aai.champcore.model.ChampObject; +import org.onap.aai.champcore.model.ChampRelationship; +import org.onap.aai.champcore.model.fluent.relationship.TargetStep; +import org.onap.aai.champcore.model.fluent.relationship.TargetTypeOrFromStep; public final class TargetStepImpl implements TargetStep { diff --git a/src/main/java/org/onap/aai/champ/model/fluent/relationship/impl/TargetTypeOrFromStepImpl.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/relationship/impl/TargetTypeOrFromStepImpl.java similarity index 83% rename from src/main/java/org/onap/aai/champ/model/fluent/relationship/impl/TargetTypeOrFromStepImpl.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/relationship/impl/TargetTypeOrFromStepImpl.java index 0c813a5..22d1d1d 100644 --- a/src/main/java/org/onap/aai/champ/model/fluent/relationship/impl/TargetTypeOrFromStepImpl.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/relationship/impl/TargetTypeOrFromStepImpl.java @@ -19,13 +19,13 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model.fluent.relationship.impl; +package org.onap.aai.champcore.model.fluent.relationship.impl; -import org.onap.aai.champ.model.ChampObject; -import org.onap.aai.champ.model.ChampRelationship; -import org.onap.aai.champ.model.fluent.relationship.TargetBuildOrPropertiesStep; -import org.onap.aai.champ.model.fluent.relationship.TargetKeyStep; -import org.onap.aai.champ.model.fluent.relationship.TargetTypeOrFromStep; +import org.onap.aai.champcore.model.ChampObject; +import org.onap.aai.champcore.model.ChampRelationship; +import org.onap.aai.champcore.model.fluent.relationship.TargetBuildOrPropertiesStep; +import org.onap.aai.champcore.model.fluent.relationship.TargetKeyStep; +import org.onap.aai.champcore.model.fluent.relationship.TargetTypeOrFromStep; public final class TargetTypeOrFromStepImpl implements TargetTypeOrFromStep { diff --git a/src/main/java/org/onap/aai/champ/model/fluent/schema/CreateChampSchemable.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/schema/CreateChampSchemable.java similarity index 88% rename from src/main/java/org/onap/aai/champ/model/fluent/schema/CreateChampSchemable.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/schema/CreateChampSchemable.java index b0a8a2b..2e1b6d9 100644 --- a/src/main/java/org/onap/aai/champ/model/fluent/schema/CreateChampSchemable.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/schema/CreateChampSchemable.java @@ -19,13 +19,13 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model.fluent.schema; +package org.onap.aai.champcore.model.fluent.schema; -import org.onap.aai.champ.model.ChampSchema; -import org.onap.aai.champ.model.fluent.BuildStep; +import org.onap.aai.champcore.model.ChampSchema; +import org.onap.aai.champcore.model.fluent.BuildStep; public interface CreateChampSchemable extends BuildStep { public ObjectConstraintTypeStep withObjectConstraint(); public RelationshipConstraintTypeStep withRelationshipConstraint(); -} +} \ No newline at end of file diff --git a/src/main/java/org/onap/aai/champ/model/fluent/schema/ObjectConstraintBuildStep.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/schema/ObjectConstraintBuildStep.java similarity index 91% rename from src/main/java/org/onap/aai/champ/model/fluent/schema/ObjectConstraintBuildStep.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/schema/ObjectConstraintBuildStep.java index 57e677d..57daae8 100644 --- a/src/main/java/org/onap/aai/champ/model/fluent/schema/ObjectConstraintBuildStep.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/schema/ObjectConstraintBuildStep.java @@ -19,9 +19,9 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model.fluent.schema; +package org.onap.aai.champcore.model.fluent.schema; -import org.onap.aai.champ.model.fluent.BuildStep; +import org.onap.aai.champcore.model.fluent.BuildStep; public interface ObjectConstraintBuildStep extends BuildStep { diff --git a/src/main/java/org/onap/aai/champ/model/fluent/schema/ObjectConstraintFieldStep.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/schema/ObjectConstraintFieldStep.java similarity index 95% rename from src/main/java/org/onap/aai/champ/model/fluent/schema/ObjectConstraintFieldStep.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/schema/ObjectConstraintFieldStep.java index d3ac1b5..06fd723 100644 --- a/src/main/java/org/onap/aai/champ/model/fluent/schema/ObjectConstraintFieldStep.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/schema/ObjectConstraintFieldStep.java @@ -19,7 +19,7 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model.fluent.schema; +package org.onap.aai.champcore.model.fluent.schema; public interface ObjectConstraintFieldStep { diff --git a/src/main/java/org/onap/aai/champ/model/fluent/schema/ObjectConstraintFieldTypeStep.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/schema/ObjectConstraintFieldTypeStep.java similarity index 92% rename from src/main/java/org/onap/aai/champ/model/fluent/schema/ObjectConstraintFieldTypeStep.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/schema/ObjectConstraintFieldTypeStep.java index b4831ab..f17608e 100644 --- a/src/main/java/org/onap/aai/champ/model/fluent/schema/ObjectConstraintFieldTypeStep.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/schema/ObjectConstraintFieldTypeStep.java @@ -19,9 +19,9 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model.fluent.schema; +package org.onap.aai.champcore.model.fluent.schema; -import org.onap.aai.champ.model.ChampField; +import org.onap.aai.champcore.model.ChampField; public interface ObjectConstraintFieldTypeStep { diff --git a/src/main/java/org/onap/aai/champ/model/fluent/schema/ObjectConstraintPropertyStep.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/schema/ObjectConstraintPropertyStep.java similarity index 91% rename from src/main/java/org/onap/aai/champ/model/fluent/schema/ObjectConstraintPropertyStep.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/schema/ObjectConstraintPropertyStep.java index 90a100f..039e4d0 100644 --- a/src/main/java/org/onap/aai/champ/model/fluent/schema/ObjectConstraintPropertyStep.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/schema/ObjectConstraintPropertyStep.java @@ -19,9 +19,9 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model.fluent.schema; +package org.onap.aai.champcore.model.fluent.schema; -import org.onap.aai.champ.model.fluent.BuildStep; +import org.onap.aai.champcore.model.fluent.BuildStep; public interface ObjectConstraintPropertyStep extends BuildStep { diff --git a/src/main/java/org/onap/aai/champ/model/fluent/schema/ObjectConstraintRequiredOptionalStep.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/schema/ObjectConstraintRequiredOptionalStep.java similarity index 92% rename from src/main/java/org/onap/aai/champ/model/fluent/schema/ObjectConstraintRequiredOptionalStep.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/schema/ObjectConstraintRequiredOptionalStep.java index 1979770..03353b5 100644 --- a/src/main/java/org/onap/aai/champ/model/fluent/schema/ObjectConstraintRequiredOptionalStep.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/schema/ObjectConstraintRequiredOptionalStep.java @@ -19,9 +19,9 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model.fluent.schema; +package org.onap.aai.champcore.model.fluent.schema; -import org.onap.aai.champ.model.ChampCardinality; +import org.onap.aai.champcore.model.ChampCardinality; public interface ObjectConstraintRequiredOptionalStep { diff --git a/src/main/java/org/onap/aai/champ/model/fluent/schema/ObjectConstraintSubStep.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/schema/ObjectConstraintSubStep.java similarity index 95% rename from src/main/java/org/onap/aai/champ/model/fluent/schema/ObjectConstraintSubStep.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/schema/ObjectConstraintSubStep.java index 6fb1266..eb9973f 100644 --- a/src/main/java/org/onap/aai/champ/model/fluent/schema/ObjectConstraintSubStep.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/schema/ObjectConstraintSubStep.java @@ -19,7 +19,7 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model.fluent.schema; +package org.onap.aai.champcore.model.fluent.schema; public interface ObjectConstraintSubStep extends ObjectConstraintFieldTypeStep, ObjectConstraintRequiredOptionalStep{ diff --git a/src/main/java/org/onap/aai/champ/model/fluent/schema/ObjectConstraintTypeStep.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/schema/ObjectConstraintTypeStep.java similarity index 95% rename from src/main/java/org/onap/aai/champ/model/fluent/schema/ObjectConstraintTypeStep.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/schema/ObjectConstraintTypeStep.java index 5d8a80b..9ac2f1d 100644 --- a/src/main/java/org/onap/aai/champ/model/fluent/schema/ObjectConstraintTypeStep.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/schema/ObjectConstraintTypeStep.java @@ -19,9 +19,9 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model.fluent.schema; +package org.onap.aai.champcore.model.fluent.schema; public interface ObjectConstraintTypeStep { public ObjectConstraintPropertyStep onType(String type); -} +} \ No newline at end of file diff --git a/src/main/java/org/onap/aai/champ/model/fluent/schema/RelationshipConstraintBuildStep.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/schema/RelationshipConstraintBuildStep.java similarity index 91% rename from src/main/java/org/onap/aai/champ/model/fluent/schema/RelationshipConstraintBuildStep.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/schema/RelationshipConstraintBuildStep.java index a8a9513..669b829 100644 --- a/src/main/java/org/onap/aai/champ/model/fluent/schema/RelationshipConstraintBuildStep.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/schema/RelationshipConstraintBuildStep.java @@ -19,9 +19,9 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model.fluent.schema; +package org.onap.aai.champcore.model.fluent.schema; -import org.onap.aai.champ.model.fluent.BuildStep; +import org.onap.aai.champcore.model.fluent.BuildStep; public interface RelationshipConstraintBuildStep extends BuildStep { } diff --git a/src/main/java/org/onap/aai/champ/model/fluent/schema/RelationshipConstraintFieldStep.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/schema/RelationshipConstraintFieldStep.java similarity index 95% rename from src/main/java/org/onap/aai/champ/model/fluent/schema/RelationshipConstraintFieldStep.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/schema/RelationshipConstraintFieldStep.java index 3673e3f..17a4bc6 100644 --- a/src/main/java/org/onap/aai/champ/model/fluent/schema/RelationshipConstraintFieldStep.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/schema/RelationshipConstraintFieldStep.java @@ -19,7 +19,7 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model.fluent.schema; +package org.onap.aai.champcore.model.fluent.schema; public interface RelationshipConstraintFieldStep { diff --git a/src/main/java/org/onap/aai/champ/model/fluent/schema/RelationshipConstraintFieldTypeStep.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/schema/RelationshipConstraintFieldTypeStep.java similarity index 92% rename from src/main/java/org/onap/aai/champ/model/fluent/schema/RelationshipConstraintFieldTypeStep.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/schema/RelationshipConstraintFieldTypeStep.java index 59e969e..42b6edf 100644 --- a/src/main/java/org/onap/aai/champ/model/fluent/schema/RelationshipConstraintFieldTypeStep.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/schema/RelationshipConstraintFieldTypeStep.java @@ -19,9 +19,9 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model.fluent.schema; +package org.onap.aai.champcore.model.fluent.schema; -import org.onap.aai.champ.model.ChampField; +import org.onap.aai.champcore.model.ChampField; public interface RelationshipConstraintFieldTypeStep { diff --git a/src/main/java/org/onap/aai/champ/model/fluent/schema/RelationshipConstraintMultiplicityStep.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/schema/RelationshipConstraintMultiplicityStep.java similarity index 88% rename from src/main/java/org/onap/aai/champ/model/fluent/schema/RelationshipConstraintMultiplicityStep.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/schema/RelationshipConstraintMultiplicityStep.java index dd8e76e..9b09a6c 100644 --- a/src/main/java/org/onap/aai/champ/model/fluent/schema/RelationshipConstraintMultiplicityStep.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/schema/RelationshipConstraintMultiplicityStep.java @@ -19,10 +19,10 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model.fluent.schema; +package org.onap.aai.champcore.model.fluent.schema; -import org.onap.aai.champ.model.ChampConnectionMultiplicity; -import org.onap.aai.champ.model.fluent.BuildStep; +import org.onap.aai.champcore.model.ChampConnectionMultiplicity; +import org.onap.aai.champcore.model.fluent.BuildStep; public interface RelationshipConstraintMultiplicityStep extends BuildStep { diff --git a/src/main/java/org/onap/aai/champ/model/fluent/schema/RelationshipConstraintPropertyOptionalsStep.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/schema/RelationshipConstraintPropertyOptionalsStep.java similarity index 95% rename from src/main/java/org/onap/aai/champ/model/fluent/schema/RelationshipConstraintPropertyOptionalsStep.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/schema/RelationshipConstraintPropertyOptionalsStep.java index 3d46437..372c53f 100644 --- a/src/main/java/org/onap/aai/champ/model/fluent/schema/RelationshipConstraintPropertyOptionalsStep.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/schema/RelationshipConstraintPropertyOptionalsStep.java @@ -19,7 +19,7 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model.fluent.schema; +package org.onap.aai.champcore.model.fluent.schema; public interface RelationshipConstraintPropertyOptionalsStep extends RelationshipConstraintFieldTypeStep, RelationshipConstraintRequiredOptionalStep { } diff --git a/src/main/java/org/onap/aai/champ/model/fluent/schema/RelationshipConstraintRequiredOptionalStep.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/schema/RelationshipConstraintRequiredOptionalStep.java similarity index 95% rename from src/main/java/org/onap/aai/champ/model/fluent/schema/RelationshipConstraintRequiredOptionalStep.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/schema/RelationshipConstraintRequiredOptionalStep.java index 54cf61d..e8fb941 100644 --- a/src/main/java/org/onap/aai/champ/model/fluent/schema/RelationshipConstraintRequiredOptionalStep.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/schema/RelationshipConstraintRequiredOptionalStep.java @@ -19,7 +19,7 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model.fluent.schema; +package org.onap.aai.champcore.model.fluent.schema; public interface RelationshipConstraintRequiredOptionalStep { diff --git a/src/main/java/org/onap/aai/champ/model/fluent/schema/RelationshipConstraintSourceStep.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/schema/RelationshipConstraintSourceStep.java similarity index 95% rename from src/main/java/org/onap/aai/champ/model/fluent/schema/RelationshipConstraintSourceStep.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/schema/RelationshipConstraintSourceStep.java index 53a17bf..0e7f62f 100644 --- a/src/main/java/org/onap/aai/champ/model/fluent/schema/RelationshipConstraintSourceStep.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/schema/RelationshipConstraintSourceStep.java @@ -19,7 +19,7 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model.fluent.schema; +package org.onap.aai.champcore.model.fluent.schema; public interface RelationshipConstraintSourceStep { diff --git a/src/main/java/org/onap/aai/champ/model/fluent/schema/RelationshipConstraintSubStep.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/schema/RelationshipConstraintSubStep.java similarity index 92% rename from src/main/java/org/onap/aai/champ/model/fluent/schema/RelationshipConstraintSubStep.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/schema/RelationshipConstraintSubStep.java index 9de5fe7..f27b2a4 100644 --- a/src/main/java/org/onap/aai/champ/model/fluent/schema/RelationshipConstraintSubStep.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/schema/RelationshipConstraintSubStep.java @@ -19,9 +19,9 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model.fluent.schema; +package org.onap.aai.champcore.model.fluent.schema; -import org.onap.aai.champ.model.fluent.BuildStep; +import org.onap.aai.champcore.model.fluent.BuildStep; public interface RelationshipConstraintSubStep extends BuildStep { diff --git a/src/main/java/org/onap/aai/champ/model/fluent/schema/RelationshipConstraintTargetStep.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/schema/RelationshipConstraintTargetStep.java similarity index 95% rename from src/main/java/org/onap/aai/champ/model/fluent/schema/RelationshipConstraintTargetStep.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/schema/RelationshipConstraintTargetStep.java index 6b86b40..b9ec7a2 100644 --- a/src/main/java/org/onap/aai/champ/model/fluent/schema/RelationshipConstraintTargetStep.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/schema/RelationshipConstraintTargetStep.java @@ -19,7 +19,7 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model.fluent.schema; +package org.onap.aai.champcore.model.fluent.schema; public interface RelationshipConstraintTargetStep { diff --git a/src/main/java/org/onap/aai/champ/model/fluent/schema/RelationshipConstraintTypeStep.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/schema/RelationshipConstraintTypeStep.java similarity index 95% rename from src/main/java/org/onap/aai/champ/model/fluent/schema/RelationshipConstraintTypeStep.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/schema/RelationshipConstraintTypeStep.java index fc20d37..f7a7c3f 100644 --- a/src/main/java/org/onap/aai/champ/model/fluent/schema/RelationshipConstraintTypeStep.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/schema/RelationshipConstraintTypeStep.java @@ -19,7 +19,7 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model.fluent.schema; +package org.onap.aai.champcore.model.fluent.schema; public interface RelationshipConstraintTypeStep { diff --git a/src/main/java/org/onap/aai/champ/model/fluent/schema/impl/CreateChampSchemableImpl.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/schema/impl/CreateChampSchemableImpl.java similarity index 77% rename from src/main/java/org/onap/aai/champ/model/fluent/schema/impl/CreateChampSchemableImpl.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/schema/impl/CreateChampSchemableImpl.java index dd27842..217b55d 100644 --- a/src/main/java/org/onap/aai/champ/model/fluent/schema/impl/CreateChampSchemableImpl.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/schema/impl/CreateChampSchemableImpl.java @@ -19,16 +19,16 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model.fluent.schema.impl; +package org.onap.aai.champcore.model.fluent.schema.impl; -import org.onap.aai.champ.model.ChampObjectConstraint; -import org.onap.aai.champ.model.ChampRelationshipConstraint; -import org.onap.aai.champ.model.ChampSchema; -import org.onap.aai.champ.model.fluent.schema.CreateChampSchemable; -import org.onap.aai.champ.model.fluent.schema.ObjectConstraintPropertyStep; -import org.onap.aai.champ.model.fluent.schema.ObjectConstraintTypeStep; -import org.onap.aai.champ.model.fluent.schema.RelationshipConstraintSubStep; -import org.onap.aai.champ.model.fluent.schema.RelationshipConstraintTypeStep; +import org.onap.aai.champcore.model.ChampObjectConstraint; +import org.onap.aai.champcore.model.ChampRelationshipConstraint; +import org.onap.aai.champcore.model.ChampSchema; +import org.onap.aai.champcore.model.fluent.schema.CreateChampSchemable; +import org.onap.aai.champcore.model.fluent.schema.ObjectConstraintPropertyStep; +import org.onap.aai.champcore.model.fluent.schema.ObjectConstraintTypeStep; +import org.onap.aai.champcore.model.fluent.schema.RelationshipConstraintSubStep; +import org.onap.aai.champcore.model.fluent.schema.RelationshipConstraintTypeStep; public class CreateChampSchemableImpl implements CreateChampSchemable { diff --git a/src/main/java/org/onap/aai/champ/model/fluent/schema/impl/ObjectConstraintBuildStepImpl.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/schema/impl/ObjectConstraintBuildStepImpl.java similarity index 83% rename from src/main/java/org/onap/aai/champ/model/fluent/schema/impl/ObjectConstraintBuildStepImpl.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/schema/impl/ObjectConstraintBuildStepImpl.java index 7d595a9..8933555 100644 --- a/src/main/java/org/onap/aai/champ/model/fluent/schema/impl/ObjectConstraintBuildStepImpl.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/schema/impl/ObjectConstraintBuildStepImpl.java @@ -19,12 +19,12 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model.fluent.schema.impl; +package org.onap.aai.champcore.model.fluent.schema.impl; -import org.onap.aai.champ.model.ChampObjectConstraint; -import org.onap.aai.champ.model.ChampSchema; -import org.onap.aai.champ.model.fluent.schema.ObjectConstraintBuildStep; -import org.onap.aai.champ.model.fluent.schema.ObjectConstraintPropertyStep; +import org.onap.aai.champcore.model.ChampObjectConstraint; +import org.onap.aai.champcore.model.ChampSchema; +import org.onap.aai.champcore.model.fluent.schema.ObjectConstraintBuildStep; +import org.onap.aai.champcore.model.fluent.schema.ObjectConstraintPropertyStep; public class ObjectConstraintBuildStepImpl implements ObjectConstraintBuildStep { diff --git a/src/main/java/org/onap/aai/champ/model/fluent/schema/impl/ObjectConstraintFieldStepImpl.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/schema/impl/ObjectConstraintFieldStepImpl.java similarity index 81% rename from src/main/java/org/onap/aai/champ/model/fluent/schema/impl/ObjectConstraintFieldStepImpl.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/schema/impl/ObjectConstraintFieldStepImpl.java index 609f0e3..f149769 100644 --- a/src/main/java/org/onap/aai/champ/model/fluent/schema/impl/ObjectConstraintFieldStepImpl.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/schema/impl/ObjectConstraintFieldStepImpl.java @@ -19,13 +19,13 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model.fluent.schema.impl; +package org.onap.aai.champcore.model.fluent.schema.impl; -import org.onap.aai.champ.model.ChampField; -import org.onap.aai.champ.model.ChampObjectConstraint; -import org.onap.aai.champ.model.ChampSchema; -import org.onap.aai.champ.model.fluent.schema.ObjectConstraintFieldStep; -import org.onap.aai.champ.model.fluent.schema.ObjectConstraintSubStep; +import org.onap.aai.champcore.model.ChampField; +import org.onap.aai.champcore.model.ChampObjectConstraint; +import org.onap.aai.champcore.model.ChampSchema; +import org.onap.aai.champcore.model.fluent.schema.ObjectConstraintFieldStep; +import org.onap.aai.champcore.model.fluent.schema.ObjectConstraintSubStep; public class ObjectConstraintFieldStepImpl implements ObjectConstraintFieldStep { diff --git a/src/main/java/org/onap/aai/champ/model/fluent/schema/impl/ObjectConstraintPropertyStepImpl.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/schema/impl/ObjectConstraintPropertyStepImpl.java similarity index 81% rename from src/main/java/org/onap/aai/champ/model/fluent/schema/impl/ObjectConstraintPropertyStepImpl.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/schema/impl/ObjectConstraintPropertyStepImpl.java index 1e85e8b..c16d311 100644 --- a/src/main/java/org/onap/aai/champ/model/fluent/schema/impl/ObjectConstraintPropertyStepImpl.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/schema/impl/ObjectConstraintPropertyStepImpl.java @@ -19,13 +19,13 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model.fluent.schema.impl; +package org.onap.aai.champcore.model.fluent.schema.impl; -import org.onap.aai.champ.model.ChampObjectConstraint; -import org.onap.aai.champ.model.ChampSchema; -import org.onap.aai.champ.model.fluent.schema.CreateChampSchemable; -import org.onap.aai.champ.model.fluent.schema.ObjectConstraintFieldStep; -import org.onap.aai.champ.model.fluent.schema.ObjectConstraintPropertyStep; +import org.onap.aai.champcore.model.ChampObjectConstraint; +import org.onap.aai.champcore.model.ChampSchema; +import org.onap.aai.champcore.model.fluent.schema.CreateChampSchemable; +import org.onap.aai.champcore.model.fluent.schema.ObjectConstraintFieldStep; +import org.onap.aai.champcore.model.fluent.schema.ObjectConstraintPropertyStep; public class ObjectConstraintPropertyStepImpl implements ObjectConstraintPropertyStep { diff --git a/src/main/java/org/onap/aai/champ/model/fluent/schema/impl/ObjectConstraintSubStepImpl.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/schema/impl/ObjectConstraintSubStepImpl.java similarity index 84% rename from src/main/java/org/onap/aai/champ/model/fluent/schema/impl/ObjectConstraintSubStepImpl.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/schema/impl/ObjectConstraintSubStepImpl.java index 6564cf4..5cb13f3 100644 --- a/src/main/java/org/onap/aai/champ/model/fluent/schema/impl/ObjectConstraintSubStepImpl.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/schema/impl/ObjectConstraintSubStepImpl.java @@ -19,17 +19,17 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model.fluent.schema.impl; - -import org.onap.aai.champ.model.ChampCardinality; -import org.onap.aai.champ.model.ChampField; -import org.onap.aai.champ.model.ChampObjectConstraint; -import org.onap.aai.champ.model.ChampPropertyConstraint; -import org.onap.aai.champ.model.ChampSchema; -import org.onap.aai.champ.model.fluent.schema.ObjectConstraintBuildStep; -import org.onap.aai.champ.model.fluent.schema.ObjectConstraintPropertyStep; -import org.onap.aai.champ.model.fluent.schema.ObjectConstraintRequiredOptionalStep; -import org.onap.aai.champ.model.fluent.schema.ObjectConstraintSubStep; +package org.onap.aai.champcore.model.fluent.schema.impl; + +import org.onap.aai.champcore.model.ChampCardinality; +import org.onap.aai.champcore.model.ChampField; +import org.onap.aai.champcore.model.ChampObjectConstraint; +import org.onap.aai.champcore.model.ChampPropertyConstraint; +import org.onap.aai.champcore.model.ChampSchema; +import org.onap.aai.champcore.model.fluent.schema.ObjectConstraintBuildStep; +import org.onap.aai.champcore.model.fluent.schema.ObjectConstraintPropertyStep; +import org.onap.aai.champcore.model.fluent.schema.ObjectConstraintRequiredOptionalStep; +import org.onap.aai.champcore.model.fluent.schema.ObjectConstraintSubStep; public class ObjectConstraintSubStepImpl implements ObjectConstraintSubStep { diff --git a/src/main/java/org/onap/aai/champ/model/fluent/schema/impl/RelationshipConstraintBuildStepImpl.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/schema/impl/RelationshipConstraintBuildStepImpl.java similarity index 80% rename from src/main/java/org/onap/aai/champ/model/fluent/schema/impl/RelationshipConstraintBuildStepImpl.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/schema/impl/RelationshipConstraintBuildStepImpl.java index d20d596..906dd4e 100644 --- a/src/main/java/org/onap/aai/champ/model/fluent/schema/impl/RelationshipConstraintBuildStepImpl.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/schema/impl/RelationshipConstraintBuildStepImpl.java @@ -19,13 +19,13 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model.fluent.schema.impl; +package org.onap.aai.champcore.model.fluent.schema.impl; -import org.onap.aai.champ.model.ChampRelationshipConstraint; -import org.onap.aai.champ.model.ChampSchema; -import org.onap.aai.champ.model.ChampSchema.Builder; -import org.onap.aai.champ.model.fluent.schema.RelationshipConstraintBuildStep; -import org.onap.aai.champ.model.fluent.schema.RelationshipConstraintSubStep; +import org.onap.aai.champcore.model.ChampRelationshipConstraint; +import org.onap.aai.champcore.model.ChampSchema; +import org.onap.aai.champcore.model.ChampSchema.Builder; +import org.onap.aai.champcore.model.fluent.schema.RelationshipConstraintBuildStep; +import org.onap.aai.champcore.model.fluent.schema.RelationshipConstraintSubStep; public class RelationshipConstraintBuildStepImpl implements RelationshipConstraintBuildStep { diff --git a/src/main/java/org/onap/aai/champ/model/fluent/schema/impl/RelationshipConstraintPropertyOptionalsStepImpl.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/schema/impl/RelationshipConstraintPropertyOptionalsStepImpl.java similarity index 82% rename from src/main/java/org/onap/aai/champ/model/fluent/schema/impl/RelationshipConstraintPropertyOptionalsStepImpl.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/schema/impl/RelationshipConstraintPropertyOptionalsStepImpl.java index 7ef822d..ba39d61 100644 --- a/src/main/java/org/onap/aai/champ/model/fluent/schema/impl/RelationshipConstraintPropertyOptionalsStepImpl.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/schema/impl/RelationshipConstraintPropertyOptionalsStepImpl.java @@ -19,15 +19,15 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model.fluent.schema.impl; +package org.onap.aai.champcore.model.fluent.schema.impl; -import org.onap.aai.champ.model.ChampField; -import org.onap.aai.champ.model.ChampPropertyConstraint; -import org.onap.aai.champ.model.ChampRelationshipConstraint; -import org.onap.aai.champ.model.ChampSchema; -import org.onap.aai.champ.model.fluent.schema.RelationshipConstraintBuildStep; -import org.onap.aai.champ.model.fluent.schema.RelationshipConstraintPropertyOptionalsStep; -import org.onap.aai.champ.model.fluent.schema.RelationshipConstraintRequiredOptionalStep; +import org.onap.aai.champcore.model.ChampField; +import org.onap.aai.champcore.model.ChampPropertyConstraint; +import org.onap.aai.champcore.model.ChampRelationshipConstraint; +import org.onap.aai.champcore.model.ChampSchema; +import org.onap.aai.champcore.model.fluent.schema.RelationshipConstraintBuildStep; +import org.onap.aai.champcore.model.fluent.schema.RelationshipConstraintPropertyOptionalsStep; +import org.onap.aai.champcore.model.fluent.schema.RelationshipConstraintRequiredOptionalStep; public class RelationshipConstraintPropertyOptionalsStepImpl implements RelationshipConstraintPropertyOptionalsStep { diff --git a/src/main/java/org/onap/aai/champ/model/fluent/schema/impl/RelationshipConstraintRequiredOptionalStepImpl.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/schema/impl/RelationshipConstraintRequiredOptionalStepImpl.java similarity index 82% rename from src/main/java/org/onap/aai/champ/model/fluent/schema/impl/RelationshipConstraintRequiredOptionalStepImpl.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/schema/impl/RelationshipConstraintRequiredOptionalStepImpl.java index 58db7bb..8a760d1 100644 --- a/src/main/java/org/onap/aai/champ/model/fluent/schema/impl/RelationshipConstraintRequiredOptionalStepImpl.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/schema/impl/RelationshipConstraintRequiredOptionalStepImpl.java @@ -19,15 +19,15 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model.fluent.schema.impl; +package org.onap.aai.champcore.model.fluent.schema.impl; -import org.onap.aai.champ.model.ChampField; -import org.onap.aai.champ.model.ChampPropertyConstraint; -import org.onap.aai.champ.model.ChampRelationshipConstraint; -import org.onap.aai.champ.model.ChampSchema; -import org.onap.aai.champ.model.ChampSchema.Builder; -import org.onap.aai.champ.model.fluent.schema.RelationshipConstraintBuildStep; -import org.onap.aai.champ.model.fluent.schema.RelationshipConstraintRequiredOptionalStep; +import org.onap.aai.champcore.model.ChampField; +import org.onap.aai.champcore.model.ChampPropertyConstraint; +import org.onap.aai.champcore.model.ChampRelationshipConstraint; +import org.onap.aai.champcore.model.ChampSchema; +import org.onap.aai.champcore.model.ChampSchema.Builder; +import org.onap.aai.champcore.model.fluent.schema.RelationshipConstraintBuildStep; +import org.onap.aai.champcore.model.fluent.schema.RelationshipConstraintRequiredOptionalStep; public class RelationshipConstraintRequiredOptionalStepImpl implements RelationshipConstraintRequiredOptionalStep { diff --git a/src/main/java/org/onap/aai/champ/model/fluent/schema/impl/RelationshipConstraintSubStepImpl.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/schema/impl/RelationshipConstraintSubStepImpl.java similarity index 86% rename from src/main/java/org/onap/aai/champ/model/fluent/schema/impl/RelationshipConstraintSubStepImpl.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/schema/impl/RelationshipConstraintSubStepImpl.java index aca9c0c..6df9cff 100644 --- a/src/main/java/org/onap/aai/champ/model/fluent/schema/impl/RelationshipConstraintSubStepImpl.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/model/fluent/schema/impl/RelationshipConstraintSubStepImpl.java @@ -19,22 +19,22 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.model.fluent.schema.impl; - -import org.onap.aai.champ.model.ChampConnectionConstraint; -import org.onap.aai.champ.model.ChampConnectionMultiplicity; -import org.onap.aai.champ.model.ChampField; -import org.onap.aai.champ.model.ChampObject; -import org.onap.aai.champ.model.ChampRelationshipConstraint; -import org.onap.aai.champ.model.ChampSchema; -import org.onap.aai.champ.model.fluent.BuildStep; -import org.onap.aai.champ.model.fluent.schema.CreateChampSchemable; -import org.onap.aai.champ.model.fluent.schema.RelationshipConstraintFieldStep; -import org.onap.aai.champ.model.fluent.schema.RelationshipConstraintMultiplicityStep; -import org.onap.aai.champ.model.fluent.schema.RelationshipConstraintPropertyOptionalsStep; -import org.onap.aai.champ.model.fluent.schema.RelationshipConstraintSourceStep; -import org.onap.aai.champ.model.fluent.schema.RelationshipConstraintSubStep; -import org.onap.aai.champ.model.fluent.schema.RelationshipConstraintTargetStep; +package org.onap.aai.champcore.model.fluent.schema.impl; + +import org.onap.aai.champcore.model.ChampConnectionConstraint; +import org.onap.aai.champcore.model.ChampField; +import org.onap.aai.champcore.model.ChampObject; +import org.onap.aai.champcore.model.ChampRelationshipConstraint; +import org.onap.aai.champcore.model.ChampConnectionMultiplicity; +import org.onap.aai.champcore.model.ChampSchema; +import org.onap.aai.champcore.model.fluent.BuildStep; +import org.onap.aai.champcore.model.fluent.schema.CreateChampSchemable; +import org.onap.aai.champcore.model.fluent.schema.RelationshipConstraintFieldStep; +import org.onap.aai.champcore.model.fluent.schema.RelationshipConstraintMultiplicityStep; +import org.onap.aai.champcore.model.fluent.schema.RelationshipConstraintPropertyOptionalsStep; +import org.onap.aai.champcore.model.fluent.schema.RelationshipConstraintSourceStep; +import org.onap.aai.champcore.model.fluent.schema.RelationshipConstraintSubStep; +import org.onap.aai.champcore.model.fluent.schema.RelationshipConstraintTargetStep; public class RelationshipConstraintSubStepImpl implements RelationshipConstraintSubStep { diff --git a/src/main/java/org/onap/aai/champ/schema/AlwaysValidChampSchemaEnforcer.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/schema/AlwaysValidChampSchemaEnforcer.java similarity index 79% rename from src/main/java/org/onap/aai/champ/schema/AlwaysValidChampSchemaEnforcer.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/schema/AlwaysValidChampSchemaEnforcer.java index 292ff4c..6aa62a4 100644 --- a/src/main/java/org/onap/aai/champ/schema/AlwaysValidChampSchemaEnforcer.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/schema/AlwaysValidChampSchemaEnforcer.java @@ -19,14 +19,14 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.schema; +package org.onap.aai.champcore.schema; -import org.onap.aai.champ.model.ChampObject; -import org.onap.aai.champ.model.ChampObjectConstraint; -import org.onap.aai.champ.model.ChampPartition; -import org.onap.aai.champ.model.ChampRelationship; -import org.onap.aai.champ.model.ChampRelationshipConstraint; -import org.onap.aai.champ.model.ChampSchema; +import org.onap.aai.champcore.model.ChampObject; +import org.onap.aai.champcore.model.ChampObjectConstraint; +import org.onap.aai.champcore.model.ChampPartition; +import org.onap.aai.champcore.model.ChampRelationship; +import org.onap.aai.champcore.model.ChampRelationshipConstraint; +import org.onap.aai.champcore.model.ChampSchema; public final class AlwaysValidChampSchemaEnforcer implements ChampSchemaEnforcer { diff --git a/src/main/java/org/onap/aai/champ/schema/ChampSchemaEnforcer.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/schema/ChampSchemaEnforcer.java similarity index 77% rename from src/main/java/org/onap/aai/champ/schema/ChampSchemaEnforcer.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/schema/ChampSchemaEnforcer.java index 978b2a0..5113aa2 100644 --- a/src/main/java/org/onap/aai/champ/schema/ChampSchemaEnforcer.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/schema/ChampSchemaEnforcer.java @@ -19,15 +19,15 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.schema; +package org.onap.aai.champcore.schema; -import org.onap.aai.champ.exceptions.ChampSchemaViolationException; -import org.onap.aai.champ.model.ChampObject; -import org.onap.aai.champ.model.ChampObjectConstraint; -import org.onap.aai.champ.model.ChampPartition; -import org.onap.aai.champ.model.ChampRelationship; -import org.onap.aai.champ.model.ChampRelationshipConstraint; -import org.onap.aai.champ.model.ChampSchema; +import org.onap.aai.champcore.exceptions.ChampSchemaViolationException; +import org.onap.aai.champcore.model.ChampObject; +import org.onap.aai.champcore.model.ChampObjectConstraint; +import org.onap.aai.champcore.model.ChampPartition; +import org.onap.aai.champcore.model.ChampRelationship; +import org.onap.aai.champcore.model.ChampRelationshipConstraint; +import org.onap.aai.champcore.model.ChampSchema; public interface ChampSchemaEnforcer { diff --git a/src/main/java/org/onap/aai/champ/schema/DefaultChampSchemaEnforcer.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/schema/DefaultChampSchemaEnforcer.java similarity index 90% rename from src/main/java/org/onap/aai/champ/schema/DefaultChampSchemaEnforcer.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/schema/DefaultChampSchemaEnforcer.java index 8ea93e5..308244e 100644 --- a/src/main/java/org/onap/aai/champ/schema/DefaultChampSchemaEnforcer.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/schema/DefaultChampSchemaEnforcer.java @@ -19,7 +19,7 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.schema; +package org.onap.aai.champcore.schema; import java.util.HashMap; import java.util.List; @@ -28,16 +28,16 @@ import java.util.Optional; import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; -import org.onap.aai.champ.exceptions.ChampSchemaViolationException; -import org.onap.aai.champ.model.ChampConnectionConstraint; -import org.onap.aai.champ.model.ChampField; -import org.onap.aai.champ.model.ChampObject; -import org.onap.aai.champ.model.ChampObjectConstraint; -import org.onap.aai.champ.model.ChampPartition; -import org.onap.aai.champ.model.ChampPropertyConstraint; -import org.onap.aai.champ.model.ChampRelationship; -import org.onap.aai.champ.model.ChampRelationshipConstraint; -import org.onap.aai.champ.model.ChampSchema; +import org.onap.aai.champcore.exceptions.ChampSchemaViolationException; +import org.onap.aai.champcore.model.ChampConnectionConstraint; +import org.onap.aai.champcore.model.ChampField; +import org.onap.aai.champcore.model.ChampObject; +import org.onap.aai.champcore.model.ChampObjectConstraint; +import org.onap.aai.champcore.model.ChampPartition; +import org.onap.aai.champcore.model.ChampPropertyConstraint; +import org.onap.aai.champcore.model.ChampRelationship; +import org.onap.aai.champcore.model.ChampRelationshipConstraint; +import org.onap.aai.champcore.model.ChampSchema; public final class DefaultChampSchemaEnforcer implements ChampSchemaEnforcer { @@ -141,4 +141,4 @@ public final class DefaultChampSchemaEnforcer implements ChampSchemaEnforcer { } } } -} +} \ No newline at end of file diff --git a/src/main/java/org/onap/aai/champ/transform/Champformer.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/transform/Champformer.java similarity index 86% rename from src/main/java/org/onap/aai/champ/transform/Champformer.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/transform/Champformer.java index da2fce7..e07ac14 100644 --- a/src/main/java/org/onap/aai/champ/transform/Champformer.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/transform/Champformer.java @@ -19,11 +19,11 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.transform; +package org.onap.aai.champcore.transform; -import org.onap.aai.champ.exceptions.ChampUnmarshallingException; -import org.onap.aai.champ.model.ChampObject; -import org.onap.aai.champ.model.ChampRelationship; +import org.onap.aai.champcore.exceptions.ChampUnmarshallingException; +import org.onap.aai.champcore.model.ChampObject; +import org.onap.aai.champcore.model.ChampRelationship; public interface Champformer { public V marshallObject(ChampObject object) throws ChampUnmarshallingException; diff --git a/src/main/java/org/onap/aai/champ/transform/TinkerpopChampformer.java b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/transform/TinkerpopChampformer.java similarity index 90% rename from src/main/java/org/onap/aai/champ/transform/TinkerpopChampformer.java rename to champ-lib/champ-core/src/main/java/org/onap/aai/champcore/transform/TinkerpopChampformer.java index e24f2dc..8552cc6 100644 --- a/src/main/java/org/onap/aai/champ/transform/TinkerpopChampformer.java +++ b/champ-lib/champ-core/src/main/java/org/onap/aai/champcore/transform/TinkerpopChampformer.java @@ -19,7 +19,7 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.transform; +package org.onap.aai.champcore.transform; import java.util.Iterator; @@ -27,11 +27,11 @@ import org.apache.tinkerpop.gremlin.structure.Edge; import org.apache.tinkerpop.gremlin.structure.Property; import org.apache.tinkerpop.gremlin.structure.Vertex; import org.apache.tinkerpop.gremlin.structure.VertexProperty; -import org.onap.aai.champ.exceptions.ChampUnmarshallingException; -import org.onap.aai.champ.model.ChampObject; -import org.onap.aai.champ.model.ChampRelationship; -import org.onap.aai.champ.model.fluent.object.ObjectBuildOrPropertiesStep; -import org.onap.aai.champ.model.fluent.relationship.RelationshipBuildOrPropertiesStep; +import org.onap.aai.champcore.exceptions.ChampUnmarshallingException; +import org.onap.aai.champcore.model.ChampObject; +import org.onap.aai.champcore.model.ChampRelationship; +import org.onap.aai.champcore.model.fluent.object.ObjectBuildOrPropertiesStep; +import org.onap.aai.champcore.model.fluent.relationship.RelationshipBuildOrPropertiesStep; public final class TinkerpopChampformer implements Champformer { diff --git a/champ-lib/champ-core/src/test/java/org/onap/aai/champcore/concurrency/ConcurrencyTest.java b/champ-lib/champ-core/src/test/java/org/onap/aai/champcore/concurrency/ConcurrencyTest.java new file mode 100644 index 0000000..9f9be02 --- /dev/null +++ b/champ-lib/champ-core/src/test/java/org/onap/aai/champcore/concurrency/ConcurrencyTest.java @@ -0,0 +1,74 @@ +/** + * ============LICENSE_START========================================== + * org.onap.aai + * =================================================================== + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 Amdocs + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END============================================ + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.champcore.concurrency; + +import org.junit.Test; +import org.onap.aai.champcore.ChampAPI; +import org.onap.aai.champcore.ChampGraph; +import org.onap.aai.champcore.core.ChampObjectTest; +import org.onap.aai.champcore.core.ChampRelationshipTest; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; + +public class ConcurrencyTest { + + private static final Logger LOGGER = LoggerFactory.getLogger(ConcurrencyTest.class); + + @Test + public void runInMemoryConcurrentTest() { + runConcurrentTest("IN_MEMORY"); + } + + public void runConcurrentTest(String apiType) { + final ChampAPI api = ChampAPI.Factory.newInstance(apiType); + runConcurrencyTest(api); + api.shutdown(); + } + + private void runConcurrencyTest(ChampAPI api) { + final int numThreads = 10; + final ExecutorService es = Executors.newFixedThreadPool(numThreads); + + for (int i = 0; i < numThreads * 2; i++) { + es.submit(new Runnable() { + @Override + public void run() { + final ChampGraph graph = api.getGraph(ConcurrencyTest.class.getSimpleName()); + ChampObjectTest.testChampObjectCrud(graph); + ChampRelationshipTest.testChampRelationshipCrud(graph); + } + }); + } + + try { + es.shutdown(); + es.awaitTermination(60, TimeUnit.SECONDS); + } catch (InterruptedException e) { + LOGGER.warn("Interrupted while waiting for concurrency test to finish", e); + return; + } + } +} diff --git a/champ-lib/champ-core/src/test/java/org/onap/aai/champcore/core/BaseChampAPITest.java b/champ-lib/champ-core/src/test/java/org/onap/aai/champcore/core/BaseChampAPITest.java new file mode 100644 index 0000000..229e920 --- /dev/null +++ b/champ-lib/champ-core/src/test/java/org/onap/aai/champcore/core/BaseChampAPITest.java @@ -0,0 +1,34 @@ +/** + * ============LICENSE_START========================================== + * org.onap.aai + * =================================================================== + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 Amdocs + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END============================================ + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.champcore.core; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class BaseChampAPITest { + + protected static final Logger LOGGER = LoggerFactory.getLogger(BaseChampAPITest.class); + + protected static void cleanUp(String graphName) { + LOGGER.warn("cleanUp is disabled for unit tests - you can enable it by commenting out the code below this log message, please don't commit it though"); + } +} diff --git a/champ-lib/champ-core/src/test/java/org/onap/aai/champcore/core/ChampAPITest.java b/champ-lib/champ-core/src/test/java/org/onap/aai/champcore/core/ChampAPITest.java new file mode 100644 index 0000000..f033b30 --- /dev/null +++ b/champ-lib/champ-core/src/test/java/org/onap/aai/champcore/core/ChampAPITest.java @@ -0,0 +1,242 @@ +/** + * ============LICENSE_START========================================== + * org.onap.aai + * =================================================================== + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 Amdocs + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END============================================ + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.champcore.core; + +import org.junit.Test; +import org.onap.aai.champcore.ChampAPI; +import org.onap.aai.champcore.ChampGraph; +import org.onap.aai.champcore.graph.impl.ChampAPIImpl; +import org.onap.aai.champcore.graph.impl.InMemoryChampGraphImpl; +import org.onap.aai.champcore.model.ChampObjectConstraint; +import org.onap.aai.champcore.model.ChampRelationshipConstraint; + +import static org.junit.Assert.assertTrue; + +import java.util.Optional; + +public class ChampAPITest { + + @Test + public void testChampAPIMemoryInstantiation() { + testChampAPIInstantiation(new ChampAPIImpl("IN_MEMORY"), "IN_MEMORY"); + } + + public void testChampAPIInstantiation(ChampAPI api, String expectedType) { + assertTrue(api.getType() == expectedType); + + api.getGraph("foo"); + api.shutdown(); + + try { + api.getGraph("foo"); + throw new AssertionError("Able to call getGraph(String name) after shutdown()"); + } catch (IllegalStateException e) { + //Expected + } + } + + @Test + public void testChampMemoryGraphInstantiation() throws Exception + { + testChampGraphInstantiation(new InMemoryChampGraphImpl.Builder().build()); + } + + public void testChampGraphInstantiation(ChampGraph graph) throws Exception { + + graph.shutdown(); + + try { + graph.deleteObject(null, Optional.empty()); + throw new AssertionError("Able to call API method after shutdown was initiated"); + } catch (IllegalStateException e) { + //Expected + } + + try { + graph.deleteObjectIndex(null); + throw new AssertionError("Able to call API method after shutdown was initiated"); + } catch (IllegalStateException e) { + //Expected + } + + try { + graph.deletePartition(null, Optional.empty()); + throw new AssertionError("Able to call API method after shutdown was initiated"); + } catch (IllegalStateException e) { + //Expected + } + + try { + graph.deleteRelationship(null, Optional.empty()); + throw new AssertionError("Able to call API method after shutdown was initiated"); + } catch (IllegalStateException e) { + //Expected + } + + try { + graph.deleteRelationshipIndex(null); + throw new AssertionError("Able to call API method after shutdown was initiated"); + } catch (IllegalStateException e) { + //Expected + } + + try { + graph.deleteSchema(); + throw new AssertionError("Able to call API method after shutdown was initiated"); + } catch (IllegalStateException e) { + //Expected + } + + try { + graph.queryObjects(null, Optional.empty()); + throw new AssertionError("Able to call API method after shutdown was initiated"); + } catch (IllegalStateException e) { + //Expected + } + + try { + graph.queryRelationships(null, Optional.empty()); + throw new AssertionError("Able to call API method after shutdown was initiated"); + } catch (IllegalStateException e) { + //Expected + } + + try { + graph.retrieveObject(null, Optional.empty()); + throw new AssertionError("Able to call API method after shutdown was initiated"); + } catch (IllegalStateException e) { + //Expected + } + + try { + graph.retrieveObjectIndex(null); + throw new AssertionError("Able to call API method after shutdown was initiated"); + } catch (IllegalStateException e) { + //Expected + } + + try { + graph.retrieveObjectIndices(); + throw new AssertionError("Able to call API method after shutdown was initiated"); + } catch (IllegalStateException e) { + //Expected + } + + try { + graph.retrieveRelationship(null, Optional.empty()); + throw new AssertionError("Able to call API method after shutdown was initiated"); + } catch (IllegalStateException e) { + //Expected + } + + try { + graph.retrieveRelationshipIndex(null); + throw new AssertionError("Able to call API method after shutdown was initiated"); + } catch (IllegalStateException e) { + //Expected + } + + try { + graph.retrieveRelationshipIndices(); + throw new AssertionError("Able to call API method after shutdown was initiated"); + } catch (IllegalStateException e) { + //Expected + } + + try { + graph.retrieveRelationships(null, Optional.empty()); + throw new AssertionError("Able to call API method after shutdown was initiated"); + } catch (IllegalStateException e) { + //Expected + } + + try { + graph.retrieveSchema(); + throw new AssertionError("Able to call API method after shutdown was initiated"); + } catch (IllegalStateException e) { + //Expected + } + + try { + graph.storeObject(null, Optional.empty()); + throw new AssertionError("Able to call API method after shutdown was initiated"); + } catch (IllegalStateException e) { + //Expected + } + + try { + graph.storeObjectIndex(null); + throw new AssertionError("Able to call API method after shutdown was initiated"); + } catch (IllegalStateException e) { + //Expected + } + + try { + graph.storePartition(null, Optional.empty()); + throw new AssertionError("Able to call API method after shutdown was initiated"); + } catch (IllegalStateException e) { + //Expected + } + + try { + graph.storeRelationship(null, Optional.empty()); + throw new AssertionError("Able to call API method after shutdown was initiated"); + } catch (IllegalStateException e) { + //Expected + } + + try { + graph.storeRelationshipIndex(null); + throw new AssertionError("Able to call API method after shutdown was initiated"); + } catch (IllegalStateException e) { + //Expected + } + + try { + graph.storeSchema(null); + throw new AssertionError("Able to call API method after shutdown was initiated"); + } catch (IllegalStateException e) { + //Expected + } + + try { + graph.updateSchema(new ChampObjectConstraint.Builder("").build()); + throw new AssertionError("Able to call API method after shutdown was initiated"); + } catch (IllegalStateException e) { + //Expected + } + + try { + graph.updateSchema(new ChampRelationshipConstraint.Builder("").build()); + throw new AssertionError("Able to call API method after shutdown was initiated"); + } catch (IllegalStateException e) { + //Expected + } + + try { + graph.shutdown(); + throw new AssertionError("Able to call API method after shutdown was initiated"); + } catch (IllegalStateException e) { + //Expected + } + } +} diff --git a/src/test/java/org/onap/aai/champ/core/ChampElementTest.java b/champ-lib/champ-core/src/test/java/org/onap/aai/champcore/core/ChampElementTest.java similarity index 91% rename from src/test/java/org/onap/aai/champ/core/ChampElementTest.java rename to champ-lib/champ-core/src/test/java/org/onap/aai/champcore/core/ChampElementTest.java index af19cc2..9eb5dfe 100644 --- a/src/test/java/org/onap/aai/champ/core/ChampElementTest.java +++ b/champ-lib/champ-core/src/test/java/org/onap/aai/champcore/core/ChampElementTest.java @@ -19,14 +19,14 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.core; +package org.onap.aai.champcore.core; import static org.junit.Assert.assertTrue; import org.junit.Test; -import org.onap.aai.champ.model.ChampElement; -import org.onap.aai.champ.model.ChampObject; -import org.onap.aai.champ.model.ChampRelationship; +import org.onap.aai.champcore.model.ChampElement; +import org.onap.aai.champcore.model.ChampObject; +import org.onap.aai.champcore.model.ChampRelationship; public class ChampElementTest { diff --git a/src/test/java/org/onap/aai/champ/core/ChampFieldTest.java b/champ-lib/champ-core/src/test/java/org/onap/aai/champcore/core/ChampFieldTest.java similarity index 95% rename from src/test/java/org/onap/aai/champ/core/ChampFieldTest.java rename to champ-lib/champ-core/src/test/java/org/onap/aai/champcore/core/ChampFieldTest.java index 0b4dbb8..4975739 100644 --- a/src/test/java/org/onap/aai/champ/core/ChampFieldTest.java +++ b/champ-lib/champ-core/src/test/java/org/onap/aai/champcore/core/ChampFieldTest.java @@ -19,12 +19,12 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.core; +package org.onap.aai.champcore.core; import static org.junit.Assert.assertTrue; import org.junit.Test; -import org.onap.aai.champ.model.ChampField; +import org.onap.aai.champcore.model.ChampField; public class ChampFieldTest { diff --git a/src/test/java/org/onap/aai/champ/core/ChampObjectIndexTest.java b/champ-lib/champ-core/src/test/java/org/onap/aai/champcore/core/ChampObjectIndexTest.java similarity index 91% rename from src/test/java/org/onap/aai/champ/core/ChampObjectIndexTest.java rename to champ-lib/champ-core/src/test/java/org/onap/aai/champcore/core/ChampObjectIndexTest.java index a11b67b..bb2c65e 100644 --- a/src/test/java/org/onap/aai/champ/core/ChampObjectIndexTest.java +++ b/champ-lib/champ-core/src/test/java/org/onap/aai/champcore/core/ChampObjectIndexTest.java @@ -19,7 +19,7 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.core; +package org.onap.aai.champcore.core; import static org.junit.Assert.assertTrue; @@ -29,35 +29,27 @@ import java.util.stream.Collectors; import java.util.stream.Stream; import org.junit.Test; -import org.onap.aai.champ.ChampAPI; -import org.onap.aai.champ.ChampGraph; -import org.onap.aai.champ.exceptions.ChampIndexNotExistsException; -import org.onap.aai.champ.model.ChampObjectIndex; +import org.onap.aai.champcore.ChampAPI; +import org.onap.aai.champcore.ChampGraph; +import org.onap.aai.champcore.exceptions.ChampIndexNotExistsException; +import org.onap.aai.champcore.model.ChampObjectIndex; public class ChampObjectIndexTest extends BaseChampAPITest { @Test - public void runTest() { - for (ChampGraph.Type apiType : ChampGraph.Type.values()) { + public void runTestMemory() { + runTest("IN_MEMORY"); + } + + public void runTest(String apiType) { final ChampAPI api = ChampAPI.Factory.newInstance(apiType); final String graphName = api.getClass().getSimpleName(); - switch (apiType) { - case IN_MEMORY: - break; - case TITAN: - cleanUp(graphName); - break; - default: - break; - } - ChampObjectIndexTest.testChampObjectIndexCrud(api.getGraph(graphName)); api.shutdown(); - } } - private static void testChampObjectIndexCrud(ChampGraph graph) { + public static void testChampObjectIndexCrud(ChampGraph graph) { final ChampObjectIndex objectIndex = ChampObjectIndex.create() .ofName("fooObjectIndex") diff --git a/champ-lib/champ-core/src/test/java/org/onap/aai/champcore/core/ChampObjectTest.java b/champ-lib/champ-core/src/test/java/org/onap/aai/champcore/core/ChampObjectTest.java new file mode 100644 index 0000000..3ef8f8c --- /dev/null +++ b/champ-lib/champ-core/src/test/java/org/onap/aai/champcore/core/ChampObjectTest.java @@ -0,0 +1,359 @@ +/** + * ============LICENSE_START========================================== + * org.onap.aai + * =================================================================== + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 Amdocs + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END============================================ + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.champcore.core; + +import org.junit.Test; +import org.onap.aai.champcore.ChampAPI; +import org.onap.aai.champcore.ChampCapabilities; +import org.onap.aai.champcore.ChampGraph; +import org.onap.aai.champcore.ChampTransaction; +import org.onap.aai.champcore.core.ChampRelationshipTest.TestTransaction; +import org.onap.aai.champcore.exceptions.ChampMarshallingException; +import org.onap.aai.champcore.exceptions.ChampObjectNotExistsException; +import org.onap.aai.champcore.exceptions.ChampSchemaViolationException; +import org.onap.aai.champcore.exceptions.ChampTransactionException; +import org.onap.aai.champcore.exceptions.ChampUnmarshallingException; +import org.onap.aai.champcore.graph.impl.InMemoryChampGraphImpl; +import org.onap.aai.champcore.model.ChampCardinality; +import org.onap.aai.champcore.model.ChampField; +import org.onap.aai.champcore.model.ChampObject; +import org.onap.aai.champcore.model.ChampSchema; + +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static org.junit.Assert.assertTrue; + +public class ChampObjectTest extends BaseChampAPITest { + + @Test + public void testHashCode() { + final ChampObject foo1 = ChampObject.create() + .ofType("foo") + .withoutKey() + .withProperty("property", "value") + .withProperty("prop", 1) + .build(); + + final ChampObject foo2 = ChampObject.create() + .ofType("foo") + .withoutKey() + .withProperty("property", "value") + .withProperty("prop", 1) + .build(); + + final ChampObject foo1Copy = ChampObject.create() + .from(foo1) + .withoutKey() + .build(); + + final ChampObject foo2Copy = ChampObject.create() + .from(foo2) + .withoutKey() + .build(); + + assertTrue(foo1.hashCode() == foo2.hashCode()); + assertTrue(foo1.hashCode() == foo1.hashCode()); + assertTrue(foo2.hashCode() == foo2.hashCode()); + assertTrue(foo1.hashCode() == foo1Copy.hashCode()); + assertTrue(foo2.hashCode() == foo2Copy.hashCode()); + + assertTrue(Collections.singleton(foo1).contains(foo1)); + assertTrue(Collections.singleton(foo1).contains(foo1Copy)); + } + + @Test + public void runInMemoryTest() { + runTest("IN_MEMORY"); + } + + public void runTest(String apiType) { + final String graphName = ChampObjectTest.class.getSimpleName(); + + final ChampAPI api = ChampAPI.Factory.newInstance(apiType); + ChampObjectTest.testChampObjectCrud(api.getGraph(graphName)); + testChampObjectReservedProperties(api.getGraph(graphName)); + api.shutdown(); + } + + public static void testChampObjectCrud(ChampGraph graph) { + + // Create a dummy object... + final ChampObject bookooObject = ChampObject.create() + .ofType("foo") + .withoutKey() + .withProperty("property1", "value1") + .withProperty("integer", 1) + .withProperty("long", 1L) + .withProperty("double", 1.2) + .withProperty("float", 2.3F) + .withProperty("string", "foo") + .withProperty("boolean", true) + .withProperty("list", Collections.singletonList("list")) + .withProperty("set", Collections.singleton("set")) + .build(); + + final ChampObject storedBookooObject; + + try { + + // Create a schema for the graph. + graph.storeSchema(ChampSchema.create() + .withObjectConstraint() + .onType("foo") + .withPropertyConstraint() + .onField("list") + .ofType(ChampField.Type.STRING) + .cardinality(ChampCardinality.LIST) + .optional() + .build() + .withPropertyConstraint() + .onField("set") + .ofType(ChampField.Type.STRING) + .cardinality(ChampCardinality.SET) + .optional() + .build() + .build() + .build()); + + + + // Store the object in the graph. + storedBookooObject = graph.storeObject(bookooObject, Optional.empty()); + + // Check that the object we got back from the store call matches what we sent. + assertTrue(storedBookooObject.getProperty("property1").get().equals("value1")); + assertTrue(storedBookooObject.getProperty("integer").get().equals(1)); + assertTrue(storedBookooObject.getProperty("long").get().equals(1L)); + assertTrue(storedBookooObject.getProperty("double").get().equals(1.2)); + assertTrue(storedBookooObject.getProperty("float").get().equals(2.3F)); + assertTrue(storedBookooObject.getProperty("string").get().equals("foo")); + assertTrue(storedBookooObject.getProperty("boolean").get().equals(true)); + assertTrue(storedBookooObject.getProperty("list").get().equals(Collections.singletonList("list"))); + assertTrue(storedBookooObject.getProperty("set").get().equals(Collections.singleton("set"))); + + final Optional retrievedBookooObject = graph.retrieveObject(storedBookooObject.getKey().get(), Optional.empty()); + + final Stream emptyStream = graph.queryObjects(new HashMap() {{ + put(ChampObject.ReservedPropertyKeys.CHAMP_OBJECT_TYPE.toString(), "foo"); + put("long", 2L); + }}, Optional.empty()); + + assertTrue(emptyStream.limit(1).count() == 0); + + final Stream oneStream = graph.queryObjects(new HashMap() {{ + put(ChampObject.ReservedPropertyKeys.CHAMP_OBJECT_TYPE.toString(), "foo"); + put("long", 1L); + }}, Optional.empty()); + final List oneObject = oneStream.limit(2).collect(Collectors.toList()); + assertTrue(oneObject.size() == 1); + assertTrue(oneObject.get(0).equals(storedBookooObject)); + + final List queryByKey = graph.queryObjects(Collections.singletonMap(ChampObject.ReservedPropertyKeys.CHAMP_OBJECT_KEY.toString(), storedBookooObject.getKey().get()), Optional.empty()) + .limit(2) + .collect(Collectors.toList()); + + assertTrue(queryByKey.size() == 1); + assertTrue(queryByKey.get(0).equals(storedBookooObject)); + + if (!retrievedBookooObject.isPresent()) { + throw new AssertionError("Failed to retrieve stored object " + bookooObject); + } + if (!storedBookooObject.equals(retrievedBookooObject.get())) { + throw new AssertionError("Retrieved object does not equal stored object"); + } + + final ChampObject updatedBookoo = graph.storeObject(ChampObject.create() + .from(storedBookooObject) + .withKey(storedBookooObject.getKey().get()) + .withProperty("long", 2L) + .build(), Optional.empty()); + + final Optional retrievedUpdBookooObject = graph.retrieveObject(updatedBookoo.getKey().get(), Optional.empty()); + + assertTrue(updatedBookoo.getProperty("property1").get().equals("value1")); + assertTrue(updatedBookoo.getProperty("integer").get().equals(1)); + assertTrue(updatedBookoo.getProperty("long").get().equals(2L)); + assertTrue(updatedBookoo.getProperty("double").get().equals(1.2)); + assertTrue(updatedBookoo.getProperty("float").get().equals(2.3F)); + assertTrue(updatedBookoo.getProperty("string").get().equals("foo")); + assertTrue(updatedBookoo.getProperty("boolean").get().equals(true)); + assertTrue(updatedBookoo.getProperty("list").get().equals(Collections.singletonList("list"))); + assertTrue(updatedBookoo.getProperty("set").get().equals(Collections.singleton("set"))); + + if (!retrievedUpdBookooObject.isPresent()) { + throw new AssertionError("Failed to retrieve stored object " + bookooObject); + } + if (!updatedBookoo.equals(retrievedUpdBookooObject.get())) { + throw new AssertionError("Retrieved object does not equal stored object"); + } + + //validate the replaceObject method + final ChampObject replacedBookoo = graph.replaceObject(ChampObject.create() + .ofType("foo") + .withKey(storedBookooObject.getKey().get()) + .withProperty("property1", "value2") + .withProperty("list", Collections.singletonList("list")) + .withProperty("set", Collections.singleton("set")) + .build(), Optional.empty()); + + final Optional retrievedReplacedBookooObject = graph.retrieveObject(replacedBookoo.getKey().get(), Optional.empty()); + + assertTrue(replacedBookoo.getProperties().size() == 3); + assertTrue(replacedBookoo.getProperty("property1").get().equals("value2")); + assertTrue(replacedBookoo.getProperty("list").get().equals(Collections.singletonList("list"))); + assertTrue(replacedBookoo.getProperty("set").get().equals(Collections.singleton("set"))); + + + if (!retrievedReplacedBookooObject.isPresent()) { + throw new AssertionError("Failed to retrieve stored object " + replacedBookoo); + } + if (!replacedBookoo.equals(retrievedReplacedBookooObject.get())) { + throw new AssertionError("Retrieved object does not equal stored object"); + } + + graph.deleteObject(storedBookooObject.getKey().get(), Optional.empty()); + + if (graph.retrieveObject(storedBookooObject.getKey().get(), Optional.empty()).isPresent()) { + throw new AssertionError("Object not successfully deleted"); + } + + assertTrue(graph.queryObjects(Collections.emptyMap(), Optional.empty()).count() == 0); + assertTrue(graph.queryRelationships(Collections.emptyMap(), Optional.empty()).count() == 0); + + + } catch (ChampSchemaViolationException e) { + throw new AssertionError("Schema mismatch while storing object", e); + } catch (ChampMarshallingException e) { + throw new AssertionError("Marshalling exception while storing object", e); + } catch (ChampUnmarshallingException e) { + throw new AssertionError("Unmarshalling exception while retrieving object", e); + } catch (ChampObjectNotExistsException e) { + throw new AssertionError("Missing object on delete/update", e); + } catch (ChampTransactionException e) { + throw new AssertionError("Transaction exception occurred", e); + } + + try { + graph.deleteObject(storedBookooObject.getKey().get(), Optional.empty()); + throw new AssertionError("Delete succeeded when it should have failed"); + } catch (ChampObjectNotExistsException e) { + //Expected + } catch (ChampTransactionException e) { + throw new AssertionError("Transaction exception occurred", e); + } + + try { + graph.storeObject(ChampObject.create() + .ofType("foo") + .withKey("non-existent object key") + .build(), Optional.empty()); + throw new AssertionError("Expected ChampObjectNotExistsException but object was successfully stored"); + } catch (ChampObjectNotExistsException e) { + //Expected + } catch (ChampMarshallingException e) { + throw new AssertionError(e); + } catch (ChampSchemaViolationException e) { + throw new AssertionError(e); + } catch (ChampTransactionException e) { + throw new AssertionError(e); + } + + try { + // validate the replaceObject method when Object key is not passed + graph.replaceObject( + ChampObject.create().ofType("foo").withoutKey().withProperty("property1", "value2").build(), Optional.empty()); + } catch (ChampObjectNotExistsException e) { + // Expected + } catch (ChampMarshallingException e) { + throw new AssertionError(e); + } catch (ChampSchemaViolationException e) { + throw new AssertionError(e); + } catch (ChampTransactionException e) { + throw new AssertionError(e); + } + } + + public void testChampObjectReservedProperties(ChampGraph graph) { + + for (ChampObject.ReservedPropertyKeys key : ChampObject.ReservedPropertyKeys.values()) { + try { + ChampObject.create() + .ofType(ChampObject.ReservedTypes.ANY.toString()) + .withoutKey() + .withProperty(key.toString(), "") + .build(); + throw new AssertionError("Allowed reserved property key to be used during object creation"); + } catch (IllegalArgumentException e) { + //Expected + } + } + } + + @Test + public void testFluentObjectCreation() { + final Object value1 = new Object(); + final String value2 = "value2"; + final float value3 = 0.0f; + + final ChampObject champObject1 = ChampObject.create() + .ofType("foo") + .withoutKey() + .withProperty("key1", value1) + .withProperty("key2", value2) + .withProperty("key3", value3) + .build(); + + assertTrue(champObject1.getKey().equals(Optional.empty())); + assertTrue(champObject1.getKey().isPresent() == false); + assertTrue(champObject1.getType().equals("foo")); + assertTrue(champObject1.getProperty("key1").get() instanceof Object); + assertTrue(champObject1.getProperty("key1").get().equals(value1)); + assertTrue(champObject1.getProperty("key2").get() instanceof String); + assertTrue(champObject1.getProperty("key2").get().equals(value2)); + assertTrue(champObject1.getProperty("key3").get() instanceof Float); + assertTrue(champObject1.getProperty("key3").get().equals(value3)); + + final ChampObject champObject2 = ChampObject.create() + .ofType("foo") + .withKey(1) + .withProperty("key1", value1) + .withProperty("key2", value2) + .withProperty("key3", value3) + .build(); + + assertTrue(champObject2.getType().equals("foo")); + assertTrue(champObject2.getKey().isPresent() == true); + assertTrue(champObject2.getKey().get() instanceof Integer); + assertTrue(champObject2.getKey().get().equals(1)); + assertTrue(champObject2.getProperty("key1").get() instanceof Object); + assertTrue(champObject2.getProperty("key1").get().equals(value1)); + assertTrue(champObject2.getProperty("key2").get() instanceof String); + assertTrue(champObject2.getProperty("key2").get().equals(value2)); + assertTrue(champObject2.getProperty("key3").get() instanceof Float); + assertTrue(champObject2.getProperty("key3").get().equals(value3)); + } +} diff --git a/champ-lib/champ-core/src/test/java/org/onap/aai/champcore/core/ChampPartitionTest.java b/champ-lib/champ-core/src/test/java/org/onap/aai/champcore/core/ChampPartitionTest.java new file mode 100644 index 0000000..1aafebe --- /dev/null +++ b/champ-lib/champ-core/src/test/java/org/onap/aai/champcore/core/ChampPartitionTest.java @@ -0,0 +1,226 @@ +/** + * ============LICENSE_START========================================== + * org.onap.aai + * =================================================================== + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 Amdocs + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END============================================ + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.champcore.core; + +import org.junit.Test; +import org.onap.aai.champcore.ChampAPI; +import org.onap.aai.champcore.ChampGraph; +import org.onap.aai.champcore.exceptions.*; +import org.onap.aai.champcore.model.ChampObject; +import org.onap.aai.champcore.model.ChampPartition; +import org.onap.aai.champcore.model.ChampRelationship; + +import java.util.Collections; +import java.util.Optional; + +import static org.junit.Assert.assertTrue; + +public class ChampPartitionTest extends org.onap.aai.champcore.core.BaseChampAPITest { + + @Test + public void runInMemoryTests() { + runTests("IN_MEMORY"); + } + + public void runTests(String apiType) { + final ChampAPI api = ChampAPI.Factory.newInstance(apiType); + final String graphName = ChampPartitionTest.class.getSimpleName(); + + ChampPartitionTest.testChampPartitionCrud(api.getGraph(graphName)); + api.shutdown(); + } + + @Test + public void testPartitionToString() throws Exception { + final ChampObject foo = ChampObject.create() + .ofType("foo") + .withoutKey() + .build(); + final ChampObject bar = ChampObject.create() + .ofType("bar") + .withoutKey() + .build(); + final ChampRelationship baz = ChampRelationship.create() + .ofType("baz") + .withoutKey() + .withSource() + .from(foo) + .build() + .withTarget() + .from(bar) + .build() + .build(); + + final ChampPartition partition = ChampPartition.create() + .withObject(foo) + .withObject(bar) + .withRelationship(baz) + .build(); + + assertTrue(partition.toString().equals("{objects: [{key: , type: bar, properties: {}},{key: , type: foo, properties: {}}], relationships: [{key: , type: baz, source: {key: , type: foo, properties: {}}, target: {key: , type: bar, properties: {}}, properties: {}}]}")); + //"{objects: [{key: \"\", type: \"foo\", properties: {}}], relationships: []}" + //"{objects: [{key: , type: foo, properties: {}}], relationships: []}" + //throw new Exception(partition.toString()); + } + + @Test + public void testHashCode() { + + final ChampObject foo = ChampObject.create() + .ofType("foo") + .withoutKey() + .build(); + final ChampObject bar = ChampObject.create() + .ofType("bar") + .withoutKey() + .build(); + final ChampRelationship baz = ChampRelationship.create() + .ofType("baz") + .withoutKey() + .withSource() + .from(foo) + .build() + .withTarget() + .from(bar) + .build() + .build(); + + final ChampPartition partition = ChampPartition.create() + .withObject(foo) + .withObject(bar) + .withRelationship(baz) + .build(); + + assertTrue(partition.getChampObjects().contains(foo)); + assertTrue(partition.getChampObjects().contains(bar)); + assertTrue(partition.getChampRelationships().contains(baz)); + } + + @Test + public void testBuilder() { + final ChampObject foo = new ChampObject.Builder("foo").build(); + final ChampObject bar = new ChampObject.Builder("bar").build(); + final ChampRelationship uses = new ChampRelationship.Builder(foo, bar, "uses") + .build(); + final ChampPartition a = new ChampPartition.Builder() + .object(foo) + .objects(Collections.singleton(bar)) + .relationship(uses) + .relationships(Collections.singleton(uses)) + .build(); + assertTrue(a.getChampObjects().size() == 2); + assertTrue(a.getChampObjects().contains(foo)); + assertTrue(a.getChampObjects().contains(bar)); + + assertTrue(a.getChampRelationships().size() == 1); + assertTrue(a.getChampRelationships().contains(uses)); + } + + public static void testChampPartitionCrud(ChampGraph graph) { + + final ChampObject foo = ChampObject.create() + .ofType("foo") + .withoutKey() + .withProperty("prop1", "value1") + .build(); + final ChampObject bar = ChampObject.create() + .ofType("bar") + .withoutKey() + .withProperty("prop2", "value2") + .build(); + + final ChampRelationship baz = ChampRelationship.create() + .ofType("baz") + .withoutKey() + .withSource() + .from(foo) + .build() + .withTarget() + .from(bar) + .build() + .withProperty("prop3", "value3") + .build(); + + final ChampPartition partition = ChampPartition.create() + .withObject(foo) + .withObject(bar) + .withRelationship(baz) + .build(); + + assertTrue(partition.getIncidentRelationships(foo).contains(baz)); + assertTrue(partition.getIncidentRelationships(bar).contains(baz)); + assertTrue(partition.getIncidentRelationshipsByType(foo).get("baz").contains(baz)); + + try { + final ChampPartition storedPartition = graph.storePartition(partition); + + ChampPartitionTest.retrievePartitionElements(graph, storedPartition, true); + + graph.deletePartition(storedPartition); + + ChampPartitionTest.retrievePartitionElements(graph, storedPartition, false); + + } catch (ChampMarshallingException e) { + throw new AssertionError(e); + } catch (ChampObjectNotExistsException e) { + throw new AssertionError(e); + } catch (ChampSchemaViolationException e) { + throw new AssertionError(e); + } catch (ChampRelationshipNotExistsException e) { + throw new AssertionError(e); + } catch (ChampTransactionException e) { + throw new AssertionError(e); + } + } + + private static void retrievePartitionElements(ChampGraph graph, ChampPartition partition, boolean expectFound) { + for (ChampObject object : partition.getChampObjects()) { + try { + final Optional retrievedObject = graph.retrieveObject(object.getKey().get()); + + if (!expectFound && retrievedObject.isPresent()) { + throw new AssertionError("Expected object to not be found, but it was found"); + } + if (expectFound && !retrievedObject.isPresent()) { + throw new AssertionError("Expected object to be found, but it was not found"); + } + } catch (ChampUnmarshallingException | ChampTransactionException e) { + throw new AssertionError(e); + } + } + + for (ChampRelationship relationship : partition.getChampRelationships()) { + try { + final Optional retrievedRelationship = graph.retrieveRelationship(relationship.getKey().get()); + + if (!expectFound && retrievedRelationship.isPresent()) { + throw new AssertionError("Expected relationship to not be found, but it was found"); + } + if (expectFound && !retrievedRelationship.isPresent()) { + throw new AssertionError("Expected relationship to be found, but it was not found"); + } + } catch (ChampUnmarshallingException | ChampTransactionException e) { + throw new AssertionError(e); + } + } + } +} diff --git a/src/test/java/org/onap/aai/champ/core/ChampPropertyConstraintTest.java b/champ-lib/champ-core/src/test/java/org/onap/aai/champcore/core/ChampPropertyConstraintTest.java similarity index 91% rename from src/test/java/org/onap/aai/champ/core/ChampPropertyConstraintTest.java rename to champ-lib/champ-core/src/test/java/org/onap/aai/champcore/core/ChampPropertyConstraintTest.java index 5dfbadf..c82e055 100644 --- a/src/test/java/org/onap/aai/champ/core/ChampPropertyConstraintTest.java +++ b/champ-lib/champ-core/src/test/java/org/onap/aai/champcore/core/ChampPropertyConstraintTest.java @@ -19,14 +19,14 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.core; +package org.onap.aai.champcore.core; import static org.junit.Assert.assertTrue; import org.junit.Test; -import org.onap.aai.champ.model.ChampCardinality; -import org.onap.aai.champ.model.ChampField; -import org.onap.aai.champ.model.ChampPropertyConstraint; +import org.onap.aai.champcore.model.ChampCardinality; +import org.onap.aai.champcore.model.ChampField; +import org.onap.aai.champcore.model.ChampPropertyConstraint; public class ChampPropertyConstraintTest { diff --git a/champ-lib/champ-core/src/test/java/org/onap/aai/champcore/core/ChampRelationshipIndexTest.java b/champ-lib/champ-core/src/test/java/org/onap/aai/champcore/core/ChampRelationshipIndexTest.java new file mode 100644 index 0000000..5b8c715 --- /dev/null +++ b/champ-lib/champ-core/src/test/java/org/onap/aai/champcore/core/ChampRelationshipIndexTest.java @@ -0,0 +1,179 @@ +/** + * ============LICENSE_START========================================== + * org.onap.aai + * =================================================================== + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 Amdocs + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END============================================ + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.champcore.core; + +import org.junit.Test; +import org.onap.aai.champcore.ChampAPI; +import org.onap.aai.champcore.ChampGraph; +import org.onap.aai.champcore.exceptions.*; +import org.onap.aai.champcore.model.ChampField; +import org.onap.aai.champcore.model.ChampRelationship; +import org.onap.aai.champcore.model.ChampRelationshipIndex; + +import java.util.Collection; +import java.util.Optional; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static org.junit.Assert.assertTrue; + +public class ChampRelationshipIndexTest extends BaseChampAPITest { + + @Test + public void runInMemoryTest() { + runTest("IN_MEMORY"); + } + + public void runTest(String apiType) { + final String graphName = ChampRelationshipIndexTest.class.getSimpleName(); + + final ChampAPI api = ChampAPI.Factory.newInstance(apiType); + testChampRelationshipIndexCrud(api.getGraph(graphName)); + api.shutdown(); + } + + public void testChampRelationshipIndexCrud(ChampGraph graph) { + + final ChampField relationshipField = new ChampField.Builder("propertyName").build(); + final ChampRelationshipIndex relationshipIndex = new ChampRelationshipIndex.Builder("fooEdgeIndex", "foo", relationshipField).build(); + + //Test on an empty graph + testChampRelationshipIndexStorage(graph, relationshipIndex); + testChampRelationshipIndexDelete(graph, relationshipIndex); + + //Test with existing data in graph + try { + graph.storeRelationship(ChampRelationship.create() + .ofType("uses") + .withoutKey() + .withSource() + .ofType("foo") + .withoutKey() + .build() + .withTarget() + .ofType("bar") + .withoutKey() + .build() + .build() + , Optional.empty()); + testChampRelationshipIndexStorage(graph, relationshipIndex); + testChampRelationshipIndexDelete(graph, relationshipIndex); + } catch (ChampMarshallingException e) { + throw new AssertionError(e); + } catch (ChampSchemaViolationException e) { + throw new AssertionError(e); + } catch (ChampObjectNotExistsException e) { + throw new AssertionError(e); + } catch (ChampRelationshipNotExistsException e) { + throw new AssertionError(e); + } catch (ChampUnmarshallingException e) { + throw new AssertionError(e); + } catch (ChampTransactionException e) { + throw new AssertionError(e); + } + } + + private void testChampRelationshipIndexDelete(ChampGraph graph, ChampRelationshipIndex relationshipIndex) { + + if (!graph.capabilities().canDeleteRelationshipIndices()) { + try { + graph.deleteRelationshipIndex("someindex"); + throw new AssertionError("Graph claims it doesn't support relationship index delete, but it failed to throw UnsupportedOperationException"); + } catch (UnsupportedOperationException e) { + //Expected + } catch (ChampIndexNotExistsException e) { + throw new AssertionError("Graph claims it doesn't support relationship index delete, but it failed to throw UnsupportedOperationException"); + } + } else { + try { + graph.deleteRelationshipIndex(relationshipIndex.getName()); + + final Optional retrieveRelationshipIndex = graph.retrieveRelationshipIndex(relationshipIndex.getName()); + + if (retrieveRelationshipIndex.isPresent()) { + throw new AssertionError("Retrieve relationship index after deleting it"); + } + + final Stream relationshipIndices = graph.retrieveRelationshipIndices(); + final Collection allRelationshipIndices = relationshipIndices.collect(Collectors.toList()); + + if (allRelationshipIndices.contains(relationshipIndex)) { + throw new AssertionError("Retrieve all relationship indices contains previously deleted index"); + } + if (allRelationshipIndices.size() != 0) { + throw new AssertionError("Wrong number of relationship indices returned by retrieve all indices"); + } + } catch (ChampIndexNotExistsException e) { + throw new AssertionError(e); + } + + try { + graph.deleteRelationshipIndex(relationshipIndex.getName()); + throw new AssertionError("Failed to throw exception on non-existent object index"); + } catch (ChampIndexNotExistsException e) { + //Expected + } + } + } + + private void testChampRelationshipIndexStorage(ChampGraph graph, ChampRelationshipIndex relationshipIndex) { + + graph.storeRelationshipIndex(relationshipIndex); + graph.storeRelationshipIndex(relationshipIndex); //Test storing duplicate relationship index + + assertTrue(!graph.retrieveObjectIndex(relationshipIndex.getName()).isPresent()); //Make sure this wasn't stored as an object index + + final Optional retrieveRelationshipIndex = graph.retrieveRelationshipIndex(relationshipIndex.getName()); + + if (!retrieveRelationshipIndex.isPresent()) { + throw new AssertionError("Failed to retrieve relationship index after storing it"); + } + if (!relationshipIndex.equals(retrieveRelationshipIndex.get())) { + throw new AssertionError("Non-equal relationship index returned from API after storing it"); + } + + final Stream relationshipIndices = graph.retrieveRelationshipIndices(); + final Collection allRelationshipIndices = relationshipIndices.collect(Collectors.toList()); + + if (!allRelationshipIndices.contains(relationshipIndex)) { + throw new AssertionError("Retrieve all relationship indices did not return previously stored relationship index"); + } + if (allRelationshipIndices.size() != 1) { + throw new AssertionError("Wrong number of relationship indices returned by retrieve all indices"); + } + + assertTrue(!graph.retrieveRelationshipIndex("nonExistentIndexName").isPresent()); + } + + @Test + public void testFluentRelationshipIndexCreation() { + final ChampRelationshipIndex relationshipIndex = ChampRelationshipIndex.create() + .ofName("fooNameIndex") + .onType("foo") + .forField("name") + .build(); + + assertTrue(relationshipIndex.getName().equals("fooNameIndex")); + assertTrue(relationshipIndex.getType().equals("foo")); + assertTrue(relationshipIndex.getField().getName().equals("name")); + } +} diff --git a/champ-lib/champ-core/src/test/java/org/onap/aai/champcore/core/ChampRelationshipTest.java b/champ-lib/champ-core/src/test/java/org/onap/aai/champcore/core/ChampRelationshipTest.java new file mode 100644 index 0000000..3f17466 --- /dev/null +++ b/champ-lib/champ-core/src/test/java/org/onap/aai/champcore/core/ChampRelationshipTest.java @@ -0,0 +1,310 @@ +/** + * ============LICENSE_START========================================== + * org.onap.aai + * =================================================================== + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 Amdocs + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END============================================ + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.champcore.core; + +import org.junit.Test; +import org.onap.aai.champcore.ChampAPI; +import org.onap.aai.champcore.ChampGraph; +import org.onap.aai.champcore.ChampTransaction; +import org.onap.aai.champcore.exceptions.*; +import org.onap.aai.champcore.model.ChampObject; +import org.onap.aai.champcore.model.ChampRelationship; +import org.onap.aai.champcore.model.ChampRelationship.ReservedPropertyKeys; +import org.onap.aai.champcore.model.ChampRelationship.ReservedTypes; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.Optional; +import java.util.stream.Collectors; + +import static org.junit.Assert.assertTrue; + +public class ChampRelationshipTest extends BaseChampAPITest { + + @Test + public void runInMemoryTest() { + runTest("IN_MEMORY"); + } + + public void runTest(String apiType) { + final String graphName = ChampRelationshipTest.class.getSimpleName(); + + final ChampAPI api = ChampAPI.Factory.newInstance(apiType); + ChampRelationshipTest.testChampRelationshipCrud(api.getGraph(graphName)); + api.shutdown(); + } + + public static void testChampRelationshipCrud(ChampGraph graph) { + final ChampObject source = ChampObject.create() + .ofType("foo") + .withoutKey() + .withProperty("property1", "value1") + .build(); + + final ChampObject target = ChampObject.create() + .ofType("foo") + .withoutKey() + .build(); + + try { + ChampTransaction tx = ChampRelationshipTest.getTransaction(); + + final ChampObject storedSource = graph.storeObject(source, Optional.of(tx)); + final ChampObject storedTarget = graph.storeObject(target, Optional.of(tx)); + + final ChampRelationship relationship = new ChampRelationship.Builder(storedSource, storedTarget, "relationship") + .property("property-1", "value-1") + .property("property-2", 3) + .build(); + + final ChampRelationship storedRelationship = graph.storeRelationship(relationship, Optional.of(tx)); + final Optional retrievedRelationship = graph.retrieveRelationship(storedRelationship.getKey().get(), Optional.of(tx)); + + if (!retrievedRelationship.isPresent()) { + throw new AssertionError("Failed to retrieve stored relationship " + storedRelationship); + } + if (!storedRelationship.equals(retrievedRelationship.get())) { + throw new AssertionError("Retrieved relationship does not equal stored object"); + } + + assertTrue(retrievedRelationship.get().getProperty("property-1").get().equals("value-1")); + assertTrue(retrievedRelationship.get().getProperty("property-2").get().equals(3)); + + if (!graph.retrieveRelationships(storedRelationship.getSource(), Optional.of(tx)).collect(Collectors.toList()).contains(storedRelationship)) { + throw new AssertionError("Failed to retrieve relationships for source object"); + } + + final ChampRelationship updatedRelationship = ChampRelationship.create() + .from(retrievedRelationship.get()) + .withKey(retrievedRelationship.get().getKey().get()) + .withProperty("property-2", 4) + .build(); + + final ChampRelationship storedUpdRel = graph.storeRelationship(updatedRelationship, Optional.of(tx)); + final Optional retrievedUpdRel = graph.retrieveRelationship(storedUpdRel.getKey().get(), Optional.of(tx)); + + assertTrue(retrievedUpdRel.isPresent()); + assertTrue(retrievedUpdRel.get().equals(storedUpdRel)); + assertTrue(retrievedUpdRel.get().getProperty("property-1").get().equals("value-1")); + assertTrue(retrievedUpdRel.get().getProperty("property-2").get().equals(4)); + + + // validate the replaceRelationship method + final ChampRelationship replacedRelationship = new ChampRelationship.Builder(storedSource, storedTarget, "relationship") + .key(retrievedRelationship.get().getKey().get()) + .property("property-2", 4) + .build(); + + final ChampRelationship replacedRel = graph.replaceRelationship(replacedRelationship, Optional.of(tx)); + final Optional retrievedReplacedRel = graph + .retrieveRelationship(replacedRel.getKey().get(), Optional.of(tx)); + + assertTrue(replacedRel.getProperties().size() == 1); + assertTrue(replacedRel.getProperty("property-2").get().equals(4)); + + assertTrue(retrievedReplacedRel.get().getProperties().size() == 1); + assertTrue(retrievedReplacedRel.get().getProperty("property-2").get().equals(4)); + + if (!retrievedReplacedRel.isPresent()) { + throw new AssertionError("Failed to retrieve stored relationship " + replacedRel); + } + if (!replacedRel.equals(retrievedReplacedRel.get())) { + throw new AssertionError("Retrieved relationship does not equal stored object"); + } + + + graph.deleteRelationship(retrievedRelationship.get(), Optional.of(tx)); + + if (graph.retrieveRelationship(relationship.getKey(), Optional.of(tx)).isPresent()) { + throw new AssertionError("Relationship not successfully deleted"); + } + + try { + graph.deleteRelationship(retrievedRelationship.get(), Optional.of(tx)); + throw new AssertionError("Failed to throw exception for missing relationship"); + } catch (ChampRelationshipNotExistsException e) { + //Expected + } + + Map queryParams = new HashMap<>(); + queryParams.put(ChampObject.ReservedPropertyKeys.CHAMP_OBJECT_TYPE.toString(), "blah"); + graph.queryRelationships(queryParams); + + queryParams = new HashMap<>(); + queryParams.put(ChampRelationship.ReservedPropertyKeys.CHAMP_RELATIONSHIP_TYPE.toString(), "blah"); + graph.queryRelationships(queryParams); + + assertTrue(graph.queryRelationships(Collections.emptyMap(), Optional.of(tx)).count() == 0); + assertTrue(graph.queryObjects(Collections.emptyMap(), Optional.of(tx)).count() == 2); + } catch (ChampSchemaViolationException e) { + throw new AssertionError("Schema mismatch while storing object", e); + } catch (ChampMarshallingException e) { + throw new AssertionError("Marshalling exception while storing object", e); + } catch (ChampUnmarshallingException e) { + throw new AssertionError("Unmarshalling exception while retrieving relationship", e); + } catch (ChampRelationshipNotExistsException e) { + throw new AssertionError("Attempted to delete non-existent relationship", e); + } catch (ChampObjectNotExistsException e) { + throw new AssertionError("Object does not exist after storing it", e); + } catch (ChampTransactionException e) { + throw new AssertionError("Transaction failure", e); + } + + ChampTransaction tx = ChampRelationshipTest.getTransaction(); + try { + graph.retrieveRelationships(ChampObject.create().ofType("").withoutKey().build(), Optional.of(tx)); + throw new AssertionError("Failed to handle missing object while retrieving relationships"); + } catch (ChampUnmarshallingException | ChampTransactionException e) { + throw new AssertionError(e); + } catch (ChampObjectNotExistsException e) { + //Expected + } + //Negative test cases for replace relationship + + try { + graph.replaceRelationship(new ChampRelationship.Builder(ChampObject.create() + .ofType("foo") + .withoutKey() + .build(), ChampObject.create() + .ofType("foo") + .withoutKey() + .build(), "relationship") + .key("1234") + .property("property-2", 4) + .build(), + Optional.of(tx)); + } catch (ChampUnmarshallingException e) { + throw new AssertionError(e); + } catch (ChampMarshallingException e) { + throw new AssertionError(e); + } catch (ChampSchemaViolationException e) { + throw new AssertionError(e); + } catch (ChampRelationshipNotExistsException e) { + throw new AssertionError(e); + } catch (IllegalArgumentException e) { + //expected + } catch (ChampTransactionException e) { + throw new AssertionError(e); + } + + try { + graph.replaceRelationship(new ChampRelationship.Builder(ChampObject.create() + .ofType("foo") + .withKey("123") + .build(), ChampObject.create() + .ofType("foo") + .withKey("456") + .build(), "relationship") + .property("property-2", 4) + .build(), + Optional.of(tx)); + } catch (ChampUnmarshallingException e) { + throw new AssertionError(e); + } catch (ChampMarshallingException e) { + throw new AssertionError(e); + } catch (ChampSchemaViolationException e) { + throw new AssertionError(e); + } catch (ChampRelationshipNotExistsException e) { + //expected + } catch (IllegalArgumentException e) { + throw new AssertionError(e); + } catch (ChampTransactionException e) { + throw new AssertionError(e); + } + + + } + + @Test + public void testFluentRelationshipCreation() { + final Object value1 = new Object(); + final String value2 = "value2"; + final float value3 = 0.0f; + + final ChampRelationship champRelationship = ChampRelationship.create() + .ofType("foo") + .withoutKey() + .withSource() + .ofType("bar") + .withoutKey() + .build() + .withTarget() + .ofType("baz") + .withKey(1) + .build() + .withProperty("key1", value1) + .withProperty("key2", value2) + .withProperty("key3", value3) + .build(); + + ChampTransaction tx = ChampRelationshipTest.getTransaction(); + assertTrue(champRelationship.getKey().equals(Optional.empty())); + assertTrue(champRelationship.getType().equals("foo")); + assertTrue(champRelationship.getProperty("key1").get() instanceof Object); + assertTrue(champRelationship.getProperty("key1").get().equals(value1)); + assertTrue(champRelationship.getProperty("key2").get() instanceof String); + assertTrue(champRelationship.getProperty("key2").get().equals(value2)); + assertTrue(champRelationship.getProperty("key3").get() instanceof Float); + assertTrue(champRelationship.getProperty("key3").get().equals(value3)); + } + + @Test + public void testChampRelationshipEnums() { + for (ReservedPropertyKeys key : ChampRelationship.ReservedPropertyKeys.values()) { + assertTrue(ChampRelationship.ReservedPropertyKeys.valueOf(key.name()) == key); + } + + for (ReservedTypes type : ChampRelationship.ReservedTypes.values()) { + assertTrue(ChampRelationship.ReservedTypes.valueOf(type.name()) == type); + } + } + + public static ChampTransaction getTransaction() { + return new TestTransaction(); + } + + public static class TestTransaction extends ChampTransaction { + + public TestTransaction() { + + } + @Override + public void commit() { + // TODO Auto-generated method stub + + } + + @Override + public void rollback() { + // TODO Auto-generated method stub + + } + @Override + public String id() { + // TODO Auto-generated method stub + return null; + } + + } + +} diff --git a/src/test/java/org/onap/aai/champ/core/ChampSchemaTest.java b/champ-lib/champ-core/src/test/java/org/onap/aai/champcore/core/ChampSchemaTest.java similarity index 93% rename from src/test/java/org/onap/aai/champ/core/ChampSchemaTest.java rename to champ-lib/champ-core/src/test/java/org/onap/aai/champcore/core/ChampSchemaTest.java index df33631..ba62628 100644 --- a/src/test/java/org/onap/aai/champ/core/ChampSchemaTest.java +++ b/champ-lib/champ-core/src/test/java/org/onap/aai/champcore/core/ChampSchemaTest.java @@ -19,52 +19,47 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.core; +package org.onap.aai.champcore.core; import static org.junit.Assert.assertTrue; import java.io.IOException; +import java.util.Optional; import java.util.Set; import org.junit.Test; -import org.onap.aai.champ.ChampAPI; -import org.onap.aai.champ.ChampGraph; -import org.onap.aai.champ.exceptions.ChampMarshallingException; -import org.onap.aai.champ.exceptions.ChampObjectNotExistsException; -import org.onap.aai.champ.exceptions.ChampSchemaViolationException; -import org.onap.aai.champ.model.ChampConnectionConstraint; -import org.onap.aai.champ.model.ChampConnectionMultiplicity; -import org.onap.aai.champ.model.ChampField; -import org.onap.aai.champ.model.ChampObject; -import org.onap.aai.champ.model.ChampObjectConstraint; -import org.onap.aai.champ.model.ChampPartition; -import org.onap.aai.champ.model.ChampPropertyConstraint; -import org.onap.aai.champ.model.ChampRelationship; -import org.onap.aai.champ.model.ChampRelationshipConstraint; -import org.onap.aai.champ.model.ChampSchema; -import org.onap.aai.champ.model.ChampObject.ReservedTypes; -import org.onap.aai.champ.schema.AlwaysValidChampSchemaEnforcer; -import org.onap.aai.champ.schema.ChampSchemaEnforcer; -import org.onap.aai.champ.schema.DefaultChampSchemaEnforcer; +import org.onap.aai.champcore.ChampAPI; +import org.onap.aai.champcore.ChampGraph; +import org.onap.aai.champcore.exceptions.ChampMarshallingException; +import org.onap.aai.champcore.exceptions.ChampObjectNotExistsException; +import org.onap.aai.champcore.exceptions.ChampSchemaViolationException; +import org.onap.aai.champcore.exceptions.ChampTransactionException; +import org.onap.aai.champcore.model.ChampConnectionConstraint; +import org.onap.aai.champcore.model.ChampConnectionMultiplicity; +import org.onap.aai.champcore.model.ChampField; +import org.onap.aai.champcore.model.ChampObject; +import org.onap.aai.champcore.model.ChampObject.ReservedTypes; +import org.onap.aai.champcore.model.ChampObjectConstraint; +import org.onap.aai.champcore.model.ChampPartition; +import org.onap.aai.champcore.model.ChampPropertyConstraint; +import org.onap.aai.champcore.model.ChampRelationship; +import org.onap.aai.champcore.model.ChampRelationshipConstraint; +import org.onap.aai.champcore.model.ChampSchema; +import org.onap.aai.champcore.schema.AlwaysValidChampSchemaEnforcer; +import org.onap.aai.champcore.schema.ChampSchemaEnforcer; +import org.onap.aai.champcore.schema.DefaultChampSchemaEnforcer; import com.fasterxml.jackson.databind.ObjectMapper; public class ChampSchemaTest extends BaseChampAPITest { @Test - public void runTest() { - for (ChampGraph.Type apiType : ChampGraph.Type.values()) { - final String graphName = ChampSchemaTest.class.getSimpleName(); + public void runInMemoryTest() { + runTest("IN_MEMORY"); + } - switch (apiType) { - case IN_MEMORY: - break; - case TITAN: - cleanUp(graphName); - break; - default: - break; - } + public void runTest(String apiType) { + final String graphName = ChampSchemaTest.class.getSimpleName(); final ChampAPI api = ChampAPI.Factory.newInstance(apiType); @@ -75,7 +70,6 @@ public class ChampSchemaTest extends BaseChampAPITest { } api.shutdown(); - } } public static void testChampSchemaCrud(ChampGraph graph) { @@ -118,14 +112,16 @@ public class ChampSchemaTest extends BaseChampAPITest { .build(); try { - graph.storeObject(emptyFoo); + graph.storeObject(emptyFoo, Optional.empty()); } catch (ChampMarshallingException e1) { throw new AssertionError(e1); } catch (ChampSchemaViolationException e1) { //Expected, since it does not have the required property "property1" } catch (ChampObjectNotExistsException e) { throw new AssertionError(e); - } + } catch (ChampTransactionException e) { + throw new AssertionError(e); + } final ChampSchema retrievedSchema = graph.retrieveSchema(); @@ -158,16 +154,18 @@ public class ChampSchemaTest extends BaseChampAPITest { ) .build()); - final ChampObject storedEmptyFoo = graph.storeObject(emptyFoo); + final ChampObject storedEmptyFoo = graph.storeObject(emptyFoo, Optional.empty()); - graph.deleteObject(storedEmptyFoo.getKey().get()); + graph.deleteObject(storedEmptyFoo.getKey().get(), Optional.empty()); } catch (ChampMarshallingException e) { throw new AssertionError(e); } catch (ChampSchemaViolationException e) { throw new AssertionError(e); } catch (ChampObjectNotExistsException e) { throw new AssertionError(e); - } + } catch (ChampTransactionException e) { + throw new AssertionError(e); + } graph.deleteSchema(); assertTrue(graph.retrieveSchema().equals(ChampSchema.emptySchema())); diff --git a/champ-lib/champ-core/src/test/java/org/onap/aai/champcore/core/ChampTransactionTest.java b/champ-lib/champ-core/src/test/java/org/onap/aai/champcore/core/ChampTransactionTest.java new file mode 100644 index 0000000..30f033c --- /dev/null +++ b/champ-lib/champ-core/src/test/java/org/onap/aai/champcore/core/ChampTransactionTest.java @@ -0,0 +1,502 @@ +/** + * ============LICENSE_START========================================== + * org.onap.aai + * =================================================================== + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 Amdocs + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END============================================ + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.champcore.core; + +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.util.*; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.stream.Stream; + +import org.apache.commons.configuration.Configuration; +import org.apache.tinkerpop.gremlin.process.computer.GraphComputer; +import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal; +import org.apache.tinkerpop.gremlin.structure.Edge; +import org.apache.tinkerpop.gremlin.structure.Graph; +import org.apache.tinkerpop.gremlin.structure.Transaction; +import org.apache.tinkerpop.gremlin.structure.Vertex; +import org.apache.tinkerpop.gremlin.structure.util.FeatureDescriptor; +import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraph; +import org.junit.Before; +import org.junit.Test; +import org.onap.aai.champcore.ChampAPI; +import org.onap.aai.champcore.ChampCapabilities; +import org.onap.aai.champcore.ChampGraph; +import org.onap.aai.champcore.ChampTransaction; +import org.onap.aai.champcore.NoOpTinkerPopTransaction; +import org.onap.aai.champcore.exceptions.ChampIndexNotExistsException; +import org.onap.aai.champcore.exceptions.ChampTransactionException; +import org.onap.aai.champcore.graph.impl.AbstractTinkerpopChampGraph; +import org.onap.aai.champcore.graph.impl.TinkerpopTransaction; +import org.onap.aai.champcore.model.ChampObjectIndex; +import org.onap.aai.champcore.model.ChampRelationshipIndex; +import org.onap.aai.champcore.schema.ChampSchemaEnforcer; + + +public class ChampTransactionTest { + + TestGraph g = null; + + @Before + public void setup() { + g = new TestGraph(); + } + + /** + * This test validates the behaviour when the underlying graph implementation + * does not support transactions. + */ + @Test + public void testNoTransactionSupport() { + + // By default our test graph should be configured to support transactions, but + // set it explicitly anyway just to be sure. + g.setTransactionSupport(true); + + // Now, try to start a new transaction against our graph - it should succeed. + TinkerpopTransaction t = new TinkerpopTransaction(g); + Graph gi = t.getGraphInstance(); // GDF: Making jacoco happy... + + // Now, configure our graph to specify that transactions are NOT supported. + g.setTransactionSupport(false); + + try { + + // Now, try to start a new transaction against our graph. + t = new TinkerpopTransaction(g); + + } catch (UnsupportedOperationException e) { + + // If we're here, it's all good since we expected an exception to be thrown (since our + // graph does NOT support transactions). + return; + } + + // If we're here then we were able to open a transaction even though our graph does + // not support that functionality. + fail("Attempt to open a transaction against a graph with no transaction support should not succeed."); + } + + + /** + * This test validates the behaviour when committing a transaction under various + * circumstances. + * @throws ChampTransactionException + */ + @Test + public void testCommit() throws ChampTransactionException { + + // By default our test graph should simulate successful commits, but set + // the configuration anyway, just to be sure. + g.setFailCommits(false); + + // Now, start a transaction. + TinkerpopTransaction t = new TinkerpopTransaction(g); + + // Call commit against the transaction - it should complete successfully. + t.commit(); + + // Now, configure our test graph to simulate failing to commit. + g.setFailCommits(true); + + // Open another transaction... + t = new TinkerpopTransaction(g); + boolean exceptionThrown = false; + try { + + //...and try to commit it. + t.commit(); + + } catch (Throwable e) { + + // Our commit should have failed and ultimately thrown an exception - so if we + // are here then it's all good. + exceptionThrown = true; + } + + assertTrue("Failed commit should have produced an exception.", exceptionThrown); + } + + + @Test + public void testRollback() throws ChampTransactionException { + + // By default our test graph should simulate successful commits, but set + // the configuration anyway, just to be sure. + g.setFailCommits(false); + + // Now, start a transaction. + TinkerpopTransaction t = new TinkerpopTransaction(g); + + // Call rollback against the transaction - it should complete successfully. + t.rollback(); + + // Now, configure our test graph to simulate failing to commit. + g.setFailCommits(true); + + // Open another transaction... + t = new TinkerpopTransaction(g); + boolean exceptionThrown = false; + try { + + //...and try to commit it. + t.rollback(); + + } catch (Throwable e) { + + // Our commit should have failed and ultimately thrown an exception - so if we + // are here then it's all good. + exceptionThrown = true; + } + + assertTrue("Failed rollback should have produced an exception.", exceptionThrown); + } + + @Test + public void test() throws ChampTransactionException { + + AbstractTinkerpopChampGraph graph = new AbstractTinkerpopChampGraph(new HashMap()) { + + @Override + protected Graph getGraph() { + return TinkerGraph.open(); + } + + @Override + protected ChampSchemaEnforcer getSchemaEnforcer() { + return null; + } + + @Override + public void executeStoreObjectIndex(ChampObjectIndex index) { } + + @Override + public Optional retrieveObjectIndex(String indexName) { + return null; + } + + @Override + public Stream retrieveObjectIndices() { + return null; + } + + @Override + public void executeDeleteObjectIndex(String indexName) throws ChampIndexNotExistsException {} + + @Override + public void executeStoreRelationshipIndex(ChampRelationshipIndex index) {} + + @Override + public Optional retrieveRelationshipIndex(String indexName) { + return null; + } + + @Override + public Stream retrieveRelationshipIndices() { + return null; + } + + @Override + public void executeDeleteRelationshipIndex(String indexName) throws ChampIndexNotExistsException {} + + @Override + public ChampCapabilities capabilities() { + return null; + } + + @Override + public GraphTraversal hasLabel(GraphTraversal query, Object type) { + // TODO Auto-generated method stub + return null; + } + }; + + TinkerpopTransaction t = new TinkerpopTransaction(g); + t.id(); + graph.commitTransaction(t); + graph.rollbackTransaction(t); + + } + + private class TestGraph implements Graph { + + private boolean supportsTransactions = true; + private boolean failCommits = false; + + + public void setTransactionSupport(boolean supportsTransactions) { + this.supportsTransactions = supportsTransactions; + } + + public void setFailCommits(boolean failCommits) { + this.failCommits = failCommits; + } + @Override + public Vertex addVertex(Object... keyValues) { + // TODO Auto-generated method stub + return null; + } + + @Override + public void close() throws Exception { + // TODO Auto-generated method stub + + } + + @Override + public GraphComputer compute() throws IllegalArgumentException { + // TODO Auto-generated method stub + return null; + } + + @Override + public C compute(Class graphComputerClass) + throws IllegalArgumentException { + // TODO Auto-generated method stub + return null; + } + + @Override + public Configuration configuration() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Iterator edges(Object... edgeIds) { + // TODO Auto-generated method stub + return null; + } + + @Override + public Transaction tx() { + return new TestTransaction(); + } + + @Override + public Variables variables() { + // TODO Auto-generated method stub + return null; + } + + @Override + public Iterator vertices(Object... vertexIds) { + // TODO Auto-generated method stub + return null; + } + + /** + * Gets the {@link Features} exposed by the underlying {@code Graph} implementation. + */ + public Features features() { + return new TestFeatures() { + }; + } + + public class TestFeatures implements Graph.Features { + + /** + * Gets the features related to "graph" operation. + */ + public GraphFeatures graph() { + return new TestGraphFeatures() { + }; + } + + public class TestGraphFeatures implements Graph.Features.GraphFeatures { + + /** + * Determines if the {@code Graph} implementations supports transactions. + */ + @FeatureDescriptor(name = FEATURE_TRANSACTIONS) + public boolean supportsTransactions() { + return supportsTransactions; + } + } + } + } + + private class TestTransaction implements Transaction { + + @Override + public void addTransactionListener(Consumer listener) { + // TODO Auto-generated method stub + + } + + @Override + public void clearTransactionListeners() { + // TODO Auto-generated method stub + + } + + @Override + public void close() { + // TODO Auto-generated method stub + + } + + @Override + public void commit() { + + if(g.failCommits) { + throw new UnsupportedOperationException(); + } + } + + @Override + public G createThreadedTx() { + return (G) g; + } + + @Override + public boolean isOpen() { + // TODO Auto-generated method stub + return false; + } + + @Override + public Transaction onClose(Consumer consumer) { + // TODO Auto-generated method stub + return null; + } + + @Override + public Transaction onReadWrite(Consumer consumer) { + // TODO Auto-generated method stub + return null; + } + + @Override + public void open() { + // TODO Auto-generated method stub + + } + + @Override + public void readWrite() { + // TODO Auto-generated method stub + + } + + @Override + public void removeTransactionListener(Consumer listener) { + // TODO Auto-generated method stub + + } + + @Override + public void rollback() { + if(g.failCommits) { + throw new UnsupportedOperationException(); + } + } + + @Override + public Workload submit(Function work) { + // TODO Auto-generated method stub + return null; + } + + } + + private class TestTinkerpopGraph extends AbstractTinkerpopChampGraph { + + protected TestTinkerpopGraph(Map properties) { + super(properties); + } + + @Override + protected Graph getGraph() { + return TinkerGraph.open(); + } + + + @Override + protected ChampSchemaEnforcer getSchemaEnforcer() { + return null; + } + + @Override + public void executeStoreObjectIndex(ChampObjectIndex index) { + } + + @Override + public Optional retrieveObjectIndex(String indexName) { + // TODO Auto-generated method stub + return null; + } + + @Override + public Stream retrieveObjectIndices() { + // TODO Auto-generated method stub + return null; + } + + @Override + public void executeDeleteObjectIndex(String indexName) throws ChampIndexNotExistsException { + // TODO Auto-generated method stub + + } + + @Override + public void executeStoreRelationshipIndex(ChampRelationshipIndex index) { + // TODO Auto-generated method stub + + } + + @Override + public Optional retrieveRelationshipIndex(String indexName) { + // TODO Auto-generated method stub + return null; + } + + @Override + public Stream retrieveRelationshipIndices() { + // TODO Auto-generated method stub + return null; + } + + @Override + public void executeDeleteRelationshipIndex(String indexName) + throws ChampIndexNotExistsException { + // TODO Auto-generated method stub + + } + + @Override + public ChampCapabilities capabilities() { + // TODO Auto-generated method stub + return null; + } + + @Override + public GraphTraversal hasLabel(GraphTraversal query, Object type) { + // TODO Auto-generated method stub + return null; + } + + } +} diff --git a/src/test/java/org/onap/aai/champ/event/AbstractLoggingChampGraphTest.java b/champ-lib/champ-core/src/test/java/org/onap/aai/champcore/event/AbstractLoggingChampGraphTest.java similarity index 77% rename from src/test/java/org/onap/aai/champ/event/AbstractLoggingChampGraphTest.java rename to champ-lib/champ-core/src/test/java/org/onap/aai/champcore/event/AbstractLoggingChampGraphTest.java index 388b16f..1f7451a 100644 --- a/src/test/java/org/onap/aai/champ/event/AbstractLoggingChampGraphTest.java +++ b/champ-lib/champ-core/src/test/java/org/onap/aai/champcore/event/AbstractLoggingChampGraphTest.java @@ -19,16 +19,13 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.event; +package org.onap.aai.champcore.event; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import java.io.IOException; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; -import java.util.Optional; +import java.util.*; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; import java.util.concurrent.TimeUnit; @@ -37,25 +34,25 @@ import java.util.stream.Stream; import org.junit.After; import org.junit.Before; import org.junit.Test; -import org.onap.aai.champ.ChampCapabilities; -import org.onap.aai.champ.event.AbstractLoggingChampGraph; -import org.onap.aai.champ.exceptions.ChampIndexNotExistsException; -import org.onap.aai.champ.exceptions.ChampMarshallingException; -import org.onap.aai.champ.exceptions.ChampObjectNotExistsException; -import org.onap.aai.champ.exceptions.ChampRelationshipNotExistsException; -import org.onap.aai.champ.exceptions.ChampSchemaViolationException; -import org.onap.aai.champ.exceptions.ChampUnmarshallingException; -import org.onap.aai.champ.model.ChampObject; -import org.onap.aai.champ.model.ChampObjectConstraint; -import org.onap.aai.champ.model.ChampObjectIndex; -import org.onap.aai.champ.model.ChampPartition; -import org.onap.aai.champ.model.ChampRelationship; -import org.onap.aai.champ.model.ChampRelationshipConstraint; -import org.onap.aai.champ.model.ChampRelationshipIndex; -import org.onap.aai.champ.model.ChampSchema; -import org.slf4j.Logger; +import org.onap.aai.champcore.ChampCapabilities; +import org.onap.aai.champcore.ChampTransaction; +import org.onap.aai.champcore.exceptions.ChampIndexNotExistsException; +import org.onap.aai.champcore.exceptions.ChampMarshallingException; +import org.onap.aai.champcore.exceptions.ChampObjectNotExistsException; +import org.onap.aai.champcore.exceptions.ChampRelationshipNotExistsException; +import org.onap.aai.champcore.exceptions.ChampSchemaViolationException; +import org.onap.aai.champcore.exceptions.ChampTransactionException; +import org.onap.aai.champcore.exceptions.ChampUnmarshallingException; +import org.onap.aai.champcore.model.ChampObject; +import org.onap.aai.champcore.model.ChampObjectConstraint; +import org.onap.aai.champcore.model.ChampObjectIndex; +import org.onap.aai.champcore.model.ChampPartition; +import org.onap.aai.champcore.model.ChampRelationship; +import org.onap.aai.champcore.model.ChampRelationshipConstraint; +import org.onap.aai.champcore.model.ChampRelationshipIndex; +import org.onap.aai.champcore.model.ChampSchema; -import com.att.nsa.cambria.client.CambriaPublisher; +import org.onap.aai.event.api.EventPublisher; import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.databind.JsonMappingException; @@ -80,17 +77,20 @@ public class AbstractLoggingChampGraphTest { // Instantiate an 'in-memory' graph for test purposes. Map graphProperties = new HashMap(); - graphProperties.put("champ.event.stream.hosts", "myeventstreamhost"); - graphProperties.put("champ.event.stream.batch-size", 1); - testGraph = new TestGraph(graphProperties, producer); + graphProperties.put("champcore.event.stream.hosts", "myeventstreamhost"); + graphProperties.put("champcore.event.stream.batch-size", 1); + graphProperties.put("champcore.event.stream.publisher", producer); + testGraph = new TestGraph(graphProperties); } /** * Perform any cleanup that needs to be done after each test. + * + * @throws Exception */ @After - public void tearDown() { + public void tearDown() throws Exception { // Close our stubbed producer and graph. producer.close(); @@ -109,15 +109,69 @@ public class AbstractLoggingChampGraphTest { * @throws JsonParseException * @throws JsonMappingException * @throws IOException + * @throws ChampTransactionException */ @Test - public void vertexOperationsTest() throws ChampMarshallingException, - ChampSchemaViolationException, - ChampObjectNotExistsException, - InterruptedException, - JsonParseException, - JsonMappingException, - IOException { + public void vertexOperationsEmptyTransactionsTest() throws ChampMarshallingException, + ChampSchemaViolationException, + ChampObjectNotExistsException, + InterruptedException, + JsonParseException, + JsonMappingException, + IOException, + ChampTransactionException { + + // Create a vertex and store it in the graph data store. + ChampObject obj1 = ChampObject.create() + .ofType("foo") + .withKey("123") + .withProperty("p1", "v1") + .withProperty("p2", "v2") + .build(); + testGraph.storeObject(obj1, Optional.empty()); + + // Retrieve the next event from the event stream and validate that it is what we expect. + String loggedEventStr = producer.eventStream.poll(5000, TimeUnit.MILLISECONDS); + assertTrue("Expected STORE event.", loggedEventStr.contains("STORE")); + assertTrue("Entity type for store event was not a vertex.", loggedEventStr.contains("vertex")); + + + + // Create a new vertex based on the one that we already created. + ChampObject obj2 = ChampObject.create() + .from(obj1) + .withKey("123") + .withProperty("p3", "v3") + .build(); + + // Now, try doing a replace operation. + testGraph.replaceObject(obj2, Optional.empty()); + + + + // Retrieve the next event from the event stream and validate that it is what we expect. + loggedEventStr = producer.eventStream.poll(5000, TimeUnit.MILLISECONDS); + assertTrue("Expected REPLACE event.", loggedEventStr.contains("REPLACE")); + assertTrue("Entity type for store event was not a vertex.", loggedEventStr.contains("vertex")); + + // Finally, delete the vertex. + testGraph.deleteObject("123", Optional.empty()); + + // Retrieve the next event from the event stream and validate that it is what we expect. + loggedEventStr = producer.eventStream.poll(5000, TimeUnit.MILLISECONDS); + assertTrue("Expected DELETE event.", loggedEventStr.contains("DELETE")); + assertTrue("Entity type for store event was not a vertex.", loggedEventStr.contains("vertex")); + } + + @Test + public void vertexOperationsLegacyTest2() throws ChampMarshallingException, + ChampSchemaViolationException, + ChampObjectNotExistsException, + InterruptedException, + JsonParseException, + JsonMappingException, + IOException, + ChampTransactionException { // Create a vertex and store it in the graph data store. ChampObject obj1 = ChampObject.create() @@ -127,12 +181,14 @@ public class AbstractLoggingChampGraphTest { .withProperty("p2", "v2") .build(); testGraph.storeObject(obj1); - + // Retrieve the next event from the event stream and validate that it is what we expect. String loggedEventStr = producer.eventStream.poll(5000, TimeUnit.MILLISECONDS); assertTrue("Expected STORE event.", loggedEventStr.contains("STORE")); assertTrue("Entity type for store event was not a vertex.", loggedEventStr.contains("vertex")); + + // Create a new vertex based on the one that we already created. ChampObject obj2 = ChampObject.create() .from(obj1) @@ -143,6 +199,8 @@ public class AbstractLoggingChampGraphTest { // Now, try doing a replace operation. testGraph.replaceObject(obj2); + + // Retrieve the next event from the event stream and validate that it is what we expect. loggedEventStr = producer.eventStream.poll(5000, TimeUnit.MILLISECONDS); assertTrue("Expected REPLACE event.", loggedEventStr.contains("REPLACE")); @@ -157,7 +215,6 @@ public class AbstractLoggingChampGraphTest { assertTrue("Entity type for store event was not a vertex.", loggedEventStr.contains("vertex")); } - /** * This test validates that performing vertex operations in the case where the data to be * forwarded to the event stream is unavailable results in no event being generated, but @@ -170,6 +227,7 @@ public class AbstractLoggingChampGraphTest { * @throws JsonParseException * @throws JsonMappingException * @throws IOException + * @throws ChampTransactionException */ @Test public void vertexOperationsWithNullsTest() throws ChampMarshallingException, @@ -178,7 +236,7 @@ public class AbstractLoggingChampGraphTest { InterruptedException, JsonParseException, JsonMappingException, - IOException { + IOException, ChampTransactionException { // Setup our test graph to simulate failures to retrieve data from the graph data store. testGraph.returnNulls(); @@ -190,7 +248,7 @@ public class AbstractLoggingChampGraphTest { .withProperty("p1", "v1") .withProperty("p2", "v2") .build(); - testGraph.storeObject(obj1); + testGraph.storeObject(obj1, Optional.empty()); // Check our simulated event stream to verify that an event log was produced. String loggedEventStr = producer.eventStream.poll(5000, TimeUnit.MILLISECONDS); @@ -206,7 +264,7 @@ public class AbstractLoggingChampGraphTest { .build(); // Now, try doing a replace operation. - testGraph.replaceObject(obj2); + testGraph.replaceObject(obj2, Optional.empty()); // Check our simulated event stream to see if an event log was not produced. loggedEventStr = producer.eventStream.poll(5000, TimeUnit.MILLISECONDS); @@ -215,7 +273,7 @@ public class AbstractLoggingChampGraphTest { assertNull("Store vertex event should not have been logged to the event stream", loggedEventStr); // Finally, delete the vertex. - testGraph.deleteObject("123"); + testGraph.deleteObject("123", Optional.empty()); // Check our simulated event stream to see if an event log was not produced. loggedEventStr = producer.eventStream.poll(5000, TimeUnit.MILLISECONDS); @@ -238,6 +296,7 @@ public class AbstractLoggingChampGraphTest { * @throws IOException * @throws ChampUnmarshallingException * @throws ChampRelationshipNotExistsException + * @throws ChampTransactionException */ @Test public void edgeOperationsTest() throws ChampMarshallingException, @@ -248,7 +307,7 @@ public class AbstractLoggingChampGraphTest { JsonMappingException, IOException, ChampUnmarshallingException, - ChampRelationshipNotExistsException { + ChampRelationshipNotExistsException, ChampTransactionException { // Create two vertices to act as the end points of our edge. ChampObject obj1 = ChampObject.create() @@ -269,7 +328,7 @@ public class AbstractLoggingChampGraphTest { .property("property-1", "value-1") .property("property-2", "value-2") .build(); - testGraph.storeRelationship(rel); + testGraph.storeRelationship(rel, Optional.empty()); // Retrieve the next event from the event stream and validate that it is what we expect. String loggedEventStr = producer.eventStream.poll(5000, TimeUnit.MILLISECONDS); @@ -283,7 +342,7 @@ public class AbstractLoggingChampGraphTest { .withKey("123") .withProperty("property-3", "value-3") .build(); - testGraph.replaceRelationship(rel2); + testGraph.replaceRelationship(rel2, Optional.empty()); // Retrieve the next event from the event stream and validate that it is what we expect. loggedEventStr = producer.eventStream.poll(5000, TimeUnit.MILLISECONDS); @@ -291,7 +350,7 @@ public class AbstractLoggingChampGraphTest { assertTrue("Entity type for store event was not an edge.", loggedEventStr.contains("relationship")); // Finally, delete our edge. - testGraph.deleteRelationship(rel2); + testGraph.deleteRelationship(rel2, Optional.empty()); // Retrieve the next event from the event stream and validate that it is what we expect. loggedEventStr = producer.eventStream.poll(5000, TimeUnit.MILLISECONDS); @@ -314,6 +373,7 @@ public class AbstractLoggingChampGraphTest { * @throws IOException * @throws ChampUnmarshallingException * @throws ChampRelationshipNotExistsException + * @throws ChampTransactionException */ @Test public void edgeOperationsWithNullsTest() throws ChampMarshallingException, @@ -324,7 +384,7 @@ public class AbstractLoggingChampGraphTest { JsonMappingException, IOException, ChampUnmarshallingException, - ChampRelationshipNotExistsException { + ChampRelationshipNotExistsException, ChampTransactionException { // Set up our graph to simulate a failure to retrieve some of the data we need to generate // events. @@ -349,7 +409,7 @@ public class AbstractLoggingChampGraphTest { .property("property-1", "value-1") .property("property-2", "value-2") .build(); - testGraph.storeRelationship(rel); + testGraph.storeRelationship(rel, Optional.empty()); // Check our simulated event stream to see if an event log was produced. String loggedEventStr = producer.eventStream.poll(5000, TimeUnit.MILLISECONDS); @@ -364,7 +424,7 @@ public class AbstractLoggingChampGraphTest { .withKey("123") .withProperty("property-3", "value-3") .build(); - testGraph.replaceRelationship(rel2); + testGraph.replaceRelationship(rel2, Optional.empty()); // Check our simulated event stream to see if an event log was produced. loggedEventStr = producer.eventStream.poll(5000, TimeUnit.MILLISECONDS); @@ -387,6 +447,7 @@ public class AbstractLoggingChampGraphTest { * @throws IOException * @throws ChampUnmarshallingException * @throws ChampRelationshipNotExistsException + * @throws ChampTransactionException */ @Test public void partitionOperationsTest() throws ChampMarshallingException, @@ -397,7 +458,7 @@ public class AbstractLoggingChampGraphTest { JsonMappingException, IOException, ChampUnmarshallingException, - ChampRelationshipNotExistsException { + ChampRelationshipNotExistsException, ChampTransactionException { // Create the vertices and edge objects that we need to create a partition. ChampObject obj1 = ChampObject.create() @@ -425,7 +486,7 @@ public class AbstractLoggingChampGraphTest { .withObject(obj2) .withRelationship(rel) .build(); - testGraph.storePartition(partition); + testGraph.storePartition(partition, Optional.empty()); // Retrieve the next event from the event stream and validate that it is what we expect. String loggedEventStr = producer.eventStream.poll(5000, TimeUnit.MILLISECONDS); @@ -433,7 +494,7 @@ public class AbstractLoggingChampGraphTest { assertTrue("Entity type for store event was not a partition.", loggedEventStr.contains("partition")); // Now, delete our partition. - testGraph.deletePartition(partition); + testGraph.deletePartition(partition, Optional.empty()); // Retrieve the next event from the event stream and validate that it is what we expect. loggedEventStr = producer.eventStream.poll(5000, TimeUnit.MILLISECONDS); @@ -456,6 +517,7 @@ public class AbstractLoggingChampGraphTest { * @throws IOException * @throws ChampUnmarshallingException * @throws ChampRelationshipNotExistsException + * @throws ChampTransactionException */ @Test public void partitionOperationsWithNullsTest() throws ChampMarshallingException, @@ -466,7 +528,7 @@ public class AbstractLoggingChampGraphTest { JsonMappingException, IOException, ChampUnmarshallingException, - ChampRelationshipNotExistsException { + ChampRelationshipNotExistsException, ChampTransactionException { // Set up our graph to simulate a failure to retrieve some of the data we need to generate // events. @@ -497,7 +559,7 @@ public class AbstractLoggingChampGraphTest { .withObject(obj2) .withRelationship(rel) .build(); - testGraph.storePartition(partition); + testGraph.storePartition(partition, Optional.empty()); // Check our simulated event stream to see if an an event log was produced. String loggedEventStr = producer.eventStream.poll(5000, TimeUnit.MILLISECONDS); @@ -727,10 +789,8 @@ public class AbstractLoggingChampGraphTest { private boolean returnNulls = false; - protected TestGraph(Map properties, CambriaPublisher producer) { - super(properties); - - setProducer(producer); + protected TestGraph(Map properties) { + super(properties); } public void returnNulls() { @@ -746,9 +806,11 @@ public class AbstractLoggingChampGraphTest { } @Override - public ChampObject executeStoreObject(ChampObject object) throws ChampMarshallingException, - ChampSchemaViolationException, - ChampObjectNotExistsException { + public ChampObject executeStoreObject(ChampObject object, Optional transaction) + throws ChampMarshallingException, + ChampSchemaViolationException, + ChampObjectNotExistsException { + if(!returnNulls) { return object; } else { @@ -757,9 +819,11 @@ public class AbstractLoggingChampGraphTest { } @Override - public ChampObject executeReplaceObject(ChampObject object) throws ChampMarshallingException, - ChampSchemaViolationException, - ChampObjectNotExistsException { + public ChampObject executeReplaceObject(ChampObject object, Optional transaction) + throws ChampMarshallingException, + ChampSchemaViolationException, + ChampObjectNotExistsException { + if(!returnNulls) { return object; } else { @@ -769,6 +833,11 @@ public class AbstractLoggingChampGraphTest { @Override public Optional retrieveObject(Object key) throws ChampUnmarshallingException { + return retrieveObject(key, Optional.empty()); + } + + @Override + public Optional retrieveObject(Object key, Optional transaction) throws ChampUnmarshallingException { if(!returnNulls) { return(Optional.of(ChampObject.create() @@ -781,18 +850,24 @@ public class AbstractLoggingChampGraphTest { } @Override - public void executeDeleteObject(Object key) throws ChampObjectNotExistsException { + public void executeDeleteObject(Object key, Optional transaction) throws ChampObjectNotExistsException { } @Override public Stream queryObjects(Map queryParams) { + return queryObjects(queryParams, Optional.empty()); + } + + + @Override + public Stream queryObjects(Map queryParams, Optional transaction) { // Not used by any tests. return null; } @Override - public ChampRelationship executeStoreRelationship(ChampRelationship relationship) + public ChampRelationship executeStoreRelationship(ChampRelationship relationship, Optional transaction) throws ChampUnmarshallingException, ChampMarshallingException, ChampObjectNotExistsException, @@ -807,7 +882,7 @@ public class AbstractLoggingChampGraphTest { } @Override - public ChampRelationship executeReplaceRelationship(ChampRelationship relationship) + public ChampRelationship executeReplaceRelationship(ChampRelationship relationship, Optional transaction) throws ChampUnmarshallingException, ChampMarshallingException, ChampSchemaViolationException, @@ -822,18 +897,29 @@ public class AbstractLoggingChampGraphTest { @Override public Optional retrieveRelationship(Object key) throws ChampUnmarshallingException { + return retrieveRelationship(key, Optional.empty()); + } + + @Override + public Optional retrieveRelationship(Object key, Optional transaction) throws ChampUnmarshallingException { // Not used by any tests. return null; } @Override - public void executeDeleteRelationship(ChampRelationship relationship) throws ChampRelationshipNotExistsException { + public void executeDeleteRelationship(ChampRelationship relationship, Optional transaction) throws ChampRelationshipNotExistsException { // Not used by any tests. } @Override public Stream retrieveRelationships(ChampObject object) throws ChampUnmarshallingException, ChampObjectNotExistsException { + return retrieveRelationships(object, Optional.empty()); + } + + @Override + public Stream retrieveRelationships(ChampObject object, Optional transaction) + throws ChampUnmarshallingException, ChampObjectNotExistsException { // Not used by any tests. return null; @@ -841,13 +927,18 @@ public class AbstractLoggingChampGraphTest { @Override public Stream queryRelationships(Map queryParams) { + return queryRelationships(queryParams, Optional.empty()); + } + + @Override + public Stream queryRelationships(Map queryParams, Optional transaction) { // Not used by any tests. return null; } @Override - public ChampPartition executeStorePartition(ChampPartition partition) + public ChampPartition executeStorePartition(ChampPartition partition, Optional transaction) throws ChampSchemaViolationException, ChampRelationshipNotExistsException, ChampMarshallingException, @@ -861,7 +952,7 @@ public class AbstractLoggingChampGraphTest { } @Override - public void executeDeletePartition(ChampPartition graph) { + public void executeDeletePartition(ChampPartition graph, Optional transaction) { // Not used by any tests. } @@ -958,73 +1049,133 @@ public class AbstractLoggingChampGraphTest { // Not used by any tests. return null; } + + @Override + public ChampTransaction openTransaction() { + // Not used by any tests. + return null; + } + + @Override + public void commitTransaction(ChampTransaction transaction) { + // Not used by any tests. + + } + + @Override + public void rollbackTransaction(ChampTransaction transaction) { + // Not used by any tests. + } } - private class InMemoryPublisher implements CambriaPublisher { + private class InMemoryPublisher implements EventPublisher { public BlockingQueue eventStream = new ArrayBlockingQueue(50); public BlockingQueue failedMsgs = new ArrayBlockingQueue(10); - private boolean failMode=false; + public void enterFailMode() { failMode=true; } @Override - public void logTo(Logger log) { - // Not used by any tests. - } - - @Override - public void setApiCredentials(String apiKey, String apiSecret) { - // Not used by any tests. + public int sendSync(String partitionKey, String message) throws Exception { + + if(!failMode) { + eventStream.add(message); + return 0; + } else { + failedMsgs.add(message); + throw new IOException("nope"); + } } - + @Override - public void clearApiCredentials() { - // Not used by any tests. + public int sendSync(String partitionKey, Collection messages) throws Exception { + + for(String msg : messages) { + if(!failMode) { + eventStream.add(msg); + return 0; + } else { + failedMsgs.add(msg); + throw new IOException("nope"); + } + } + return 0; } - + @Override - public void setHttpBasicCredentials(String username, String password) { - // Not used by any tests. + public int sendSync(String message) throws Exception { + if(!failMode) { + eventStream.add(message); + return 0; + } else { + failedMsgs.add(message); + throw new IOException("nope"); + } } - + @Override - public void clearHttpBasicCredentials() { - // Not used by any tests. + public int sendSync(Collection messages) throws Exception { + + for(String msg : messages) { + if(!failMode) { + eventStream.add(msg); + return 0; + } else { + failedMsgs.add(msg); + throw new IOException("nope"); + } + } + return 0; } - @Override - public int send(String partition, String msg) throws IOException { - + public void sendAsync(String partitionKey, String message) throws Exception { if(!failMode) { - eventStream.add(msg); - return 0; + eventStream.add(message); } else { - failedMsgs.add(msg); + failedMsgs.add(message); throw new IOException("nope"); - } + } } - @Override - public int send(message msg) throws IOException { - eventStream.add(msg.toString()); - return 0; + public void sendAsync(String partitionKey, Collection messages) throws Exception { + for(String msg : messages) { + if(!failMode) { + eventStream.add(msg); + } else { + failedMsgs.add(msg); + throw new IOException("nope"); + } + } } - @Override - public int send(Collection msgs) throws IOException { - for(message msg : msgs) { - eventStream.add(msg.toString()); - } - return 0; + public void sendAsync(String message) throws Exception { + if(!failMode) { + eventStream.add(message); + } else { + failedMsgs.add(message); + throw new IOException("nope"); + } } - @Override - public void close() { - // Not used by any tests. - } + public void sendAsync(Collection messages) throws Exception { + for(String msg : messages) { + if(!failMode) { + eventStream.add(msg); + } else { + failedMsgs.add(msg); + throw new IOException("nope"); + } + } + } + + @Override + public void close() throws Exception { + // TODO Auto-generated method stub + + } } } diff --git a/src/test/java/org/onap/aai/champ/exceptions/ChampExceptionTest.java b/champ-lib/champ-core/src/test/java/org/onap/aai/champcore/exceptions/ChampExceptionTest.java similarity index 91% rename from src/test/java/org/onap/aai/champ/exceptions/ChampExceptionTest.java rename to champ-lib/champ-core/src/test/java/org/onap/aai/champcore/exceptions/ChampExceptionTest.java index b92ccdf..f7a32f7 100644 --- a/src/test/java/org/onap/aai/champ/exceptions/ChampExceptionTest.java +++ b/champ-lib/champ-core/src/test/java/org/onap/aai/champcore/exceptions/ChampExceptionTest.java @@ -19,17 +19,11 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.exceptions; +package org.onap.aai.champcore.exceptions; import static org.junit.Assert.assertTrue; import org.junit.Test; -import org.onap.aai.champ.exceptions.ChampIndexNotExistsException; -import org.onap.aai.champ.exceptions.ChampMarshallingException; -import org.onap.aai.champ.exceptions.ChampObjectNotExistsException; -import org.onap.aai.champ.exceptions.ChampRelationshipNotExistsException; -import org.onap.aai.champ.exceptions.ChampSchemaViolationException; -import org.onap.aai.champ.exceptions.ChampUnmarshallingException; public class ChampExceptionTest { diff --git a/src/test/java/org/onap/aai/champ/ie/ExportTest.java b/champ-lib/champ-core/src/test/java/org/onap/aai/champcore/ie/ExportTest.java similarity index 85% rename from src/test/java/org/onap/aai/champ/ie/ExportTest.java rename to champ-lib/champ-core/src/test/java/org/onap/aai/champcore/ie/ExportTest.java index 80142b2..bda6122 100644 --- a/src/test/java/org/onap/aai/champ/ie/ExportTest.java +++ b/champ-lib/champ-core/src/test/java/org/onap/aai/champcore/ie/ExportTest.java @@ -19,12 +19,10 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.ie; +package org.onap.aai.champcore.ie; import org.junit.Test; -import org.onap.aai.champ.ChampAPI; -import org.onap.aai.champ.ChampGraph; -import org.onap.aai.champ.ie.GraphMLImporterExporter; +import org.onap.aai.champcore.ChampAPI; public class ExportTest { @@ -32,7 +30,7 @@ public class ExportTest { public void testGraphMLExport() { final GraphMLImporterExporter ie = new GraphMLImporterExporter(); - final ChampAPI api = ChampAPI.Factory.newInstance(ChampGraph.Type.IN_MEMORY); + final ChampAPI api = ChampAPI.Factory.newInstance("IN_MEMORY"); ie.importData(api, getClass().getClassLoader().getResourceAsStream("import-test.graphml")); diff --git a/src/test/java/org/onap/aai/champ/ie/ImportTest.java b/champ-lib/champ-core/src/test/java/org/onap/aai/champcore/ie/ImportTest.java similarity index 88% rename from src/test/java/org/onap/aai/champ/ie/ImportTest.java rename to champ-lib/champ-core/src/test/java/org/onap/aai/champcore/ie/ImportTest.java index 0dca95e..67fdb19 100644 --- a/src/test/java/org/onap/aai/champ/ie/ImportTest.java +++ b/champ-lib/champ-core/src/test/java/org/onap/aai/champcore/ie/ImportTest.java @@ -19,7 +19,7 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.ie; +package org.onap.aai.champcore.ie; import static org.junit.Assert.assertTrue; @@ -27,25 +27,25 @@ import java.util.Collections; import java.util.Optional; import org.junit.Test; -import org.onap.aai.champ.ChampAPI; -import org.onap.aai.champ.ChampGraph; -import org.onap.aai.champ.ie.GraphMLImporterExporter; +import org.onap.aai.champcore.ChampAPI; +import org.onap.aai.champcore.ChampGraph; +import org.onap.aai.champcore.exceptions.ChampTransactionException; public class ImportTest { private final String GRAPH_NAME = "unit-test"; @Test - public void testGraphMLImport() { + public void testGraphMLImport() throws ChampTransactionException, AssertionError { final GraphMLImporterExporter importer = new GraphMLImporterExporter(); - final ChampAPI api = ChampAPI.Factory.newInstance(ChampGraph.Type.IN_MEMORY); + final ChampAPI api = ChampAPI.Factory.newInstance("IN_MEMORY"); importer.importData(api, getClass().getClassLoader().getResourceAsStream("import-test.graphml")); final ChampGraph graph = api.getGraph(GRAPH_NAME); - graph.queryObjects(Collections.emptyMap()).forEach(object -> { + graph.queryObjects(Collections.emptyMap(), Optional.empty()).forEach(object -> { final Optional nameOpt = object.getProperty("name"); final Optional studentOpt = object.getProperty("student"); final Optional worthOpt = object.getProperty("worth"); diff --git a/src/test/resources/import-test.graphml b/champ-lib/champ-core/src/test/resources/import-test.graphml old mode 100755 new mode 100644 similarity index 100% rename from src/test/resources/import-test.graphml rename to champ-lib/champ-core/src/test/resources/import-test.graphml diff --git a/src/test/resources/logback.xml b/champ-lib/champ-core/src/test/resources/logback.xml similarity index 100% rename from src/test/resources/logback.xml rename to champ-lib/champ-core/src/test/resources/logback.xml diff --git a/champ-lib/champ-janus/License.txt b/champ-lib/champ-janus/License.txt new file mode 100644 index 0000000..469f362 --- /dev/null +++ b/champ-lib/champ-janus/License.txt @@ -0,0 +1,21 @@ +============LICENSE_START========================================== +org.onap.aai +=================================================================== +Copyright © 2017 AT&T Intellectual Property. All rights reserved. +Copyright © 2017 Amdocs +=================================================================== +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +============LICENSE_END============================================ +ECOMP is a trademark and service mark of AT&T Intellectual Property. + + diff --git a/champ-lib/champ-janus/pom.xml b/champ-lib/champ-janus/pom.xml new file mode 100644 index 0000000..15c65e5 --- /dev/null +++ b/champ-lib/champ-janus/pom.xml @@ -0,0 +1,188 @@ + + + 4.0.0 + + + champ-lib + org.onap.aai + 1.2.0-SNAPSHOT + + + champ-janus + + + 3.2.3 + + + + + org.apache.tinkerpop + tinkergraph-gremlin + ${tinkerpop.version} + + + org.onap.aai + champ-core + 1.2.0-SNAPSHOT + + + org.onap.aai + champ-core + 1.2.0-SNAPSHOT + test-jar + test + + + org.janusgraph + janusgraph-cassandra + 0.1.1 + true + + + org.slf4j + slf4j-log4j12 + + + ch.qos.logback + logback-classic + + + org.apache.tinkerpop + gremlin-core + + + org.apache.tinkerpop + gremlin-groovy + + + + + org.janusgraph + janusgraph-hbase + 0.1.1 + true + + + org.apache.tinkerpop + gremlin-groovy + + + org.slf4j + slf4j-log4j12 + + + ch.qos.logback + logback-classic + + + org.apache.tinkerpop + gremlin-core + + + + + + + + + org.jacoco + jacoco-maven-plugin + 0.7.9 + + + default-prepare-agent + + prepare-agent + + + + default-report + prepare-package + + report + + + + default-check + + check + + + + + + BUNDLE + + + + INSTRUCTION + COVEREDRATIO + .15 + + + BRANCH + COVEREDRATIO + .14 + + + COMPLEXITY + COVEREDRATIO + .15 + + + LINE + COVEREDRATIO + .18 + + + METHOD + COVEREDRATIO + .10 + + + CLASS + MISSEDCOUNT + 2 + + + + + + + + + + com.mycila + license-maven-plugin + 3.0 + +
License.txt
+ + **/*.java + **/*.ksh + **/*.sh + **/*.ftl + **/*.xsd + **/*.xjb + **/*.yml + **/*.yaml + **/aai*.xml + **/*logback*.xml + **/*aaiconfig*.properties + **/*titan*.properties + +
+ + + + format + + process-sources + + +
+
+
+
diff --git a/champ-lib/champ-janus/src/main/java/org/onap/aai/champjanus/graph/impl/GraphSON.java b/champ-lib/champ-janus/src/main/java/org/onap/aai/champjanus/graph/impl/GraphSON.java new file mode 100644 index 0000000..9e849b8 --- /dev/null +++ b/champ-lib/champ-janus/src/main/java/org/onap/aai/champjanus/graph/impl/GraphSON.java @@ -0,0 +1,66 @@ +/** + * ============LICENSE_START========================================== + * org.onap.aai + * =================================================================== + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 Amdocs + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END============================================ + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.champjanus.graph.impl; + +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +// import com.thinkaurelius.titan.graphdb.tinkerpop.TitanIoRegistry; +import org.janusgraph.graphdb.tinkerpop.JanusGraphIoRegistry; +import org.apache.tinkerpop.gremlin.structure.Direction; +import org.apache.tinkerpop.gremlin.structure.Vertex; +import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONMapper; +import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONWriter; +import org.onap.aai.champcore.FormatMapper; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +public class GraphSON implements FormatMapper { + private final GraphSONMapper mapper; + private final GraphSONWriter writer; + protected JsonParser parser; + + public GraphSON() { + this.mapper = GraphSONMapper.build().addRegistry(JanusGraphIoRegistry.getInstance ()).create(); + this.writer = GraphSONWriter.build().mapper(this.mapper).create(); + this.parser = new JsonParser(); + } + + public JsonObject formatObject(Object v) { + OutputStream os = new ByteArrayOutputStream(); + String result = ""; + + try { + this.writer.writeVertex(os, (Vertex)v, Direction.BOTH); + result = os.toString(); + } catch (IOException var5) { + var5.printStackTrace(); + } + + return this.parser.parse(result).getAsJsonObject(); + } + + public int parallelThreshold() { + return 50; + } +} diff --git a/champ-lib/champ-janus/src/main/java/org/onap/aai/champjanus/graph/impl/JanusChampGraphImpl.java b/champ-lib/champ-janus/src/main/java/org/onap/aai/champjanus/graph/impl/JanusChampGraphImpl.java new file mode 100644 index 0000000..9ede7df --- /dev/null +++ b/champ-lib/champ-janus/src/main/java/org/onap/aai/champjanus/graph/impl/JanusChampGraphImpl.java @@ -0,0 +1,493 @@ +/** + * ============LICENSE_START========================================== + * org.onap.aai + * =================================================================== + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 Amdocs + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END============================================ + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.champjanus.graph.impl; + +import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal; +import org.apache.tinkerpop.gremlin.structure.Edge; +import org.apache.tinkerpop.gremlin.structure.Vertex; +import org.janusgraph.core.*; +import org.onap.aai.champcore.Formatter; +import org.janusgraph.core.schema.JanusGraphIndex; +import org.janusgraph.core.schema.JanusGraphManagement; +import org.janusgraph.core.schema.SchemaAction; +import org.janusgraph.core.schema.SchemaStatus; +import org.janusgraph.graphdb.database.management.ManagementSystem; +import org.onap.aai.champcore.ChampCapabilities; +import org.onap.aai.champcore.FormatMapper; +import org.onap.aai.champcore.exceptions.ChampIndexNotExistsException; +import org.onap.aai.champcore.exceptions.ChampSchemaViolationException; +import org.onap.aai.champcore.graph.impl.AbstractTinkerpopChampGraph; +import org.onap.aai.champcore.model.*; +import org.onap.aai.champcore.schema.ChampSchemaEnforcer; +import org.onap.aai.champcore.schema.DefaultChampSchemaEnforcer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.time.temporal.ChronoUnit; +import java.util.*; +import java.util.concurrent.ExecutionException; +import java.util.stream.Stream; +import java.util.stream.StreamSupport; + +public final class JanusChampGraphImpl extends AbstractTinkerpopChampGraph { + private static final Logger LOGGER = LoggerFactory.getLogger(JanusChampGraphImpl.class); + private static final String JANUS_CASSANDRA_KEYSPACE = "storage.cassandra.keyspace"; + private static final String JANUS_HBASE_TABLE = "storage.hbase.table"; + private static final String JANUS_UNIQUE_SUFFIX = "graph.unique-instance-id-suffix"; + private static final ChampSchemaEnforcer SCHEMA_ENFORCER = new DefaultChampSchemaEnforcer(); + private static final int REGISTER_OBJECT_INDEX_TIMEOUT_SECS = 30; + + private static final ChampCapabilities CAPABILITIES = new ChampCapabilities() { + + @Override + public boolean canDeleteObjectIndices() { + return false; + } + + @Override + public boolean canDeleteRelationshipIndices() { + return false; + } + }; + + private final JanusGraph graph; + + public JanusChampGraphImpl(Builder builder) { + super(builder.graphConfiguration); + final JanusGraphFactory.Builder janusGraphBuilder = JanusGraphFactory.build(); + + for (Map.Entry janusGraphProperty : builder.graphConfiguration.entrySet()) { + janusGraphBuilder.set(janusGraphProperty.getKey(), janusGraphProperty.getValue()); + } + + janusGraphBuilder.set(JANUS_UNIQUE_SUFFIX, ((short) new Random().nextInt(Short.MAX_VALUE)+"")); + + final Object storageBackend = builder.graphConfiguration.get("storage.backend"); + + if ("cassandra".equals(storageBackend) || + "cassandrathrift".equals(storageBackend) || + "astyanax".equals(storageBackend) || + "embeddedcassandra".equals(storageBackend)) { + + janusGraphBuilder.set(JANUS_CASSANDRA_KEYSPACE, builder.graphName); + } else if ("hbase".equals(storageBackend)) { + janusGraphBuilder.set(JANUS_HBASE_TABLE, builder.graphName); + } else if ("berkleyje".equals(storageBackend)) { + throw new RuntimeException("storage.backend=berkleyje cannot handle multiple graphs on a single DB, not usable"); + } else if ("inmemory".equals(storageBackend)) { + } else { + throw new RuntimeException("Unknown storage.backend=" + storageBackend); + } + + LOGGER.info("Instantiated data access layer for Janus graph data store with backend: " + storageBackend); + this.graph = janusGraphBuilder.open(); + } + + public static class Builder { + private final String graphName; + + private final Map graphConfiguration = new HashMap(); + + public Builder(String graphName) { + this.graphName = graphName; + } + + public Builder(String graphName, Map properties) { + this.graphName = graphName; + properties(properties); + } + + public Builder properties(Map properties) { + if (properties.containsKey(JANUS_CASSANDRA_KEYSPACE)) { + throw new IllegalArgumentException("Cannot use path " + JANUS_CASSANDRA_KEYSPACE + + " in initial configuration - this path is used" + + " to specify graph names"); + } + + this.graphConfiguration.putAll(properties); + return this; + } + + public Builder property(String path, Object value) { + if (path.equals(JANUS_CASSANDRA_KEYSPACE)) { + throw new IllegalArgumentException("Cannot use path " + JANUS_CASSANDRA_KEYSPACE + + " in initial configuration - this path is used" + + " to specify graph names"); + } + graphConfiguration.put(path, value); + return this; + } + + public JanusChampGraphImpl build() { + return new JanusChampGraphImpl(this); + } + } + + @Override + protected JanusGraph getGraph() { + return graph; + } + + + @Override + protected ChampSchemaEnforcer getSchemaEnforcer() { + return SCHEMA_ENFORCER; + } + + @Override + public void executeStoreObjectIndex(ChampObjectIndex index) { + if (isShutdown()) { + throw new IllegalStateException("Cannot call storeObjectIndex() after shutdown has been initiated"); + } + + final JanusGraph graph = getGraph(); + final JanusGraphManagement createIndexMgmt = graph.openManagement(); + final PropertyKey pk = createIndexMgmt.getOrCreatePropertyKey(index.getField().getName()); + + if (createIndexMgmt.getGraphIndex(index.getName()) != null) { + createIndexMgmt.rollback(); + return; //Ignore, index already exists + } + + createIndexMgmt.buildIndex(index.getName(), Vertex.class).addKey(pk).buildCompositeIndex(); + + createIndexMgmt.commit(); + graph.tx().commit(); + + awaitIndexCreation(index.getName()); + } + + @Override + public Optional retrieveObjectIndex(String indexName) { + if (isShutdown()) { + throw new IllegalStateException("Cannot call retrieveObjectIndex() after shutdown has been initiated"); + } + + final JanusGraphManagement retrieveIndexMgmt = getGraph().openManagement(); + final JanusGraphIndex index = retrieveIndexMgmt.getGraphIndex(indexName); + + if (index == null) { + return Optional.empty(); + } + if (index.getIndexedElement() != JanusGraphVertex.class) { + return Optional.empty(); + } + + return Optional.of(ChampObjectIndex.create() + .ofName(indexName) + .onType(ChampObject.ReservedTypes.ANY.toString()) + .forField(index.getFieldKeys()[0].name()) + .build()); + } + + @Override + public Stream retrieveObjectIndices() { + if (isShutdown()) { + throw new IllegalStateException("Cannot call retrieveObjectIndices() after shutdown has been initiated"); + } + + final JanusGraphManagement createIndexMgmt = getGraph().openManagement(); + final Iterator indices = createIndexMgmt.getGraphIndexes(Vertex.class).iterator(); + + final Iterator objIter = new Iterator() { + + private ChampObjectIndex next; + + @Override + public boolean hasNext() { + if (indices.hasNext()) { + final JanusGraphIndex index = indices.next(); + + next = ChampObjectIndex.create() + .ofName(index.name()) + .onType(ChampObject.ReservedTypes.ANY.toString()) + .forField(index.getFieldKeys()[0].name()) + .build(); + return true; + } + + next = null; + return false; + } + + @Override + public ChampObjectIndex next() { + if (next == null) { + throw new NoSuchElementException(); + } + + return next; + } + }; + + return StreamSupport.stream(Spliterators.spliteratorUnknownSize( + objIter, Spliterator.ORDERED | Spliterator.NONNULL), false); + } + + @Override + public void executeDeleteObjectIndex(String indexName) throws ChampIndexNotExistsException { + if (isShutdown()) { + throw new IllegalStateException("Cannot call deleteObjectIndex() after shutdown has been initiated"); + } + + throw new UnsupportedOperationException("Cannot delete indices using the JanusChampImpl"); + } + + @Override + public void executeStoreRelationshipIndex(ChampRelationshipIndex index) { + if (isShutdown()) { + throw new IllegalStateException("Cannot call storeRelationshipIndex() after shutdown has been initiated"); + } + + final JanusGraph graph = getGraph(); + final JanusGraphManagement createIndexMgmt = graph.openManagement(); + final PropertyKey pk = createIndexMgmt.getOrCreatePropertyKey(index.getField().getName()); + + if (createIndexMgmt.getGraphIndex(index.getName()) != null) { + return; //Ignore, index already exists + } + createIndexMgmt.buildIndex(index.getName(), Edge.class).addKey(pk).buildCompositeIndex(); + + createIndexMgmt.commit(); + graph.tx().commit(); + + awaitIndexCreation(index.getName()); + } + + @Override + public Optional retrieveRelationshipIndex(String indexName) { + if (isShutdown()) { + throw new IllegalStateException("Cannot call retrieveRelationshipIndex() after shutdown has been initiated"); + } + + final JanusGraphManagement retrieveIndexMgmt = getGraph().openManagement(); + final JanusGraphIndex index = retrieveIndexMgmt.getGraphIndex(indexName); + + if (index == null) { + return Optional.empty(); + } + if (index.getIndexedElement() != JanusGraphEdge.class) { + return Optional.empty(); + } + + return Optional.of(ChampRelationshipIndex.create() + .ofName(indexName) + .onType(ChampObject.ReservedTypes.ANY.toString()) + .forField(index.getFieldKeys()[0].name()) + .build()); + } + + @Override + public Stream retrieveRelationshipIndices() { + if (isShutdown()) { + throw new IllegalStateException("Cannot call retrieveRelationshipIndices() after shutdown has been initiated"); + } + + final JanusGraphManagement createIndexMgmt = getGraph().openManagement(); + final Iterator indices = createIndexMgmt.getGraphIndexes(Edge.class).iterator(); + + final Iterator objIter = new Iterator() { + + private ChampRelationshipIndex next; + + @Override + public boolean hasNext() { + if (indices.hasNext()) { + final JanusGraphIndex index = indices.next(); + + next = ChampRelationshipIndex.create() + .ofName(index.name()) + .onType(ChampRelationship.ReservedTypes.ANY.toString()) + .forField(index.getFieldKeys()[0].name()) + .build(); + return true; + } + + next = null; + return false; + } + + @Override + public ChampRelationshipIndex next() { + if (next == null) { + throw new NoSuchElementException(); + } + + return next; + } + }; + + return StreamSupport.stream(Spliterators.spliteratorUnknownSize( + objIter, Spliterator.ORDERED | Spliterator.NONNULL), false); + } + + @Override + public void executeDeleteRelationshipIndex(String indexName) throws ChampIndexNotExistsException { + if (isShutdown()) { + throw new IllegalStateException("Cannot call deleteRelationshipIndex() after shutdown has been initiated"); + } + + throw new UnsupportedOperationException("Cannot delete indices using the JanusChampImpl"); + } + + private Cardinality getJanusCardinality(ChampCardinality cardinality) { + switch (cardinality) { + case LIST: + return Cardinality.LIST; + case SET: + return Cardinality.SET; + case SINGLE: + return Cardinality.SINGLE; + default: + throw new RuntimeException("Unknown ChampCardinality " + cardinality); + } + } + + private void awaitIndexCreation(String indexName) { + //Wait for the index to become available + try { + if (ManagementSystem.awaitGraphIndexStatus(graph, indexName) + .status(SchemaStatus.ENABLED) + .timeout(1, ChronoUnit.SECONDS) + .call() + .getSucceeded()) { + return; //Empty graphs immediately ENABLE indices + } + + if (!ManagementSystem.awaitGraphIndexStatus(graph, indexName) + .status(SchemaStatus.REGISTERED) + .timeout(REGISTER_OBJECT_INDEX_TIMEOUT_SECS, ChronoUnit.SECONDS) + .call() + .getSucceeded()) { + LOGGER.warn("Object index was created, but timed out while waiting for it to be registered"); + return; + } + } catch (InterruptedException e) { + LOGGER.warn("Interrupted while waiting for object index creation status"); + return; + } + + //Reindex the existing data + + try { + final JanusGraphManagement updateIndexMgmt = graph.openManagement(); + updateIndexMgmt.updateIndex(updateIndexMgmt.getGraphIndex(indexName), SchemaAction.REINDEX).get(); + updateIndexMgmt.commit(); + } catch (InterruptedException e) { + LOGGER.warn("Interrupted while reindexing for object index"); + return; + } catch (ExecutionException e) { + LOGGER.warn("Exception occurred during reindexing procedure for creating object index " + indexName, e); + } + + try { + ManagementSystem.awaitGraphIndexStatus(graph, indexName) + .status(SchemaStatus.ENABLED) + .timeout(10, ChronoUnit.MINUTES) + .call(); + } catch (InterruptedException e) { + LOGGER.warn("Interrupted while waiting for index to transition to ENABLED state"); + return; + } + } + + @Override + public ChampCapabilities capabilities() { + return CAPABILITIES; + } + + public void storeSchema(ChampSchema schema) throws ChampSchemaViolationException { + if (isShutdown()) throw new IllegalStateException("Cannot call storeSchema() after shutdown has been initiated"); + + final ChampSchema currentSchema = retrieveSchema(); + final JanusGraphManagement mgmt = getGraph().openManagement(); + + try { + for (ChampObjectConstraint objConstraint : schema.getObjectConstraints().values()) { + for (ChampPropertyConstraint propConstraint : objConstraint.getPropertyConstraints()) { + final Optional currentObjConstraint = currentSchema.getObjectConstraint(objConstraint.getType()); + + if (currentObjConstraint.isPresent()) { + final Optional currentPropConstraint = currentObjConstraint.get().getPropertyConstraint(propConstraint.getField().getName()); + + if (currentPropConstraint.isPresent() && currentPropConstraint.get().compareTo(propConstraint) != 0) { + throw new ChampSchemaViolationException("Cannot update already existing property on object type " + objConstraint.getType() + ": " + propConstraint); + } + } + + final String newPropertyKeyName = propConstraint.getField().getName(); + + if (mgmt.getPropertyKey(newPropertyKeyName) != null) continue; //Check Janus to see if another node created this property key + + mgmt.makePropertyKey(newPropertyKeyName) + .dataType(propConstraint.getField().getJavaType()) + .cardinality(getJanusCardinality(propConstraint.getCardinality())) + .make(); + } + } + + for (ChampRelationshipConstraint relConstraint : schema.getRelationshipConstraints().values()) { + + final Optional currentRelConstraint = currentSchema.getRelationshipConstraint(relConstraint.getType()); + + for (ChampPropertyConstraint propConstraint : relConstraint.getPropertyConstraints()) { + + if (currentRelConstraint.isPresent()) { + final Optional currentPropConstraint = currentRelConstraint.get().getPropertyConstraint(propConstraint.getField().getName()); + + if (currentPropConstraint.isPresent() && currentPropConstraint.get().compareTo(propConstraint) != 0) { + throw new ChampSchemaViolationException("Cannot update already existing property on relationship type " + relConstraint.getType()); + } + } + + final String newPropertyKeyName = propConstraint.getField().getName(); + + if (mgmt.getPropertyKey(newPropertyKeyName) != null) continue; //Check Janus to see if another node created this property key + + mgmt.makePropertyKey(newPropertyKeyName) + .dataType(propConstraint.getField().getJavaType()) + .cardinality(getJanusCardinality(propConstraint.getCardinality())) + .make(); + } + + final EdgeLabel edgeLabel = mgmt.getEdgeLabel(relConstraint.getType()); + + if (edgeLabel != null) { + mgmt.makeEdgeLabel(relConstraint.getType()) + .directed() + .make(); + } + } + + mgmt.commit(); + + super.storeSchema(schema); + } catch (SchemaViolationException | ChampSchemaViolationException e) { + mgmt.rollback(); + throw new ChampSchemaViolationException(e); + } + } + + public GraphTraversal hasLabel(GraphTraversal query, Object type) { + return query.hasLabel(type); + } +} \ No newline at end of file diff --git a/champ-lib/champ-janus/src/test/java/org/onap/aai/champjanus/concurrency/ConcurrencyTest.java b/champ-lib/champ-janus/src/test/java/org/onap/aai/champjanus/concurrency/ConcurrencyTest.java new file mode 100644 index 0000000..68e1a1a --- /dev/null +++ b/champ-lib/champ-janus/src/test/java/org/onap/aai/champjanus/concurrency/ConcurrencyTest.java @@ -0,0 +1,33 @@ +/** + * ============LICENSE_START========================================== + * org.onap.aai + * =================================================================== + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 Amdocs + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END============================================ + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.champjanus.concurrency; + +import org.junit.Test; + +public class ConcurrencyTest { + + @Test + public void runInMemoryConcurrentTest() { + org.onap.aai.champcore.concurrency.ConcurrencyTest baseTest = new org.onap.aai.champcore.concurrency.ConcurrencyTest(); + baseTest.runConcurrentTest("JANUS"); + } +} diff --git a/champ-lib/champ-janus/src/test/java/org/onap/aai/champjanus/core/ChampAPITest.java b/champ-lib/champ-janus/src/test/java/org/onap/aai/champjanus/core/ChampAPITest.java new file mode 100644 index 0000000..4fd9e4a --- /dev/null +++ b/champ-lib/champ-janus/src/test/java/org/onap/aai/champjanus/core/ChampAPITest.java @@ -0,0 +1,38 @@ +/** + * ============LICENSE_START========================================== + * org.onap.aai + * =================================================================== + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 Amdocs + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END============================================ + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.champjanus.core; + +import org.junit.Test; +import org.onap.aai.champjanus.graph.impl.JanusChampGraphImpl; + +public class ChampAPITest { + @Test + public void testChampGraphInstantiation() throws Exception { + JanusChampGraphImpl graph = new JanusChampGraphImpl.Builder("testGraph") + .property("storage.backend", "inmemory") + .build(); + + org.onap.aai.champcore.core.ChampAPITest baseTest = new org.onap.aai.champcore.core.ChampAPITest(); + + baseTest.testChampGraphInstantiation(graph); + } +} diff --git a/champ-lib/champ-janus/src/test/java/org/onap/aai/champjanus/core/ChampObjectIndexTest.java b/champ-lib/champ-janus/src/test/java/org/onap/aai/champjanus/core/ChampObjectIndexTest.java new file mode 100644 index 0000000..bd031ef --- /dev/null +++ b/champ-lib/champ-janus/src/test/java/org/onap/aai/champjanus/core/ChampObjectIndexTest.java @@ -0,0 +1,46 @@ +/** + * ============LICENSE_START========================================== + * org.onap.aai + * =================================================================== + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 Amdocs + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END============================================ + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.champjanus.core; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.onap.aai.champjanus.graph.impl.JanusChampGraphImpl; + +public class ChampObjectIndexTest { + @Rule + public final ExpectedException exception = ExpectedException.none(); + + @Test + public void testChampObjectIndexCrud() throws Exception { + JanusChampGraphImpl graph = new JanusChampGraphImpl.Builder("testGraph") + .property("storage.backend", "inmemory") + .build(); + + org.onap.aai.champcore.core.ChampObjectIndexTest.testChampObjectIndexCrud(graph); + + graph.shutdown(); + + exception.expect(IllegalStateException.class); + graph.executeDeleteObjectIndex("any"); + } +} diff --git a/champ-lib/champ-janus/src/test/java/org/onap/aai/champjanus/core/ChampRelationshipIndexTest.java b/champ-lib/champ-janus/src/test/java/org/onap/aai/champjanus/core/ChampRelationshipIndexTest.java new file mode 100644 index 0000000..bbfb585 --- /dev/null +++ b/champ-lib/champ-janus/src/test/java/org/onap/aai/champjanus/core/ChampRelationshipIndexTest.java @@ -0,0 +1,38 @@ +/** + * ============LICENSE_START========================================== + * org.onap.aai + * =================================================================== + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 Amdocs + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END============================================ + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.champjanus.core; + +import org.junit.Test; +import org.onap.aai.champjanus.graph.impl.JanusChampGraphImpl; + +public class ChampRelationshipIndexTest { + @Test + public void testChampRelationshipIndexCrud() { + JanusChampGraphImpl graph = new JanusChampGraphImpl.Builder("testGraph") + .property("storage.backend", "inmemory") + .build(); + org.onap.aai.champcore.core.ChampRelationshipIndexTest baseTest = new org.onap.aai.champcore.core.ChampRelationshipIndexTest(); + baseTest.testChampRelationshipIndexCrud(graph); + + graph.shutdown(); + } +} diff --git a/champ-lib/champ-janus/src/test/java/org/onap/aai/champjanus/core/ChampSchemaTest.java b/champ-lib/champ-janus/src/test/java/org/onap/aai/champjanus/core/ChampSchemaTest.java new file mode 100644 index 0000000..96ffb25 --- /dev/null +++ b/champ-lib/champ-janus/src/test/java/org/onap/aai/champjanus/core/ChampSchemaTest.java @@ -0,0 +1,37 @@ +/** + * ============LICENSE_START========================================== + * org.onap.aai + * =================================================================== + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 Amdocs + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END============================================ + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.champjanus.core; + +import org.junit.Test; +import org.onap.aai.champjanus.graph.impl.JanusChampGraphImpl; + +public class ChampSchemaTest { + @Test + public void testChampSchemaCrud() { + JanusChampGraphImpl graph = new JanusChampGraphImpl.Builder("testGraph") + .property("storage.backend", "inmemory") + .build(); + org.onap.aai.champcore.core.ChampSchemaTest.testChampSchemaCrud(graph); + + graph.shutdown(); + } +} diff --git a/champ-lib/champ-janus/src/test/java/org/onap/aai/champjanus/core/JanusChampSetupTest.java b/champ-lib/champ-janus/src/test/java/org/onap/aai/champjanus/core/JanusChampSetupTest.java new file mode 100644 index 0000000..3cca54d --- /dev/null +++ b/champ-lib/champ-janus/src/test/java/org/onap/aai/champjanus/core/JanusChampSetupTest.java @@ -0,0 +1,74 @@ +/** + * ============LICENSE_START========================================== + * org.onap.aai + * =================================================================== + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 Amdocs + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END============================================ + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.champjanus.core; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.onap.aai.champjanus.graph.impl.JanusChampGraphImpl; + +import java.util.HashMap; +import java.util.Map; + +public class JanusChampSetupTest { + @Rule + public final ExpectedException exception = ExpectedException.none(); + + @Test + public void JanusSetupBadBackendTest() { + exception.expect(RuntimeException.class); + JanusChampGraphImpl graph = new JanusChampGraphImpl.Builder("testGraph") + .property("storage.backend", "bad-backend") + .build(); + } + + @Test + public void JanusSetupBerkleyBackendTest() { + exception.expect(RuntimeException.class); + Map propertiesMap = new HashMap(); + propertiesMap.put("storage.backend", "berkleyje"); + JanusChampGraphImpl graph = new JanusChampGraphImpl.Builder("testGraph") + .properties(propertiesMap) + .build(); + } + + @Test + public void JanusSetupBadPropertyTest() { + exception.expect(RuntimeException.class); + JanusChampGraphImpl graph = new JanusChampGraphImpl.Builder("testGraph") + .property("storage.backend", "in-memory") + .property("storage.cassandra.keyspace", "anything") + .build(); + } + + @Test + public void JanusSetupBadPropertiesTest() { + exception.expect(RuntimeException.class); + Map propertiesMap = new HashMap(); + propertiesMap.put("storage.cassandra.keyspace", "anything"); + + JanusChampGraphImpl graph = new JanusChampGraphImpl.Builder("testGraph") + .property("storage.backend", "in-memory") + .properties(propertiesMap) + .build(); + } +} diff --git a/champ-lib/champ-titan/License.txt b/champ-lib/champ-titan/License.txt new file mode 100644 index 0000000..469f362 --- /dev/null +++ b/champ-lib/champ-titan/License.txt @@ -0,0 +1,21 @@ +============LICENSE_START========================================== +org.onap.aai +=================================================================== +Copyright © 2017 AT&T Intellectual Property. All rights reserved. +Copyright © 2017 Amdocs +=================================================================== +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +============LICENSE_END============================================ +ECOMP is a trademark and service mark of AT&T Intellectual Property. + + diff --git a/champ-lib/champ-titan/pom.xml b/champ-lib/champ-titan/pom.xml new file mode 100644 index 0000000..72d5039 --- /dev/null +++ b/champ-lib/champ-titan/pom.xml @@ -0,0 +1,188 @@ + + + 4.0.0 + + + champ-lib + org.onap.aai + 1.2.0-SNAPSHOT + + + champ-titan + + + 3.0.1-incubating + + + + + org.apache.tinkerpop + tinkergraph-gremlin + ${tinkerpop.version} + + + org.onap.aai + champ-core + 1.2.0-SNAPSHOT + + + org.onap.aai + champ-core + 1.2.0-SNAPSHOT + test-jar + test + + + com.thinkaurelius.titan + titan-cassandra + 1.0.0 + true + + + org.apache.tinkerpop + gremlin-groovy + + + org.slf4j + slf4j-log4j12 + + + ch.qos.logback + logback-classic + + + org.apache.tinkerpop + gremlin-core + + + + + com.thinkaurelius.titan + titan-hbase + 1.0.0 + true + + + org.apache.tinkerpop + gremlin-groovy + + + org.slf4j + slf4j-log4j12 + + + ch.qos.logback + logback-classic + + + org.apache.tinkerpop + gremlin-core + + + + + + + + + org.jacoco + jacoco-maven-plugin + 0.7.9 + + + default-prepare-agent + + prepare-agent + + + + default-report + prepare-package + + report + + + + default-check + + check + + + + + + BUNDLE + + + + INSTRUCTION + COVEREDRATIO + .15 + + + BRANCH + COVEREDRATIO + .14 + + + COMPLEXITY + COVEREDRATIO + .15 + + + LINE + COVEREDRATIO + .18 + + + METHOD + COVEREDRATIO + .10 + + + CLASS + MISSEDCOUNT + 2 + + + + + + + + + + com.mycila + license-maven-plugin + 3.0 + +
License.txt
+ + **/*.java + **/*.ksh + **/*.sh + **/*.ftl + **/*.xsd + **/*.xjb + **/*.yml + **/*.yaml + **/aai*.xml + **/*logback*.xml + **/*aaiconfig*.properties + **/*titan*.properties + +
+ + + + format + + process-sources + + +
+
+
+
diff --git a/champ-lib/champ-titan/src/main/java/org/onap/aai/champtitan/graph/impl/GraphSON.java b/champ-lib/champ-titan/src/main/java/org/onap/aai/champtitan/graph/impl/GraphSON.java new file mode 100644 index 0000000..e36bd53 --- /dev/null +++ b/champ-lib/champ-titan/src/main/java/org/onap/aai/champtitan/graph/impl/GraphSON.java @@ -0,0 +1,66 @@ +/** + * ============LICENSE_START========================================== + * org.onap.aai + * =================================================================== + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 Amdocs + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END============================================ + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.champtitan.graph.impl; + +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import com.thinkaurelius.titan.graphdb.tinkerpop.TitanIoRegistry; +import org.apache.tinkerpop.gremlin.structure.Direction; +import org.apache.tinkerpop.gremlin.structure.Vertex; +import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONMapper; +import org.apache.tinkerpop.gremlin.structure.io.graphson.GraphSONWriter; +import org.onap.aai.champcore.FormatMapper; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +public class GraphSON implements FormatMapper { + private final GraphSONMapper mapper; + private final GraphSONWriter writer; + protected JsonParser parser; + + public GraphSON() { + this.mapper = GraphSONMapper.build().addRegistry(TitanIoRegistry.INSTANCE).create(); + this.writer = GraphSONWriter.build().mapper(this.mapper).create(); + this.parser = new JsonParser(); + } + + public JsonObject formatObject(Object v) { + OutputStream os = new ByteArrayOutputStream(); + String result = ""; + + try { + this.writer.writeVertex(os, (Vertex)v, Direction.BOTH); + result = os.toString(); + } catch (IOException var5) { + var5.printStackTrace(); + } + + return this.parser.parse(result).getAsJsonObject(); + } + + public int parallelThreshold() { + return 50; + } + +} diff --git a/champ-lib/champ-titan/src/main/java/org/onap/aai/champtitan/graph/impl/TitanChampGraphImpl.java b/champ-lib/champ-titan/src/main/java/org/onap/aai/champtitan/graph/impl/TitanChampGraphImpl.java new file mode 100644 index 0000000..56434be --- /dev/null +++ b/champ-lib/champ-titan/src/main/java/org/onap/aai/champtitan/graph/impl/TitanChampGraphImpl.java @@ -0,0 +1,474 @@ +/** + * ============LICENSE_START========================================== + * org.onap.aai + * =================================================================== + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 Amdocs + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END============================================ + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.champtitan.graph.impl; + +import java.time.temporal.ChronoUnit; +import java.util.*; +import java.util.Map.Entry; +import java.util.concurrent.ExecutionException; +import java.util.stream.Stream; +import java.util.stream.StreamSupport; + +import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal; +import org.apache.tinkerpop.gremlin.structure.Edge; +import org.apache.tinkerpop.gremlin.structure.Vertex; +import org.onap.aai.champcore.ChampCapabilities; +import org.onap.aai.champcore.FormatMapper; +import org.onap.aai.champcore.Formatter; +import org.onap.aai.champcore.exceptions.ChampIndexNotExistsException; +import org.onap.aai.champcore.exceptions.ChampSchemaViolationException; +import org.onap.aai.champcore.graph.impl.AbstractTinkerpopChampGraph; +import org.onap.aai.champcore.model.ChampCardinality; +import org.onap.aai.champcore.model.ChampObject; +import org.onap.aai.champcore.model.ChampObjectConstraint; +import org.onap.aai.champcore.model.ChampObjectIndex; +import org.onap.aai.champcore.model.ChampPropertyConstraint; +import org.onap.aai.champcore.model.ChampRelationship; +import org.onap.aai.champcore.model.ChampRelationshipConstraint; +import org.onap.aai.champcore.model.ChampRelationshipIndex; +import org.onap.aai.champcore.model.ChampSchema; +import org.onap.aai.champcore.schema.ChampSchemaEnforcer; +import org.onap.aai.champcore.schema.DefaultChampSchemaEnforcer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.thinkaurelius.titan.core.Cardinality; +import com.thinkaurelius.titan.core.EdgeLabel; +import com.thinkaurelius.titan.core.PropertyKey; +import com.thinkaurelius.titan.core.SchemaViolationException; +import com.thinkaurelius.titan.core.TitanEdge; +import com.thinkaurelius.titan.core.TitanFactory; +import com.thinkaurelius.titan.core.TitanGraph; +import com.thinkaurelius.titan.core.TitanVertex; +import com.thinkaurelius.titan.core.schema.SchemaAction; +import com.thinkaurelius.titan.core.schema.SchemaStatus; +import com.thinkaurelius.titan.core.schema.TitanGraphIndex; +import com.thinkaurelius.titan.core.schema.TitanManagement; +import com.thinkaurelius.titan.graphdb.database.management.ManagementSystem; + +public final class TitanChampGraphImpl extends AbstractTinkerpopChampGraph { + + private static final Logger LOGGER = LoggerFactory.getLogger(TitanChampGraphImpl.class); + private static final String TITAN_UNIQUE_SUFFIX = "graph.unique-instance-id-suffix"; + private static final String TITAN_CASSANDRA_KEYSPACE = "storage.cassandra.keyspace"; + private static final String TITAN_HBASE_TABLE = "storage.hbase.table"; + private static final ChampSchemaEnforcer SCHEMA_ENFORCER = new DefaultChampSchemaEnforcer(); + private static final int REGISTER_OBJECT_INDEX_TIMEOUT_SECS = 30; + + private static final ChampCapabilities CAPABILITIES = new ChampCapabilities() { + + @Override + public boolean canDeleteObjectIndices() { + return false; + } + + @Override + public boolean canDeleteRelationshipIndices() { + return false; + } + }; + + private final TitanGraph graph; + + public TitanChampGraphImpl(Builder builder) { + super(builder.graphConfiguration); + final TitanFactory.Builder titanGraphBuilder = TitanFactory.build(); + + for (Entry titanGraphProperty : builder.graphConfiguration.entrySet()) { + titanGraphBuilder.set(titanGraphProperty.getKey(), titanGraphProperty.getValue()); + } + + titanGraphBuilder.set(TITAN_UNIQUE_SUFFIX, ((short) new Random().nextInt(Short.MAX_VALUE)+"")); + + final Object storageBackend = builder.graphConfiguration.get("storage.backend"); + + if ("cassandra".equals(storageBackend) || + "cassandrathrift".equals(storageBackend) || + "astyanax".equals(storageBackend) || + "embeddedcassandra".equals(storageBackend)) { + titanGraphBuilder.set(TITAN_CASSANDRA_KEYSPACE, builder.graphName); + } else if ("hbase".equals(storageBackend)) { + titanGraphBuilder.set(TITAN_HBASE_TABLE, builder.graphName); + } else if ("berkleyje".equals(storageBackend)) { + throw new RuntimeException("storage.backend=berkleyje cannot handle multiple graphs on a single DB, not usable"); + } else if ("inmemory".equals(storageBackend)) { + } else { + throw new RuntimeException("Unknown storage.backend=" + storageBackend); + } + + LOGGER.info("Instantiated data access layer for Titan graph data store with backend: " + storageBackend); + + this.graph = titanGraphBuilder.open(); + } + + public static class Builder { + private final String graphName; + + private final Map graphConfiguration = new HashMap (); + + public Builder(String graphName) { + this.graphName = graphName; + } + + public Builder(String graphName, Map properties) { + this.graphName = graphName; + properties(properties); + } + + public Builder properties(Map properties) { + if (properties.containsKey(TITAN_CASSANDRA_KEYSPACE)) + throw new IllegalArgumentException("Cannot use path " + TITAN_CASSANDRA_KEYSPACE + + " in initial configuration - this path is used" + + " to specify graph names"); + + this.graphConfiguration.putAll(properties); + return this; + } + + public Builder property(String path, Object value) { + if (path.equals(TITAN_CASSANDRA_KEYSPACE)) + throw new IllegalArgumentException("Cannot use path " + TITAN_CASSANDRA_KEYSPACE + + " in initial configuration - this path is used" + + " to specify graph names"); + graphConfiguration.put(path, value); + return this; + } + + public TitanChampGraphImpl build() { + return new TitanChampGraphImpl(this); + } + } + + @Override + protected TitanGraph getGraph() { + return graph; + } + + @Override + protected ChampSchemaEnforcer getSchemaEnforcer() { + return SCHEMA_ENFORCER; + } + + public void executeStoreObjectIndex(ChampObjectIndex index) { + if (isShutdown()) throw new IllegalStateException("Cannot call storeObjectIndex() after shutdown has been initiated"); + + final TitanGraph graph = getGraph(); + final TitanManagement createIndexMgmt = graph.openManagement(); + final PropertyKey pk = createIndexMgmt.getOrCreatePropertyKey(index.getField().getName()); + + if (createIndexMgmt.getGraphIndex(index.getName()) != null) { + createIndexMgmt.rollback(); + return; //Ignore, index already exists + } + + createIndexMgmt.buildIndex(index.getName(), Vertex.class).addKey(pk).buildCompositeIndex(); + + createIndexMgmt.commit(); + graph.tx().commit(); + + awaitIndexCreation(index.getName()); + } + + @Override + public Optional retrieveObjectIndex(String indexName) { + if (isShutdown()) throw new IllegalStateException("Cannot call retrieveObjectIndex() after shutdown has been initiated"); + + final TitanManagement retrieveIndexMgmt = getGraph().openManagement(); + final TitanGraphIndex index = retrieveIndexMgmt.getGraphIndex(indexName); + + if (index == null) return Optional.empty(); + if (index.getIndexedElement() != TitanVertex.class) return Optional.empty(); + + return Optional.of(ChampObjectIndex.create() + .ofName(indexName) + .onType(ChampObject.ReservedTypes.ANY.toString()) + .forField(index.getFieldKeys()[0].name()) + .build()); + } + + @Override + public Stream retrieveObjectIndices() { + if (isShutdown()) throw new IllegalStateException("Cannot call retrieveObjectIndices() after shutdown has been initiated"); + + final TitanManagement createIndexMgmt = getGraph().openManagement(); + final Iterator indices = createIndexMgmt.getGraphIndexes(Vertex.class).iterator(); + + final Iterator objIter = new Iterator () { + + private ChampObjectIndex next; + + @Override + public boolean hasNext() { + if (indices.hasNext()) { + final TitanGraphIndex index = indices.next(); + + next = ChampObjectIndex.create() + .ofName(index.name()) + .onType(ChampObject.ReservedTypes.ANY.toString()) + .forField(index.getFieldKeys()[0].name()) + .build(); + return true; + } + + next = null; + return false; + } + + @Override + public ChampObjectIndex next() { + if (next == null) throw new NoSuchElementException(); + + return next; + } + }; + + return StreamSupport.stream(Spliterators.spliteratorUnknownSize( + objIter, Spliterator.ORDERED | Spliterator.NONNULL), false); + } + + public void executeDeleteObjectIndex(String indexName) throws ChampIndexNotExistsException { + if (isShutdown()) throw new IllegalStateException("Cannot call deleteObjectIndex() after shutdown has been initiated"); + + throw new UnsupportedOperationException("Cannot delete indices using the TitanChampImpl"); + } + + public void executeStoreRelationshipIndex(ChampRelationshipIndex index) { + if (isShutdown()) throw new IllegalStateException("Cannot call storeRelationshipIndex() after shutdown has been initiated"); + + final TitanGraph graph = getGraph(); + final TitanManagement createIndexMgmt = graph.openManagement(); + final PropertyKey pk = createIndexMgmt.getOrCreatePropertyKey(index.getField().getName()); + + if (createIndexMgmt.getGraphIndex(index.getName()) != null) return; //Ignore, index already exists + createIndexMgmt.buildIndex(index.getName(), Edge.class).addKey(pk).buildCompositeIndex(); + + createIndexMgmt.commit(); + graph.tx().commit(); + + awaitIndexCreation(index.getName()); + } + + @Override + public Optional retrieveRelationshipIndex(String indexName) { + if (isShutdown()) throw new IllegalStateException("Cannot call retrieveRelationshipIndex() after shutdown has been initiated"); + + final TitanManagement retrieveIndexMgmt = getGraph().openManagement(); + final TitanGraphIndex index = retrieveIndexMgmt.getGraphIndex(indexName); + + if (index == null) return Optional.empty(); + if (index.getIndexedElement() != TitanEdge.class) return Optional.empty(); + + return Optional.of(ChampRelationshipIndex.create() + .ofName(indexName) + .onType(ChampObject.ReservedTypes.ANY.toString()) + .forField(index.getFieldKeys()[0].name()) + .build()); + } + + @Override + public Stream retrieveRelationshipIndices() { + if (isShutdown()) throw new IllegalStateException("Cannot call retrieveRelationshipIndices() after shutdown has been initiated"); + + final TitanManagement createIndexMgmt = getGraph().openManagement(); + final Iterator indices = createIndexMgmt.getGraphIndexes(Edge.class).iterator(); + + final Iterator objIter = new Iterator () { + + private ChampRelationshipIndex next; + + @Override + public boolean hasNext() { + if (indices.hasNext()) { + final TitanGraphIndex index = indices.next(); + + next = ChampRelationshipIndex.create() + .ofName(index.name()) + .onType(ChampRelationship.ReservedTypes.ANY.toString()) + .forField(index.getFieldKeys()[0].name()) + .build(); + return true; + } + + next = null; + return false; + } + + @Override + public ChampRelationshipIndex next() { + if (next == null) throw new NoSuchElementException(); + + return next; + } + }; + + return StreamSupport.stream(Spliterators.spliteratorUnknownSize( + objIter, Spliterator.ORDERED | Spliterator.NONNULL), false); + } + + public void executeDeleteRelationshipIndex(String indexName) throws ChampIndexNotExistsException { + if (isShutdown()) throw new IllegalStateException("Cannot call deleteRelationshipIndex() after shutdown has been initiated"); + + throw new UnsupportedOperationException("Cannot delete indices using the TitanChampImpl"); + } + + private Cardinality getTitanCardinality(ChampCardinality cardinality) { + switch (cardinality) { + case LIST: + return Cardinality.LIST; + case SET: + return Cardinality.SET; + case SINGLE: + return Cardinality.SINGLE; + default: + throw new RuntimeException("Unknown ChampCardinality " + cardinality); + } + } + + private void awaitIndexCreation(String indexName) { + //Wait for the index to become available + try { + if (ManagementSystem.awaitGraphIndexStatus(graph, indexName) + .status(SchemaStatus.ENABLED) + .timeout(1, ChronoUnit.SECONDS) + .call() + .getSucceeded()) { + return; //Empty graphs immediately ENABLE indices + } + + if (!ManagementSystem.awaitGraphIndexStatus(graph, indexName) + .status(SchemaStatus.REGISTERED) + .timeout(REGISTER_OBJECT_INDEX_TIMEOUT_SECS, ChronoUnit.SECONDS) + .call() + .getSucceeded()) { + LOGGER.warn("Object index was created, but timed out while waiting for it to be registered"); + return; + } + } catch (InterruptedException e) { + LOGGER.warn("Interrupted while waiting for object index creation status"); + return; + } + + //Reindex the existing data + + try { + final TitanManagement updateIndexMgmt = graph.openManagement(); + updateIndexMgmt.updateIndex(updateIndexMgmt.getGraphIndex(indexName),SchemaAction.REINDEX).get(); + updateIndexMgmt.commit(); + } catch (InterruptedException e) { + LOGGER.warn("Interrupted while reindexing for object index"); + return; + } catch (ExecutionException e) { + LOGGER.warn("Exception occurred during reindexing procedure for creating object index " + indexName, e); + } + + try { + ManagementSystem.awaitGraphIndexStatus(graph, indexName) + .status(SchemaStatus.ENABLED) + .timeout(10, ChronoUnit.MINUTES) + .call(); + } catch (InterruptedException e) { + LOGGER.warn("Interrupted while waiting for index to transition to ENABLED state"); + return; + } + } + + @Override + public ChampCapabilities capabilities() { + return CAPABILITIES; + } + + @Override + public void storeSchema(ChampSchema schema) throws ChampSchemaViolationException { + if (isShutdown()) throw new IllegalStateException("Cannot call storeSchema() after shutdown has been initiated"); + + final ChampSchema currentSchema = retrieveSchema(); + final TitanManagement mgmt = getGraph().openManagement(); + + try { + for (ChampObjectConstraint objConstraint : schema.getObjectConstraints().values()) { + for (ChampPropertyConstraint propConstraint : objConstraint.getPropertyConstraints()) { + final Optional currentObjConstraint = currentSchema.getObjectConstraint(objConstraint.getType()); + + if (currentObjConstraint.isPresent()) { + final Optional currentPropConstraint = currentObjConstraint.get().getPropertyConstraint(propConstraint.getField().getName()); + + if (currentPropConstraint.isPresent() && currentPropConstraint.get().compareTo(propConstraint) != 0) { + throw new ChampSchemaViolationException("Cannot update already existing property on object type " + objConstraint.getType() + ": " + propConstraint); + } + } + + final String newPropertyKeyName = propConstraint.getField().getName(); + + if (mgmt.getPropertyKey(newPropertyKeyName) != null) continue; //Check Titan to see if another node created this property key + + mgmt.makePropertyKey(newPropertyKeyName) + .dataType(propConstraint.getField().getJavaType()) + .cardinality(getTitanCardinality(propConstraint.getCardinality())) + .make(); + } + } + + for (ChampRelationshipConstraint relConstraint : schema.getRelationshipConstraints().values()) { + + final Optional currentRelConstraint = currentSchema.getRelationshipConstraint(relConstraint.getType()); + + for (ChampPropertyConstraint propConstraint : relConstraint.getPropertyConstraints()) { + + if (currentRelConstraint.isPresent()) { + final Optional currentPropConstraint = currentRelConstraint.get().getPropertyConstraint(propConstraint.getField().getName()); + + if (currentPropConstraint.isPresent() && currentPropConstraint.get().compareTo(propConstraint) != 0) { + throw new ChampSchemaViolationException("Cannot update already existing property on relationship type " + relConstraint.getType()); + } + } + + final String newPropertyKeyName = propConstraint.getField().getName(); + + if (mgmt.getPropertyKey(newPropertyKeyName) != null) continue; //Check Titan to see if another node created this property key + + mgmt.makePropertyKey(newPropertyKeyName) + .dataType(propConstraint.getField().getJavaType()) + .cardinality(getTitanCardinality(propConstraint.getCardinality())) + .make(); + } + + final EdgeLabel edgeLabel = mgmt.getEdgeLabel(relConstraint.getType()); + + if (edgeLabel != null) mgmt.makeEdgeLabel(relConstraint.getType()) + .directed() + .make(); + } + + mgmt.commit(); + + super.storeSchema(schema); + } catch (SchemaViolationException | ChampSchemaViolationException e) { + mgmt.rollback(); + throw new ChampSchemaViolationException(e); + } + } + + @Override + public GraphTraversal hasLabel(GraphTraversal query, Object type) { + return query.hasLabel((String) type); + } +} diff --git a/src/main/java/org/onap/aai/champ/perf/ChampAPIPerformanceTest.java b/champ-lib/champ-titan/src/main/java/org/onap/aai/champtitan/perf/ChampAPIPerformanceTest.java similarity index 76% rename from src/main/java/org/onap/aai/champ/perf/ChampAPIPerformanceTest.java rename to champ-lib/champ-titan/src/main/java/org/onap/aai/champtitan/perf/ChampAPIPerformanceTest.java index e1266aa..37ea4ff 100644 --- a/src/main/java/org/onap/aai/champ/perf/ChampAPIPerformanceTest.java +++ b/champ-lib/champ-titan/src/main/java/org/onap/aai/champtitan/perf/ChampAPIPerformanceTest.java @@ -19,40 +19,27 @@ * ============LICENSE_END============================================ * ECOMP is a trademark and service mark of AT&T Intellectual Property. */ -package org.onap.aai.champ.perf; - -import java.util.Arrays; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import org.onap.aai.champ.ChampGraph; -import org.onap.aai.champ.exceptions.ChampMarshallingException; -import org.onap.aai.champ.exceptions.ChampObjectNotExistsException; -import org.onap.aai.champ.exceptions.ChampRelationshipNotExistsException; -import org.onap.aai.champ.exceptions.ChampSchemaViolationException; -import org.onap.aai.champ.exceptions.ChampUnmarshallingException; -import org.onap.aai.champ.graph.impl.InMemoryChampGraphImpl; -import org.onap.aai.champ.graph.impl.TitanChampGraphImpl; -import org.onap.aai.champ.model.ChampField; -import org.onap.aai.champ.model.ChampObject; -import org.onap.aai.champ.model.ChampObjectIndex; -import org.onap.aai.champ.model.ChampRelationship; -import org.onap.aai.champ.model.ChampRelationshipIndex; -import org.onap.aai.champ.model.ChampSchema; -import org.onap.aai.champ.schema.ChampSchemaEnforcer; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +package org.onap.aai.champtitan.perf; import com.thinkaurelius.titan.core.TitanFactory; import com.thinkaurelius.titan.core.TitanFactory.Builder; import com.thinkaurelius.titan.core.TitanGraph; import com.thinkaurelius.titan.core.util.TitanCleanup; +import org.onap.aai.champcore.ChampGraph; +import org.onap.aai.champcore.exceptions.*; +import org.onap.aai.champcore.graph.impl.InMemoryChampGraphImpl; +import org.onap.aai.champcore.model.*; +import org.onap.aai.champcore.schema.ChampSchemaEnforcer; +import org.onap.aai.champtitan.graph.impl.TitanChampGraphImpl; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.*; +import java.util.Map.Entry; +import java.util.stream.Collectors; +import java.util.stream.Stream; + public class ChampAPIPerformanceTest { private static final Logger LOGGER = LoggerFactory.getLogger(ChampAPIPerformanceTest.class); @@ -97,43 +84,51 @@ public class ChampAPIPerformanceTest { public static void main(String[] args) { - if (args.length < 1 || !args[0].startsWith("--champ.graph.type=")) { - throw new RuntimeException("Must provide --champ.graph.type=" + ChampGraph.Type.values() + " as first parameter"); + if (args.length < 1 || !args[0].startsWith("--champcore.graph.type=")) { + throw new RuntimeException("Must provide --champcore.graph.type=" + " as first parameter"); } - final ChampGraph.Type graphType = ChampGraph.Type.valueOf(args[0].split("=")[1]); + final String graphType = args[0].split("=")[1]; final Map settings = new HashMap (); for (int i = 1; i < args.length; i++) { - if (!args[i].startsWith("--")) throw new RuntimeException("Bad command line argument: " + args[i]); + if (!args[i].startsWith("--")) { + throw new RuntimeException("Bad command line argument: " + args[i]); + } final String[] keyValue = args[i].replaceFirst("--", "").split("="); - if (keyValue.length != 2) throw new RuntimeException("Bad command line argument: " + args[i]); + if (keyValue.length != 2) { + throw new RuntimeException("Bad command line argument: " + args[i]); + } settings.put(keyValue[0], keyValue[1]); } LOGGER.info("Provided graph settings: " + settings); - if (graphType == ChampGraph.Type.TITAN) cleanUp(getGraphName(), settings); + if (graphType.equals("TITAN")) { + cleanUp(getGraphName(), settings); + } LOGGER.info("Graph cleaned, instantiating ChampGraph"); final ChampGraph graph; switch (graphType) { - case IN_MEMORY: + case "IN_MEMORY": final InMemoryChampGraphImpl.Builder inMemGraphBuilder = new InMemoryChampGraphImpl.Builder(); - if (settings.containsKey("champ.schema.enforcer")) { - final String schemaEnforcerClassStr = settings.get("champ.schema.enforcer"); + if (settings.containsKey("champcore.schema.enforcer")) { + final String schemaEnforcerClassStr = settings.get("champcore.schema.enforcer"); try { final Class schemaEnforcer = Class.forName(schemaEnforcerClassStr); - if (!schemaEnforcer.isAssignableFrom(ChampSchemaEnforcer.class)) throw new RuntimeException("Unknown ChampSchemaEnforcer " + schemaEnforcer); + if (!schemaEnforcer.isAssignableFrom(ChampSchemaEnforcer.class)) { + throw new RuntimeException("Unknown ChampSchemaEnforcer " + schemaEnforcer); + } inMemGraphBuilder.schemaEnforcer((ChampSchemaEnforcer) schemaEnforcer.newInstance()); } catch (ClassNotFoundException e) { @@ -147,7 +142,7 @@ public class ChampAPIPerformanceTest { graph = inMemGraphBuilder.build(); break; - case TITAN: + case "TITAN": final TitanChampGraphImpl.Builder graphBuilder = new TitanChampGraphImpl.Builder(getGraphName()); for (Entry setting : settings.entrySet()) { @@ -160,10 +155,14 @@ public class ChampAPIPerformanceTest { throw new RuntimeException("Unknown ChampGraph.Type " + graphType); } - if (graph.queryObjects(Collections.emptyMap()).limit(1).count() > 0) { - graph.shutdown(); - throw new RuntimeException("Expected empty graph"); - } + try { + if (graph.queryObjects(Collections.emptyMap(), Optional.empty()).limit(1).count() > 0) { + graph.shutdown(); + throw new RuntimeException("Expected empty graph"); + } + } catch (ChampTransactionException e) { + throw new RuntimeException("Transaction failure"); + } LOGGER.info("Graph instantiated, warming up JVM"); warmUp(graph); @@ -203,22 +202,22 @@ public class ChampAPIPerformanceTest { private static void storeSchema(ChampGraph graph, boolean warmUp) { try { graph.storeSchema( - ChampSchema.create() + ChampSchema.create() .withObjectConstraint() - .onType("foo") - .withPropertyConstraint() - .onField("fooObjectNumber") - .optional() - .build() - .build() + .onType("foo") + .withPropertyConstraint() + .onField("fooObjectNumber") + .optional() + .build() + .build() .withRelationshipConstraint() - .onType("bar") - .withPropertyConstraint() - .onField("barObjectNumber") - .ofType(ChampField.Type.INTEGER) - .optional() - .build() - .build() + .onType("bar") + .withPropertyConstraint() + .onField("barObjectNumber") + .ofType(ChampField.Type.INTEGER) + .optional() + .build() + .build() .build() ); } catch (ChampSchemaViolationException e) { @@ -258,7 +257,13 @@ public class ChampAPIPerformanceTest { for (int i = 0; i < NUM_RELATIONSHIPS; i++) { final long startTime = System.nanoTime(); - final Stream objects = graph.queryRelationships(Collections.singletonMap("relationshipNumber", i)); + Stream objects; + try { + objects = graph.queryRelationships(Collections.singletonMap("relationshipNumber", i), Optional.empty()); + } catch (ChampTransactionException e) { + throw new RuntimeException(e); + } + objects.findFirst().get(); final double elapsedMs = (System.nanoTime() - startTime) / 1000.0 / 1000.0; latencies[i] = elapsedMs; @@ -285,7 +290,12 @@ public class ChampAPIPerformanceTest { for (int i = 0; i < NUM_OBJECTS; i++) { final long startTime = System.nanoTime(); - final Stream objects = graph.queryObjects(Collections.singletonMap("objectNumber", i)); + Stream objects; + try { + objects = graph.queryObjects(Collections.singletonMap("objectNumber", i), Optional.empty()); + } catch (ChampTransactionException e) { + throw new RuntimeException(e); + } objects.findFirst().get(); @@ -311,32 +321,46 @@ public class ChampAPIPerformanceTest { private static List retrieveBulkObjects(ChampGraph graph, boolean warmUp) { final long startTime = System.nanoTime(); - final Stream objects = graph.queryObjects( - Collections.singletonMap( - ChampObject.ReservedPropertyKeys.CHAMP_OBJECT_TYPE.toString(), "foo" - ) - ); + Stream objects; + try { + objects = graph.queryObjects( + Collections.singletonMap( + ChampObject.ReservedPropertyKeys.CHAMP_OBJECT_TYPE.toString(), "foo" + ), Optional.empty() + ); + } catch (ChampTransactionException e) { + throw new RuntimeException(e); + } final List objectsAsList = objects.collect(Collectors.toList()); final double elapsedSecs = (System.nanoTime() - startTime) / 1000.0 / 1000.0 / 1000.0; - if (!warmUp) LOGGER.info("Bulk read " + objectsAsList.size() + " objects in " + elapsedSecs + "s (" + objectsAsList.size() / elapsedSecs + " objects/s)"); + if (!warmUp) { + LOGGER.info("Bulk read " + objectsAsList.size() + " objects in " + elapsedSecs + "s (" + objectsAsList.size() / elapsedSecs + " objects/s)"); + } return objectsAsList; } private static List retrieveBulkRelationships(ChampGraph graph, boolean warmUp) { final long startTime = System.nanoTime(); - final Stream relationships = graph.queryRelationships( - Collections.singletonMap( - ChampRelationship.ReservedPropertyKeys.CHAMP_RELATIONSHIP_TYPE.toString(), "bazz" - ) - ); + Stream relationships; + try { + relationships = graph.queryRelationships( + Collections.singletonMap( + ChampRelationship.ReservedPropertyKeys.CHAMP_RELATIONSHIP_TYPE.toString(), "bazz" + ), Optional.empty() + ); + } catch (ChampTransactionException e) { + throw new RuntimeException(e); + } final List relationshipsAsList = relationships.collect(Collectors.toList()); final double elapsedSecs = (System.nanoTime() - startTime) / 1000.0 / 1000.0 / 1000.0; - if (!warmUp) LOGGER.info("Bulk read " + relationshipsAsList.size() + " relationships in " + elapsedSecs + "s (" + relationshipsAsList.size() / elapsedSecs + " relationships/s)"); + if (!warmUp) { + LOGGER.info("Bulk read " + relationshipsAsList.size() + " relationships in " + elapsedSecs + "s (" + relationshipsAsList.size() / elapsedSecs + " relationships/s)"); + } return relationshipsAsList; } @@ -354,7 +378,7 @@ public class ChampAPIPerformanceTest { .ofType("foo") .withoutKey() .withProperty("objectNumber", i) - .build() + .build(), Optional.empty() ); final double elapsedMs = (System.nanoTime() - startTime) / 1000.0 / 1000.0; @@ -365,7 +389,9 @@ public class ChampAPIPerformanceTest { //Ignore, no schema set } catch (ChampObjectNotExistsException e) { //Ignore, not an update - } + } catch (ChampTransactionException e) { + throw new RuntimeException(e); + } } final double totalElapsedTimeSecs = (System.nanoTime() - totalStartTime) / 1000.0 / 1000.0 / 1000.0; @@ -396,7 +422,7 @@ public class ChampAPIPerformanceTest { objects.get(i % objects.size()), objects.get((i + 1) % objects.size()), "bazz" ).property("relationshipNumber", i) .build() - ); + , Optional.empty()); final double elapsedMs = (System.nanoTime() - startTime) / 1000.0 / 1000.0; @@ -411,6 +437,8 @@ public class ChampAPIPerformanceTest { throw new RuntimeException(e); } catch (ChampUnmarshallingException e) { throw new RuntimeException(e); + } catch (ChampTransactionException e) { + throw new RuntimeException(e); } } diff --git a/champ-lib/champ-titan/src/test/java/org/onap/aai/champtitan/concurrency/ConcurrencyTest.java b/champ-lib/champ-titan/src/test/java/org/onap/aai/champtitan/concurrency/ConcurrencyTest.java new file mode 100644 index 0000000..9e08f55 --- /dev/null +++ b/champ-lib/champ-titan/src/test/java/org/onap/aai/champtitan/concurrency/ConcurrencyTest.java @@ -0,0 +1,33 @@ +/** + * ============LICENSE_START========================================== + * org.onap.aai + * =================================================================== + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 Amdocs + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END============================================ + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.champtitan.concurrency; + +import org.junit.Test; + +public class ConcurrencyTest { + + @Test + public void runInMemoryConcurrentTest() { + org.onap.aai.champcore.concurrency.ConcurrencyTest baseTest = new org.onap.aai.champcore.concurrency.ConcurrencyTest(); + baseTest.runConcurrentTest("TITAN"); + } +} diff --git a/champ-lib/champ-titan/src/test/java/org/onap/aai/champtitan/core/ChampAPITest.java b/champ-lib/champ-titan/src/test/java/org/onap/aai/champtitan/core/ChampAPITest.java new file mode 100644 index 0000000..8d4bc57 --- /dev/null +++ b/champ-lib/champ-titan/src/test/java/org/onap/aai/champtitan/core/ChampAPITest.java @@ -0,0 +1,40 @@ +/** + * ============LICENSE_START========================================== + * org.onap.aai + * =================================================================== + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 Amdocs + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END============================================ + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.champtitan.core; + +import org.junit.Test; +import org.onap.aai.champtitan.graph.impl.TitanChampGraphImpl; + +public class ChampAPITest { + @Test + public void testChampGraphInstantiation() throws Exception { + TitanChampGraphImpl graph = new TitanChampGraphImpl.Builder("testGraph") + .property("storage.backend", "inmemory") + .build(); + + org.onap.aai.champcore.core.ChampAPITest baseTest = new org.onap.aai.champcore.core.ChampAPITest(); + + baseTest.testChampGraphInstantiation(graph); + } + + +} diff --git a/champ-lib/champ-titan/src/test/java/org/onap/aai/champtitan/core/ChampObjectIndexTest.java b/champ-lib/champ-titan/src/test/java/org/onap/aai/champtitan/core/ChampObjectIndexTest.java new file mode 100644 index 0000000..bd9295f --- /dev/null +++ b/champ-lib/champ-titan/src/test/java/org/onap/aai/champtitan/core/ChampObjectIndexTest.java @@ -0,0 +1,48 @@ +/** + * ============LICENSE_START========================================== + * org.onap.aai + * =================================================================== + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 Amdocs + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END============================================ + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.champtitan.core; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.onap.aai.champcore.exceptions.ChampIndexNotExistsException; +import org.onap.aai.champcore.model.ChampCardinality; +import org.onap.aai.champtitan.graph.impl.TitanChampGraphImpl; + +public class ChampObjectIndexTest { + @Rule + public final ExpectedException exception = ExpectedException.none(); + + @Test + public void testChampObjectIndexCrud() throws Exception { + TitanChampGraphImpl graph = new TitanChampGraphImpl.Builder("testGraph") + .property("storage.backend", "inmemory") + .build(); + + org.onap.aai.champcore.core.ChampObjectIndexTest.testChampObjectIndexCrud(graph); + + graph.shutdown(); + + exception.expect(IllegalStateException.class); + graph.executeDeleteObjectIndex("any"); + } +} diff --git a/champ-lib/champ-titan/src/test/java/org/onap/aai/champtitan/core/ChampRelationshipIndexTest.java b/champ-lib/champ-titan/src/test/java/org/onap/aai/champtitan/core/ChampRelationshipIndexTest.java new file mode 100644 index 0000000..e515101 --- /dev/null +++ b/champ-lib/champ-titan/src/test/java/org/onap/aai/champtitan/core/ChampRelationshipIndexTest.java @@ -0,0 +1,38 @@ +/** + * ============LICENSE_START========================================== + * org.onap.aai + * =================================================================== + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 Amdocs + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END============================================ + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.champtitan.core; + +import org.junit.Test; +import org.onap.aai.champtitan.graph.impl.TitanChampGraphImpl; + +public class ChampRelationshipIndexTest { + @Test + public void testChampRelationshipIndexCrud() { + TitanChampGraphImpl graph = new TitanChampGraphImpl.Builder("testGraph") + .property("storage.backend", "inmemory") + .build(); + org.onap.aai.champcore.core.ChampRelationshipIndexTest baseTest = new org.onap.aai.champcore.core.ChampRelationshipIndexTest(); + baseTest.testChampRelationshipIndexCrud(graph); + + graph.shutdown(); + } +} diff --git a/champ-lib/champ-titan/src/test/java/org/onap/aai/champtitan/core/ChampSchemaTest.java b/champ-lib/champ-titan/src/test/java/org/onap/aai/champtitan/core/ChampSchemaTest.java new file mode 100644 index 0000000..ac29fc8 --- /dev/null +++ b/champ-lib/champ-titan/src/test/java/org/onap/aai/champtitan/core/ChampSchemaTest.java @@ -0,0 +1,37 @@ +/** + * ============LICENSE_START========================================== + * org.onap.aai + * =================================================================== + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 Amdocs + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END============================================ + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.champtitan.core; + +import org.junit.Test; +import org.onap.aai.champtitan.graph.impl.TitanChampGraphImpl; + +public class ChampSchemaTest { + @Test + public void testChampSchemaCrud() { + TitanChampGraphImpl graph = new TitanChampGraphImpl.Builder("testGraph") + .property("storage.backend", "inmemory") + .build(); + org.onap.aai.champcore.core.ChampSchemaTest.testChampSchemaCrud(graph); + + graph.shutdown(); + } +} diff --git a/champ-lib/champ-titan/src/test/java/org/onap/aai/champtitan/core/ChampTransactionTest.java b/champ-lib/champ-titan/src/test/java/org/onap/aai/champtitan/core/ChampTransactionTest.java new file mode 100644 index 0000000..aafc053 --- /dev/null +++ b/champ-lib/champ-titan/src/test/java/org/onap/aai/champtitan/core/ChampTransactionTest.java @@ -0,0 +1,335 @@ +/** + * ============LICENSE_START========================================== + * org.onap.aai + * =================================================================== + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 Amdocs + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END============================================ + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.champtitan.core; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.util.Optional; +import java.util.concurrent.CountDownLatch; + +import org.junit.Before; +import org.junit.Test; +import org.onap.aai.champcore.ChampTransaction; +import org.onap.aai.champcore.exceptions.ChampMarshallingException; +import org.onap.aai.champcore.exceptions.ChampObjectNotExistsException; +import org.onap.aai.champcore.exceptions.ChampRelationshipNotExistsException; +import org.onap.aai.champcore.exceptions.ChampSchemaViolationException; +import org.onap.aai.champcore.exceptions.ChampTransactionException; +import org.onap.aai.champcore.exceptions.ChampUnmarshallingException; +import org.onap.aai.champcore.model.ChampObject; +import org.onap.aai.champcore.model.ChampRelationship; +import org.onap.aai.champtitan.graph.impl.TitanChampGraphImpl; + +public class ChampTransactionTest { + + public TitanChampGraphImpl graph = null; + public CountDownLatch latch = new CountDownLatch(2); + public ChampObject[] storedVertices = new ChampObject[2]; + + + @Before + public void setup() { + graph = new TitanChampGraphImpl.Builder("TransactionTestGraph") + .property("storage.backend", "inmemory") + .build(); + } + + + /** + * This test validates that multiple CRUD operations can be performed against vertices within + * the same transactional context and that, once the transaction is committed, the final + * state of the vertices reflects the sum of all of the operations performed within the + * transaction. + * + * @throws ChampMarshallingException + * @throws ChampSchemaViolationException + * @throws ChampObjectNotExistsException + * @throws ChampUnmarshallingException + * @throws ChampTransactionException + */ + @Test + public void champObjectSingleTxTest() throws ChampMarshallingException, ChampSchemaViolationException, ChampObjectNotExistsException, ChampUnmarshallingException, ChampTransactionException { + + ChampObject v1 = ChampObject.create() + .ofType("foo") + .withoutKey() + .withProperty("property1", "value1") + .withProperty("property2", "value2") + .build(); + + ChampObject v2 = ChampObject.create() + .ofType("foo") + .withoutKey() + .withProperty("property3", "value3") + .withProperty("property4", "value4") + .build(); + + ChampObject v3 = ChampObject.create() + .ofType("foo") + .withoutKey() + .withProperty("property5", "value5") + .withProperty("property6", "value6") + .build(); + + ChampObject v4 = ChampObject.create() + .ofType("foo") + .withoutKey() + .withProperty("property7", "value7") + .withProperty("property8", "value8") + .build(); + + + // Open a transaction with the graph data store. + ChampTransaction tx = graph.openTransaction(); + + // Create all of our vertices. + ChampObject storedV1 = graph.storeObject(v1, Optional.of(tx)); + ChampObject storedV2 = graph.storeObject(v2, Optional.of(tx)); + ChampObject storedV3 = graph.storeObject(v3, Optional.of(tx)); + ChampObject storedV4 = graph.storeObject(v4, Optional.of(tx)); + + // Now, within the same transactional context, do a replacement against one of the + // vertices that we just created. + ChampObject replacedV2 = graph.replaceObject(ChampObject.create() + .ofType("foo") + .withKey(storedV2.getKey().get()) + .withProperty("replacedProperty3", "replacedValue3") + .withProperty("replacedProperty4", "replacedValue4") + .build(), + Optional.of(tx)); + + // Within the same transactional context, do an update against one of the vertices + // that we just created. + final ChampObject updatedV3 = graph.storeObject(ChampObject.create() + .from(storedV3) + .withKey(storedV3.getKey().get()) + .withProperty("updatedProperty", "updatedValue") + .build(), Optional.of(tx)); + + // Within the same transactional context, delete one of the vertices that we just + // created. + graph.deleteObject(storedV4.getKey().get(), Optional.of(tx)); + + // Finally, commit our transaction. + tx.commit(); + + tx = graph.openTransaction(); + + Optional retrievedV1 = graph.retrieveObject(storedV1.getKey().get(), Optional.of(tx)); + assertTrue(retrievedV1.isPresent()); + assertTrue(retrievedV1.get().getProperty("property1").get().equals("value1")); + assertTrue(retrievedV1.get().getProperty("property2").get().equals("value2")); + + + Optional retrievedV2 = graph.retrieveObject(storedV2.getKey().get(), Optional.of(tx)); + assertTrue(retrievedV2.isPresent()); + assertTrue(retrievedV2.get().getProperty("replacedProperty3").get().equals("replacedValue3")); + assertTrue(retrievedV2.get().getProperty("replacedProperty4").get().equals("replacedValue4")); + assertFalse(retrievedV2.get().getProperty("value3").isPresent()); + assertFalse(retrievedV2.get().getProperty("value4").isPresent()); + + Optional retrievedV3 = graph.retrieveObject(storedV3.getKey().get(), Optional.of(tx)); + assertTrue(retrievedV3.isPresent()); + assertTrue(retrievedV3.get().getProperty("property5").get().equals("value5")); + assertTrue(retrievedV3.get().getProperty("property6").get().equals("value6")); + assertTrue(retrievedV3.get().getProperty("updatedProperty").get().equals("updatedValue")); + + + Optional retrievedV4 = graph.retrieveObject(storedV4.getKey().get(), Optional.of(tx)); + assertFalse("Deleted vertex should not be present in graph", retrievedV4.isPresent()); + + tx.commit(); + } + + + /** + * This test validates that multiple threads can each open their own transactions with the + * graph data store, and that there is no leakage between each thread's transactions. + * + * @throws ChampMarshallingException + * @throws ChampSchemaViolationException + * @throws ChampObjectNotExistsException + * @throws ChampUnmarshallingException + * @throws ChampTransactionException + */ + @Test + public void multipleTransactionTest() throws ChampMarshallingException, ChampSchemaViolationException, ChampObjectNotExistsException, ChampUnmarshallingException, ChampTransactionException { + + ChampObject v1 = ChampObject.create() + .ofType("foo") + .withoutKey() + .withProperty("property1", "value1") + .withProperty("property2", "value2") + .build(); + + ChampObject v2 = ChampObject.create() + .ofType("bar") + .withoutKey() + .withProperty("property3", "value3") + .withProperty("property4", "value4") + .build(); + + // Instantiate and start our two transactional worker threads... + Thread thread1 = new Thread(new VertexWriter(v1, 0)); + Thread thread2 = new Thread(new VertexWriter(v2, 1)); + thread1.start(); + thread2.start(); + + // and wait for the threads to complete. + try { + thread1.join(); + thread2.join(); + + } catch (InterruptedException e) { } + + // Now that all of our data has been committed, let's open a new transaction + // and verify that all of our vertices can be retrieved. + ChampTransaction tx3 = graph.openTransaction(); + + Optional retrievedV1 = graph.retrieveObject(storedVertices[0].getKey().get(), Optional.of(tx3)); + assertTrue(retrievedV1.isPresent()); + Optional retrievedV2 = graph.retrieveObject(storedVertices[1].getKey().get(), Optional.of(tx3)); + assertTrue(retrievedV2.isPresent()); + + tx3.commit(); + } + + + /** + * This method validates that edges can be successfully created within a single transaction. + * + * @throws ChampMarshallingException + * @throws ChampSchemaViolationException + * @throws ChampObjectNotExistsException + * @throws ChampUnmarshallingException + * @throws ChampRelationshipNotExistsException + * @throws ChampTransactionException + */ + @Test + public void edgeTest() throws ChampMarshallingException, ChampSchemaViolationException, ChampObjectNotExistsException, ChampUnmarshallingException, ChampRelationshipNotExistsException, ChampTransactionException { + + // Create the source and target vertices for our edge. + final ChampObject source = ChampObject.create() + .ofType("foo") + .withoutKey() + .withProperty("property1", "value1") + .build(); + + final ChampObject target = ChampObject.create() + .ofType("foo") + .withoutKey() + .build(); + + // Open a transaction with the graph data store. + ChampTransaction tx = graph.openTransaction(); + + // Now, create our vertices. + ChampObject storedSource = graph.storeObject(source, Optional.of(tx)); + ChampObject storedTarget = graph.storeObject(target, Optional.of(tx)); + + // Create the edge between the vertices. + ChampRelationship relationship = new ChampRelationship.Builder(storedSource, storedTarget, "relationship") + .property("property-1", "value-1") + .property("property-2", 3) + .build(); + ChampRelationship storedRelationship = graph.storeRelationship(relationship, Optional.of(tx)); + + // Validate that we can read back the edge within the transactional context. + Optional retrievedRelationship = graph.retrieveRelationship(storedRelationship.getKey().get(), Optional.of(tx)); + assertTrue("Failed to retrieve stored relationship", retrievedRelationship.isPresent()); + + // Commit our transaction. + graph.commitTransaction(tx); + + // Now, open a new transaction. + tx = graph.openTransaction(); + + // Now, read back the edge that we just created again, validating that it was + // successfully committed to the graph. + retrievedRelationship = graph.retrieveRelationship(storedRelationship.getKey().get(), Optional.of(tx)); + assertTrue("Failed to retrieve stored relationship", retrievedRelationship.isPresent()); + + graph.commitTransaction(tx); + } + + private class VertexWriter implements Runnable { + + ChampObject vertex; + int index; + + public VertexWriter(ChampObject vertex, int index) { + this.vertex = vertex; + this.index = index; + } + + public void run() { + + ChampTransaction tx=null; + try { + + // Open a threaded transaction to do some work in. + tx = graph.openTransaction(); + + // Now store one of our two vertices within the context of this transaction. + storedVertices[index] = graph.storeObject(vertex, Optional.of(tx)); + + // Use our latch to indicate that we are done creating vertices, and wait for + // the other thread to do the same. + latch.countDown(); + latch.await(); + + // Validate that the vertex we created is visible to us in the graph, but the + // one that the other thread created is not. + Optional retrievedV2 = graph.retrieveObject(storedVertices[index].getKey().get(), Optional.of(tx)); + assertTrue(retrievedV2.isPresent()); + Optional retrievedV1 = graph.retrieveObject(storedVertices[(index+1)%2].getKey().get(), Optional.of(tx)); + assertFalse(retrievedV1.isPresent()); + + } catch (InterruptedException | + ChampUnmarshallingException | + ChampMarshallingException | + ChampSchemaViolationException | + ChampObjectNotExistsException | ChampTransactionException e) { + + fail("Thread failed to interact with graph due to " + e.getMessage()); + + } finally { + + try { + Thread.sleep(index * 500); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + // Now, commit our transaction and bail... + try { + graph.commitTransaction(tx); + } catch (ChampTransactionException e) { + + } + } + } + }; +} + diff --git a/champ-lib/champ-titan/src/test/java/org/onap/aai/champtitan/core/TitanChampSetupTest.java b/champ-lib/champ-titan/src/test/java/org/onap/aai/champtitan/core/TitanChampSetupTest.java new file mode 100644 index 0000000..bca61ec --- /dev/null +++ b/champ-lib/champ-titan/src/test/java/org/onap/aai/champtitan/core/TitanChampSetupTest.java @@ -0,0 +1,74 @@ +/** + * ============LICENSE_START========================================== + * org.onap.aai + * =================================================================== + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 Amdocs + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END============================================ + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.aai.champtitan.core; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.onap.aai.champtitan.graph.impl.TitanChampGraphImpl; + +import java.util.HashMap; +import java.util.Map; + +public class TitanChampSetupTest { + @Rule + public final ExpectedException exception = ExpectedException.none(); + + @Test + public void TitanSetupBadBackendTest() { + exception.expect(RuntimeException.class); + TitanChampGraphImpl graph = new TitanChampGraphImpl.Builder("testGraph") + .property("storage.backend", "bad-backend") + .build(); + } + + @Test + public void TitanSetupBerkleyBackendTest() { + exception.expect(RuntimeException.class); + Map propertiesMap = new HashMap(); + propertiesMap.put("storage.backend", "berkleyje"); + TitanChampGraphImpl graph = new TitanChampGraphImpl.Builder("testGraph") + .properties(propertiesMap) + .build(); + } + + @Test + public void TitanSetupBadPropertyTest() { + exception.expect(RuntimeException.class); + TitanChampGraphImpl graph = new TitanChampGraphImpl.Builder("testGraph") + .property("storage.backend", "in-memory") + .property("storage.cassandra.keyspace", "anything") + .build(); + } + + @Test + public void TitanSetupBadPropertiesTest() { + exception.expect(RuntimeException.class); + Map propertiesMap = new HashMap(); + propertiesMap.put("storage.cassandra.keyspace", "anything"); + + TitanChampGraphImpl graph = new TitanChampGraphImpl.Builder("testGraph") + .property("storage.backend", "in-memory") + .properties(propertiesMap) + .build(); + } +} diff --git a/champ-lib/pom.xml b/champ-lib/pom.xml new file mode 100644 index 0000000..771957a --- /dev/null +++ b/champ-lib/pom.xml @@ -0,0 +1,300 @@ + + 4.0.0 + + org.onap.aai + champ-lib + pom + 1.2.0-SNAPSHOT + + + champ-core + champ-titan + champ-janus + + + + UTF-8 + 1.2.0 + + + + + + + + + + + + + scm:git:ssh://git@codecloud.web.att.com:7999/st_aai/champ.git + HEAD + + + + + + nexus + ecomp_aai-releases + http://mavencentral.it.att.com:8084/nexus/content/repositories/ecomp_aai-releases + + + + nexus + ecomp_aai-snapshots + http://mavencentral.it.att.com:8084/nexus/content/repositories/ecomp_aai-snapshots + + + + + + + org.onap.aai.event-client + event-client-api + ${event.client.version} + + + org.onap.aai.event-client + event-client-dmaap + ${event.client.version} + + + org.onap.aai.event-client + event-client-kafka + ${event.client.version} + + + + + + + junit + junit + 4.12 + test + + + ch.qos.logback + logback-classic + 1.2.1 + true + + + org.apache.hbase + hbase-client + 0.98.4-hadoop2 + + + org.slf4j + slf4j-log4j12 + + + com.google.guava + guava + + + + + jdk.tools + jdk.tools + 1.8 + system + ${JAVA_HOME}/lib/tools.jar + + + org.jacoco + org.jacoco.agent + 0.7.9 + runtime + test + + + + + + + org.jacoco + jacoco-maven-plugin + 0.7.9 + + + + **/AbstractGremlinChampGraph* + **/DseChampGraphImpl* + **/DseChampformer* + + **/ChampAPIPerformanceTest* + + + + + default-prepare-agent + + prepare-agent + + + + default-report + prepare-package + + report + + + + default-check + + check + + + + + + BUNDLE + + + + INSTRUCTION + COVEREDRATIO + .15 + + + BRANCH + COVEREDRATIO + .12 + + + COMPLEXITY + COVEREDRATIO + .15 + + + LINE + COVEREDRATIO + .10 + + + METHOD + COVEREDRATIO + .17 + + + CLASS + MISSEDCOUNT + 5 + + + + + + + + + + org.apache.maven.plugins + maven-assembly-plugin + 3.0.0 + + + jar-with-dependencies + + + + + make-jar-with-dependencies + package + + single + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.6.1 + + 1.8 + 1.8 + + + + maven-release-plugin + 2.4.2 + + + org.apache.maven.scm + maven-scm-provider-gitexe + 1.8.1 + + + + + org.apache.maven.plugins + maven-source-plugin + 3.0.1 + + + attach-sources + + jar + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.9.1 + + + attach-javadocs + + jar + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.12.2 + + + target/jacoco.exec + + + + + com.mycila + license-maven-plugin + 3.0 + +
License.txt
+ + **/*.java + **/*.ksh + **/*.sh + **/*.ftl + **/*.xsd + **/*.xjb + **/*.yml + **/*.yaml + **/aai*.xml + **/*logback*.xml + **/*aaiconfig*.properties + **/*titan*.properties + +
+ + + + format + + process-sources + + +
+
+
+
diff --git a/champ-service-deps-janus/pom.xml b/champ-service-deps-janus/pom.xml new file mode 100644 index 0000000..9bc954c --- /dev/null +++ b/champ-service-deps-janus/pom.xml @@ -0,0 +1,125 @@ + + 4.0.0 + + org.onap.aai + champ-service-deps-janus + pom + 1.2.0-SNAPSHOT + + + 1.2.0 + + + + + + org.onap.aai.event-client + event-client-api + ${event.client.version} + + + org.onap.aai.event-client + event-client-dmaap + ${event.client.version} + + + org.onap.aai.event-client + event-client-kafka + ${event.client.version} + + + + org.onap.aai + champ-janus + 1.2.0-SNAPSHOT + + + org.onap.aai.event-client + event-client-api + + + org.onap.aai.event-client + event-client-dmaap + + + org.onap.aai.event-client + event-client-kafka + + + + + org.janusgraph + janusgraph-cassandra + 0.1.1 + true + + + org.slf4j + slf4j-log4j12 + + + ch.qos.logback + logback-classic + + + org.apache.tinkerpop + gremlin-core + + + org.apache.tinkerpop + gremlin-groovy + + + + + org.janusgraph + janusgraph-hbase + 0.1.1 + true + + + org.apache.tinkerpop + gremlin-groovy + + + org.slf4j + slf4j-log4j12 + + + ch.qos.logback + logback-classic + + + org.apache.tinkerpop + gremlin-core + + + + + + + + + org.apache.maven.plugins + maven-dependency-plugin + 3.0.1 + + + copy-janus-dependencies + package + + copy-dependencies + + + ../champ-service/target/graph-deps/janus-deps + false + false + true + + + + + + + \ No newline at end of file diff --git a/champ-service-deps-titan/pom.xml b/champ-service-deps-titan/pom.xml new file mode 100644 index 0000000..f4f081d --- /dev/null +++ b/champ-service-deps-titan/pom.xml @@ -0,0 +1,122 @@ + + 4.0.0 + + org.onap.aai + champ-service-deps-titan + pom + 1.2.0-SNAPSHOT + + + 1.2.0 + + + + + + org.onap.aai.event-client + event-client-api + ${event.client.version} + + + org.onap.aai.event-client + event-client-dmaap + ${event.client.version} + + + org.onap.aai.event-client + event-client-kafka + ${event.client.version} + + + org.onap.aai + champ-titan + 1.2.0-SNAPSHOT + + + org.onap.aai.event-client + event-client-api + + + org.onap.aai.event-client + event-client-dmaap + + + org.onap.aai.event-client + event-client-kafka + + + + + com.thinkaurelius.titan + titan-cassandra + 1.0.0 + + + org.apache.tinkerpop + gremlin-groovy + + + org.slf4j + slf4j-log4j12 + + + ch.qos.logback + logback-classic + + + org.apache.tinkerpop + gremlin-core + + + + + com.thinkaurelius.titan + titan-hbase + 1.0.0 + + + org.apache.tinkerpop + gremlin-groovy + + + org.slf4j + slf4j-log4j12 + + + ch.qos.logback + logback-classic + + + org.apache.tinkerpop + gremlin-core + + + + + + + + + org.apache.maven.plugins + maven-dependency-plugin + 3.0.1 + + + copy-titan-dependencies + package + + copy-dependencies + + + ../champ-service/target/graph-deps/titan-deps + false + false + true + + + + + + + \ No newline at end of file diff --git a/champ-service/License.txt b/champ-service/License.txt new file mode 100644 index 0000000..469f362 --- /dev/null +++ b/champ-service/License.txt @@ -0,0 +1,21 @@ +============LICENSE_START========================================== +org.onap.aai +=================================================================== +Copyright © 2017 AT&T Intellectual Property. All rights reserved. +Copyright © 2017 Amdocs +=================================================================== +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +============LICENSE_END============================================ +ECOMP is a trademark and service mark of AT&T Intellectual Property. + + diff --git a/champ-service/ajsc-shared-config/etc/logback.xml b/champ-service/ajsc-shared-config/etc/logback.xml new file mode 100644 index 0000000..12ed478 --- /dev/null +++ b/champ-service/ajsc-shared-config/etc/logback.xml @@ -0,0 +1,235 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + ${errorLogPattern} + + + + + + + + + + + ${logDirectory}/${generalLogName}.log + + ${logDirectory}/${generalLogName}.%d{yyyy-MM-dd}.log.zip + + 60 + + + ${errorLogPattern} + + + + + + INFO + + 256 + + + + + + + + ${logDirectory}/${auditLogName}.log + + ${logDirectory}/${auditLogName}.%d{yyyy-MM-dd}.log.zip + + 60 + + + ${auditMetricPattern} + + + + 256 + + + + + ${logDirectory}/${metricsLogName}.log + + ${logDirectory}/${metricsLogName}.%d{yyyy-MM-dd}.log.zip + + 60 + + + + ${auditMetricPattern} + + + + + + 256 + + + + + ${logDirectory}/${debugLogName}.log + + ${logDirectory}/${debugLogName}.%d{yyyy-MM-dd}.log.zip + + 60 + + + ${errorLogPattern} + + + + + 256 + + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/champ-service/antBuild/build.xml b/champ-service/antBuild/build.xml new file mode 100644 index 0000000..b898a9e --- /dev/null +++ b/champ-service/antBuild/build.xml @@ -0,0 +1,178 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/champ-service/appconfig-local/auth/champion-service_policy.json-REPLACE b/champ-service/appconfig-local/auth/champion-service_policy.json-REPLACE new file mode 100644 index 0000000..ee9bf44 --- /dev/null +++ b/champ-service/appconfig-local/auth/champion-service_policy.json-REPLACE @@ -0,0 +1 @@ +This should be replaced with an actual policy file \ No newline at end of file diff --git a/champ-service/appconfig-local/auth/tomcat_keystore-REPLACE b/champ-service/appconfig-local/auth/tomcat_keystore-REPLACE new file mode 100644 index 0000000..cfc37ff --- /dev/null +++ b/champ-service/appconfig-local/auth/tomcat_keystore-REPLACE @@ -0,0 +1 @@ +Place keystore here \ No newline at end of file diff --git a/champ-service/appconfig-local/champ-api.properties-REPLACE b/champ-service/appconfig-local/champ-api.properties-REPLACE new file mode 100644 index 0000000..9ad9b33 --- /dev/null +++ b/champ-service/appconfig-local/champ-api.properties-REPLACE @@ -0,0 +1,7 @@ +Replace with your actual properties file. Should contain something like: + +keyName=aai-uuid +sourceOfTruthName=source-of-truth +createdTsName=aai-created-ts +lastModTsName=aai-last-mod-ts +collectionPropertiesKey=properties \ No newline at end of file diff --git a/champ-service/bundleconfig-local/etc/appprops/AAFUserRoles.properties b/champ-service/bundleconfig-local/etc/appprops/AAFUserRoles.properties new file mode 100644 index 0000000..dde7e09 --- /dev/null +++ b/champ-service/bundleconfig-local/etc/appprops/AAFUserRoles.properties @@ -0,0 +1,12 @@ + +#If using AAF for Role based authentication/authorization, define your routes/services which will utilize AAF. The AJSC will +#read this file and protect the routes given with the AAF role defined. + +#The following example would protect the JAXRS echo example service provided with the archetype. +#/services/${namespace}/v1/jaxrs-services/jaxrsExample/echo/*=com.att.ajsc.myper|mymachine|manage + +#The following example would protect ALL AJSC services running within your project. +#/**=com.att.ajsc.myperm|mymachine|manage + +#The following example would protect ALL REST services utilizing the Camel restlet routes. +#/rest/**=com.att.ajsc.myperm|mymachine|manage diff --git a/champ-service/bundleconfig-local/etc/appprops/PostProcessorInterceptors.properties b/champ-service/bundleconfig-local/etc/appprops/PostProcessorInterceptors.properties new file mode 100644 index 0000000..17b5036 --- /dev/null +++ b/champ-service/bundleconfig-local/etc/appprops/PostProcessorInterceptors.properties @@ -0,0 +1,2 @@ +#This properties file is for defining any PostProcessorInterceptors that have been created for your AJSC service. + diff --git a/champ-service/bundleconfig-local/etc/appprops/PreProcessorInterceptors.properties b/champ-service/bundleconfig-local/etc/appprops/PreProcessorInterceptors.properties new file mode 100644 index 0000000..ddaefdd --- /dev/null +++ b/champ-service/bundleconfig-local/etc/appprops/PreProcessorInterceptors.properties @@ -0,0 +1,3 @@ +#This properties file is for defining any PreProcessorInterceptors that have been created for your AJSC service. + +/**=com.att.ajsc.csi.restmethodmap.RestMethodMapInterceptor diff --git a/champ-service/bundleconfig-local/etc/appprops/app-intercepts.properties b/champ-service/bundleconfig-local/etc/appprops/app-intercepts.properties new file mode 100644 index 0000000..bcf3912 --- /dev/null +++ b/champ-service/bundleconfig-local/etc/appprops/app-intercepts.properties @@ -0,0 +1,7 @@ + +#This is where all your application intercept strategies must be configured. AJSC reads this property file and adds +#the list of intercepts specified here to the camel context. This can be useful for accessing every exchange object transferred from/to +#each endpoint in the request/response flow and can allow for more precise debugging and/or processing of the exchange. + +#e.g. +#intercepts=org.openecomp.champ.JaxrsEchoService,packagename.class1name,packagename.class2name diff --git a/champ-service/bundleconfig-local/etc/appprops/methodMapper.properties b/champ-service/bundleconfig-local/etc/appprops/methodMapper.properties new file mode 100644 index 0000000..1cda3e5 --- /dev/null +++ b/champ-service/bundleconfig-local/etc/appprops/methodMapper.properties @@ -0,0 +1,45 @@ +// +// Json object holds the method mapping.Update the JSON object with the proper route to logical mapping based +// on the example provided below : +// "helloWorld" = Service Name +// "method" = http method +// "url" = the url component from the route +// "logicalName"= When a combination of method and url from the route matches the json object , +// the logical name is put in the http header as "x-CSI-ServiceName" and "x-CSI-MethodName" +// "dme2url"= if provided it register the endpoint to GRM, it is optional. This is useful for JAX-RS services. + +{ + "helloWorld": [ + { + "method": "get", + "url": "/rest/champ-service/v1/helloWorld", + "logicalName": "GetMethod(Logical)" + }, + { + "method": "get", + "url": "/services/champ-service/v1/jaxrsExample/jaxrs-services/echo/{input}", + "logicalName": "GetJaxrsExampleEcho(Logical)", + "dme2url": "/services/champ-service/v1/jaxrsExample/jaxrs-services/echo/{input}" + }, + { + "method": "get", + "url": "/services/champ-service/v1/jaxrsExample/jaxrs-services/property/{fileName}/{input}", + "logicalName": "GetJaxrsExampleProperty(Logical)", + "dme2url": "/services/champ-service/v1/jaxrsExample/jaxrs-services/property/{fileName}/{input}" + } + ], + "errormessage": + [ + { + "method": "get", + "url": "/services/champ-service/v1/jaxrsExample/errormessage/emls", + "logicalName": "setCAETHeaders(Logical)" + }, + { + "method": "get", + "url": "/services/champ-service/v1/errorMessageLookupService2", + "logicalName": "setCAETHeaders(Logical)" + } + + ] +} \ No newline at end of file diff --git a/champ-service/bundleconfig-local/etc/sysprops/sys-props.properties b/champ-service/bundleconfig-local/etc/sysprops/sys-props.properties new file mode 100644 index 0000000..26cd13d --- /dev/null +++ b/champ-service/bundleconfig-local/etc/sysprops/sys-props.properties @@ -0,0 +1,117 @@ +#This file is used for defining AJSC system properties for different configuration schemes and is necessary for the AJSC to run properly. +#The sys-props.properties file is used for running locally. The template.sys-props.properties file will be used when deployed +#to a SOA/CSI Cloud node. + +#AJSC System Properties. The following properties are required for ALL AJSC services. If you are adding System Properties for your +#particular service, please add them AFTER all AJSC related System Properties. + +#For Cadi Authorization, use value="authentication-scheme-1 +CadiAuthN=authentication-scheme-1 + +#For Basic Authorization, use value="authentication-scheme-1 +authN=authentication-scheme-2 + +#Persistence used for AJSC meta-data storage. For most environments, "file" should be used. +ajscPersistence=file + +#For Direct Invocation to be enabled (values=true/false) +directInvocationEnable=false + +# If using hawtio for local development, these properties will allow for faster server startup and usage for local development + +hawtio.authenticationEnabled=false +hawtio.config.pullOnStartup=false + +#Removes the extraneous restlet console output +org.restlet.engine.loggerFacadeClass=org.restlet.ext.slf4j.Slf4jLoggerFacade + +#server.host property to be enabled for local DME2 related testing +#server.host= + +#Enable/disable SSL (values=true/false). This property also determines which protocol to use (https if true, http otherwise), to register services into GRM through DME2. +enableSSL=false + + +#Enable/disable EJB Container +ENABLE_EJB=false + +#Enable/disable OSGI +isOSGIEnable=false + +#Generate/Skip api docs +isApiDoc=false + +#CSI related variables for CSM framework +csm.hostname=servername + + +#SOA_CLOUD_ENV is used to register your service with dme2 and can be turned off for local development (values=true/false). +SOA_CLOUD_ENV=false + +#CONTINUE_ON_LISTENER_EXCEPTION will exit the application if there is a DME2 exception at the time of registration. +CONTINUE_ON_LISTENER_EXCEPTION=false + +#Jetty Container ThreadCount Configuration Variables +AJSC_JETTY_ThreadCount_MIN=1 +AJSC_JETTY_ThreadCount_MAX=200 +AJSC_JETTY_IDLETIME_MAX=3000 + +#Camel Context level default threadPool Profile configuration +CAMEL_POOL_SIZE=10 +CAMEL_MAX_POOL_SIZE=20 +CAMEL_KEEP_ALIVE_TIME=60 +CAMEL_MAX_QUEUE_SIZE=1000 + +#GRM/DME2 System Properties +AFT_DME2_CONN_IDLE_TIMEOUTMS=5000 +AJSC_ENV=SOACLOUD + +SOACLOUD_NAMESPACE=com.att.ajsc +SOACLOUD_ENV_CONTEXT=DEV +SOACLOUD_PROTOCOL=http +SOACLOUD_ROUTE_OFFER=DEFAULT + +AFT_LATITUDE=23.4 +AFT_LONGITUDE=33.6 +AFT_ENVIRONMENT=AFTUAT + +#Restlet Component Default Properties +RESTLET_COMPONENT_CONTROLLER_DAEMON=true +RESTLET_COMPONENT_CONTROLLER_SLEEP_TIME_MS=100 +RESTLET_COMPONENT_INBOUND_BUFFER_SIZE=8192 +RESTLET_COMPONENT_MIN_THREADS=1 +RESTLET_COMPONENT_MAX_THREADS=10 +RESTLET_COMPONENT_LOW_THREADS=8 +RESTLET_COMPONENT_MAX_QUEUED=0 +RESTLET_COMPONENT_MAX_CONNECTIONS_PER_HOST=-1 +RESTLET_COMPONENT_MAX_TOTAL_CONNECTIONS=-1 +RESTLET_COMPONENT_OUTBOUND_BUFFER_SIZE=8192 +RESTLET_COMPONENT_PERSISTING_CONNECTIONS=true +RESTLET_COMPONENT_PIPELINING_CONNECTIONS=false +RESTLET_COMPONENT_THREAD_MAX_IDLE_TIME_MS=60000 +RESTLET_COMPONENT_USE_FORWARDED_HEADER=false +RESTLET_COMPONENT_REUSE_ADDRESS=true + +#Externalized jar and properties file location. In CSI environments, there are a few libs that have been externalized to aid +#in CSTEM maintenance of the versions of these libs. The most important to the AJSC is the DME2 lib. Not only is this lib necessary +#for proper registration of your AJSC service on a node, but it is also necessary for running locally as well. Another framework +#used in CSI envs is the CSM framework. These 2 framework libs are shown as "provided" dependencies within the pom.xml. These +#dependencies will be copied into the target/commonLibs folder with the normal "mvn clean package" goal of the AJSC. They will +#then be added to the classpath via AJSC_EXTERNAL_LIB_FOLDERS system property. Any files (mainly property files) that need +#to be on the classpath should be added to the AJSC_EXTERNAL_PROPERTIES_FOLDERS system property. The default scenario when +#testing your AJSC service locally will utilize the target/commonLibs directory for DME2 and CSM related artifacts and 2 +#default csm properties files will be used for local testing with anything CSM knorelated. +#NOTE: we are using maven-replacer-plugin to replace "(doubleUnderscore)basedir(doubleUnderscore)" with ${basedir} within the +#target directory for running locally. Multiple folder locations can be separated by the pipe ("|") character. +#Please, NOTE: for running locally, we are setting this system property in the antBuild/build.xml "runLocal" target and in the +#"runAjsc" profile within the pom.xml. This is to most effectively use maven variables (${basedir}, most specifically. Therefore, +#when running locally, the following 2 properties should be set within the profile(s) themselves. +#Example: target/commonLibs|target/otherLibs +#AJSC_EXTERNAL_LIB_FOLDERS=__basedir__/target/commonLibs +#AJSC_EXTERNAL_PROPERTIES_FOLDERS=__basedir__/ajsc-shared-config/etc +#End of AJSC System Properties + +#Service System Properties. Please, place any Service related System Properties below. + +KEY_STORE_PASSWORD=OBF:1y0q1uvc1uum1uvg1pil1pjl1uuq1uvk1uuu1y10 +KEY_MANAGER_PASSWORD=OBF:1y0q1uvc1uum1uvg1pil1pjl1uuq1uvk1uuu1y10 diff --git a/champ-service/pom.xml b/champ-service/pom.xml new file mode 100644 index 0000000..9edf59d --- /dev/null +++ b/champ-service/pom.xml @@ -0,0 +1,360 @@ + + + 4.0.0 + + + com.att.ajsc + ajsc-archetype-parent + 2.0.0 + + + org.onap.aai + champ-service + 1.2.0-SNAPSHOT + + + ${basedir}/target/swm/package/nix/dist_files${distFilesRoot} + 2.0.0 + + /appl/${project.artifactId} + + + /appl/${project.artifactId}/${project.version} + + 1.2.0 + org.onap.aai.logging-service + 1.2.0 + + + + + com.sun.jersey + jersey-core + 1.18.6 + + + + + dom4j + dom4j + 1.6.1 + provided + + + com.att.aft + dme2 + 3.1.200 + provided + + + + + org.json + json + 20160212 + + + + org.glassfish.jersey.core + jersey-client + 2.23 + + + + commons-io + commons-io + 2.4 + + + + com.google.code.gson + gson + 2.6.2 + + + + ${common.logging.groupid} + common-logging + ${common.logging.version} + + + + ch.qos.logback + logback-core + 1.1.7 + + + + org.eclipse.persistence + eclipselink + 2.6.2 + + + + + org.onap.aai.event-client + event-client-api + ${event.client.version} + + + org.onap.aai.event-client + event-client-dmaap + ${event.client.version} + + + org.onap.aai.event-client + event-client-kafka + ${event.client.version} + + + + + org.onap.aai + champ-core + 1.2.0-SNAPSHOT + compile + + + org.apache.hbase + hbase-client + + + org.onap.aai.event-client + event-client-api + + + org.onap.aai.event-client + event-client-dmaap + + + org.onap.aai.event-client + event-client-kafka + + + + + + + ${project.artifactId} + + + org.apache.maven.plugins + maven-resources-plugin + 2.7 + + + copy-docker-file + package + + copy-resources + + + target + true + + + ${basedir}/src/main/docker + true + + **/* + + + + ${basedir}/src/main/bin/ + + + + + + + + + org.jacoco + jacoco-maven-plugin + 0.7.9 + + + default-prepare-agent + + prepare-agent + + + + default-report + prepare-package + + report + + + + default-check + + check + + + + + + BUNDLE + + + + INSTRUCTION + COVEREDRATIO + .15 + + + BRANCH + COVEREDRATIO + .12 + + + COMPLEXITY + COVEREDRATIO + .15 + + + LINE + COVEREDRATIO + .10 + + + METHOD + COVEREDRATIO + .17 + + + CLASS + MISSEDCOUNT + 5 + + + + + + + + + + + + + + runAjsc + + initialize + + + org.codehaus.mojo + exec-maven-plugin + 1.3.2 + + + initialize + + java + + + false + true + java + com.att.ajsc.runner.Runner + + com.att.ajsc + ajsc-runner + + + ${basedir}/ajsc-shared-config/etc + + + + ${runAjscHome} + + + + + + AJSC_HOME + ${runAjscHome} + + + CONFIG_HOME + ${basedir}/appconfig-local/ + + + AJSC_CONF_HOME + ${basedir}/bundleconfig-local + + + logback.configurationFile + ${basedir}/ajsc-shared-config/etc/logback.xml + + + AJSC_SHARED_CONFIG + ${basedir}/ajsc-shared-config + + + + AJSC_EXTERNAL_LIB_FOLDERS + ${basedir}/target/commonLibs + + + AJSC_EXTERNAL_PROPERTIES_FOLDERS + ${basedir}/ajsc-shared-config/etc + + + + AJSC_SERVICE_NAMESPACE + ${module.ajsc.namespace.name} + + + AJSC_SERVICE_VERSION + ${module.ajsc.namespace.version} + + + SOACLOUD_SERVICE_VERSION + ${project.version} + + + server.port + ${serverPort} + + + + + + context=/ + port=${serverPort} + sslport=${sslport} + + + + + + java + + + + com.att.ajsc + ajsc-runner + ${ajscRuntimeVersion} + + + + + + + + diff --git a/champ-service/src/main/ajsc/champ-service_v1/champ-service/v1/conf/jaxrsBeans.groovy b/champ-service/src/main/ajsc/champ-service_v1/champ-service/v1/conf/jaxrsBeans.groovy new file mode 100644 index 0000000..17d80a4 --- /dev/null +++ b/champ-service/src/main/ajsc/champ-service_v1/champ-service/v1/conf/jaxrsBeans.groovy @@ -0,0 +1,11 @@ +beans{ + xmlns cxf: "http://camel.apache.org/schema/cxf" + xmlns jaxrs: "http://cxf.apache.org/jaxrs" + xmlns util: "http://www.springframework.org/schema/util" + + echoService(org.onap.champ.service.EchoService) + + util.list(id: 'echoServices') { + ref(bean:'echoService') + } +} \ No newline at end of file diff --git a/champ-service/src/main/ajsc/champ-service_v1/champ-service/v1/docs/README.txt b/champ-service/src/main/ajsc/champ-service_v1/champ-service/v1/docs/README.txt new file mode 100644 index 0000000..3707179 --- /dev/null +++ b/champ-service/src/main/ajsc/champ-service_v1/champ-service/v1/docs/README.txt @@ -0,0 +1 @@ +Place any docs here that you want to access within the ajsc upon deployment of your service. diff --git a/champ-service/src/main/ajsc/champ-service_v1/champ-service/v1/lib/README.txt b/champ-service/src/main/ajsc/champ-service_v1/champ-service/v1/lib/README.txt new file mode 100644 index 0000000..639e21b --- /dev/null +++ b/champ-service/src/main/ajsc/champ-service_v1/champ-service/v1/lib/README.txt @@ -0,0 +1 @@ +3rd party JAR's needed by your jars (if any) for a ajsc deployment package go here... \ No newline at end of file diff --git a/champ-service/src/main/ajsc/champ-service_v1/champ-service/v1/routes/champ.route b/champ-service/src/main/ajsc/champ-service_v1/champ-service/v1/routes/champ.route new file mode 100644 index 0000000..cf8d115 --- /dev/null +++ b/champ-service/src/main/ajsc/champ-service_v1/champ-service/v1/routes/champ.route @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/champ-service/src/main/ajsc/champ-service_v1/champ-service/v1/routes/jaxrsExample.route b/champ-service/src/main/ajsc/champ-service_v1/champ-service/v1/routes/jaxrsExample.route new file mode 100644 index 0000000..a132030 --- /dev/null +++ b/champ-service/src/main/ajsc/champ-service_v1/champ-service/v1/routes/jaxrsExample.route @@ -0,0 +1,5 @@ + + + + + diff --git a/champ-service/src/main/assemble/ajsc_module_assembly.xml b/champ-service/src/main/assemble/ajsc_module_assembly.xml new file mode 100644 index 0000000..4ec4e28 --- /dev/null +++ b/champ-service/src/main/assemble/ajsc_module_assembly.xml @@ -0,0 +1,66 @@ + + ${version} + false + + zip + + + + ${project.basedir}/target/versioned-ajsc/routes/ + ${module.ajsc.namespace.name}/${module.ajsc.namespace.version}/routes/ + + *.route + + + + + + ${project.basedir}/target/versioned-ajsc/docs/ + ${module.ajsc.namespace.name}/${module.ajsc.namespace.version}/docs/ + + *.* + + + + + + + ${project.basedir}/target/versioned-ajsc/lib/ + ${module.ajsc.namespace.name}/${module.ajsc.namespace.version}/lib/ + + *.jar + + + + + ${project.basedir}/target/versioned-ajsc/extJars/ + ${module.ajsc.namespace.name}/${module.ajsc.namespace.version}/extJars/ + + *.jar + + + + + + ${project.basedir}/target/ + ${module.ajsc.namespace.name}/${module.ajsc.namespace.version}/lib/ + + *.jar + + + + + ${project.basedir}/target/versioned-ajsc/conf/ + ${module.ajsc.namespace.name}/${module.ajsc.namespace.version}/conf/ + + *.* + + + + + + + diff --git a/champ-service/src/main/assemble/ajsc_props_assembly.xml b/champ-service/src/main/assemble/ajsc_props_assembly.xml new file mode 100644 index 0000000..5b8a6fa --- /dev/null +++ b/champ-service/src/main/assemble/ajsc_props_assembly.xml @@ -0,0 +1,23 @@ + + ${version}_properties + false + + zip + + + + ${project.basedir}/target/versioned-ajsc/props + ${module.ajsc.namespace.name}/${module.ajsc.namespace.version}/props/ + + *.props + + + + + + + + diff --git a/champ-service/src/main/assemble/ajsc_runtime_assembly.xml b/champ-service/src/main/assemble/ajsc_runtime_assembly.xml new file mode 100644 index 0000000..e37d366 --- /dev/null +++ b/champ-service/src/main/assemble/ajsc_runtime_assembly.xml @@ -0,0 +1,44 @@ + + runtimeEnvironment + false + + zip + + + + ${project.basedir}/target/versioned-runtime/context/ + runtime/context/ + + *.context + + + + ${project.basedir}/target/versioned-runtime/serviceProperties/ + runtime/serviceProperties/ + + *.props + + + ${project.basedir}/target/versioned-runtime/shiroRole + runtime/shiroRole/ + + *.json + + + ${project.basedir}/target/versioned-runtime/shiroUser + runtime/shiroUser/ + + *.json + + + ${project.basedir}/target/versioned-runtime/shiroUserRole + runtime/shiroUserRole + + *.json + + + + \ No newline at end of file diff --git a/champ-service/src/main/bin/start.sh b/champ-service/src/main/bin/start.sh new file mode 100644 index 0000000..de8a4fb --- /dev/null +++ b/champ-service/src/main/bin/start.sh @@ -0,0 +1,94 @@ +#!/bin/sh +# +# ============LICENSE_START========================================== +# org.onap.aai +# =================================================================== +# Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# Copyright © 2017 Amdocs +# =================================================================== +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# ============LICENSE_END============================================ +# ECOMP is a trademark and service mark of AT&T Intellectual Property. +# + + +BASEDIR="/opt/app/champ-service/" +AJSC_HOME="$BASEDIR" +AJSC_CONF_HOME="$AJSC_HOME/bundleconfig/" + +if [ -z "$CONFIG_HOME" ]; then + echo "CONFIG_HOME must be set in order to start up process" + exit 1 +fi + +if [ -z "$KEY_STORE_PASSWORD" ]; then + echo "KEY_STORE_PASSWORD must be set in order to start up process" + exit 1 +else + echo "KEY_STORE_PASSWORD=$KEY_STORE_PASSWORD\n" >> $AJSC_CONF_HOME/etc/sysprops/sys-props.properties +fi + +if [ -z "$KEY_MANAGER_PASSWORD" ]; then + echo "KEY_MANAGER_PASSWORD must be set in order to start up process" + exit 1 +else + echo "KEY_MANAGER_PASSWORD=$KEY_MANAGER_PASSWORD\n" >> $AJSC_CONF_HOME/etc/sysprops/sys-props.properties +fi + +# Add any spring bean configuration files to the Gizmo deployment +if [ -n "$SERVICE_BEANS" ]; then + echo "Adding the following dynamic service beans to the deployment: " + mkdir -p /tmp/champ-service/v1/conf + for f in `ls $SERVICE_BEANS` + do + cp $SERVICE_BEANS/$f /tmp/champ-service/v1/conf + echo "Adding dynamic service bean $SERVICE_BEANS/$f" + done + jar uf /opt/app/champ-service/services/champ-service_v1.zip* -C /tmp/ champ-service + rm -rf /tmp/champ-service +fi + +CLASSPATH="$AJSC_HOME/lib/*" +CLASSPATH="$CLASSPATH:$AJSC_HOME/extJars/" +CLASSPATH="$CLASSPATH:$AJSC_HOME/etc/" + +# Check to see if the provided implementation exists in the image and add it to the classpath +for file in $( find ${BASEDIR}graph-deps/* -maxdepth 0 -type d ); do + CURRIMPL=$(echo $file | cut -d"/" -f6) + if [ "x$GRAPHIMPL" = "x$CURRIMPL" ]; then + CLASSPATH_GRAPHIMPL=$file + echo "Setting up graph implementation of $GRAPHIMPL" + else + SUPPORTED_GRAPHIMPL="$SUPPORTED_GRAPHIMPL $CURRIMPL" + fi +done +if [ -n "$CLASSPATH_GRAPHIMPL" ]; then + cp $CLASSPATH_GRAPHIMPL/* $AJSC_HOME/extJars/ +else + echo "Configured graph implementation '$GRAPHIMPL' is not supported. Acceptable implementations are one of: $SUPPORTED_GRAPHIMPL" + exit 1 +fi + +PROPS="-DAJSC_HOME=$AJSC_HOME" +PROPS="$PROPS -DAJSC_CONF_HOME=$BASEDIR/bundleconfig/" +PROPS="$PROPS -Dlogback.configurationFile=$BASEDIR/bundleconfig/etc/logback.xml" +PROPS="$PROPS -DAJSC_SHARED_CONFIG=$AJSC_CONF_HOME" +PROPS="$PROPS -DAJSC_SERVICE_NAMESPACE=champ-service" +PROPS="$PROPS -DAJSC_SERVICE_VERSION=v1" +PROPS="$PROPS -Dserver.port=9522" +PROPS="$PROPS -DCONFIG_HOME=$CONFIG_HOME" +JVM_MAX_HEAP=${MAX_HEAP:-1024} + +echo $CLASSPATH + +exec java -Xmx${JVM_MAX_HEAP}m $PROPS -classpath $CLASSPATH com.att.ajsc.runner.Runner context=// sslport=9522 diff --git a/champ-service/src/main/config/ajsc-chef.jks b/champ-service/src/main/config/ajsc-chef.jks new file mode 100644 index 0000000000000000000000000000000000000000..aeca7700182fb1824b47fca285204122a879ff85 GIT binary patch literal 5256 zcmdT|TTfiq6`ngV%y1iS1_lfU6TrY31_rRX8e?;}F&GS(`*qA^xC~%0mo#-FS52M9 zY8BOaNKz%P)yh$$Hfs7%MXFs@Y2qf0V<&aeSgl|B(&jJp`(|wh?6@zL`cUax-&$** zea_iut+m&gGhe^=+pl+^)9DOBF`pmz``2_j{V5!u90TdhXA4TSa-GfyM}zEW18hT> z?(;XHn;}k!X17|xa$z(;0J~MMH=A`l4RD2PVHV>Vlf_{;)3M`(+6>*bt|%>nM?!2N z9pl4(|IGN#h}~)n>G3Vs`4;D04lSCK!fkfz$@%fcVZYZmx8!na$s9G>V%KND%Qni#PmlURtk6iOD*Nk5no}Hf==QJ%f!ESYxXr-Pv=r#gf$Zrc1DVj=h{cAdfc$)Azct4QdA|> z667KzF%HxU$(U>be|8PD3;~u-*Ye!GuyxnktqzQ258b+&+IF!I=7z8I;SYn8;@yj4 zZ$T}0Z~?%asU_(GbO~f!hPH8`V`A>*h2BbJSZrP4R?as^gCh@r2Gb>O4W9-W z5;Zji{qQZW7Z`;kFed4c-+vo)?{!egC(nWf7TpSrf}juM%Ns>u;-6X-oe_To#&L1L zom~3ZWYGV|tM9-Lh3w9Ovn~_3ty&K<2|#;IYjlqX#>X#k{{f{CyLA?Pqz>eR#6tjs zQLocKtu(MZxuK;P;&|3YMjZI`b@k}t?goBCWoRq`M@ly2@Gul>g{d;ObWF(T$~1Ht zWQucJxu7qus$*3(XW;_%_4nUBw%vVLJn%p!XsQf%zNRK|R9RPvSDX(Wxw0Uhsj)pm zo2`Mvuoo`w<8#{N*mh$v48}q|;~$>qM8F9N=b+wm_qq&$y`%fV)g&+PfBTZ%nhJdi z!pS;_S|2QKmzknarsv`a=-9g5IsjeK5X0LFs{a0?@4!N5*XvBf=a)uRQ*WsVjG7H> zXeJ0cuictw(VO(ShG?{F9S12o<`ekx`9nNsR6KBP2B>&{8Z#8d(!Kvi!3xt*?FH4V zlDhzVi9Q6lbJfU^MhH(2;ux%0hzfNei*Sbq1{ca?5=(1kXaB$+Pm=KqjQfxQR2v~9 z!l$9)RzRKN2P%a{_m`Jt0L(j%L0Tc@8$)2=tLH##Jzd~5894`417UsaMK?E!fawBw zug*We!h~@#8F8SatQ(%XJqJ2Iv1+v4y#!0`-vclO1)|E{|CJcrECBnGUQBRPFJq^V zHXMbcWcpY?8@mIYzKaCJ#eP*e}7cg$|RbA5Iylab@Jw25>uYbVFV z6+eOYBe!l~$jzRfzWm^d9PUOR-aE0`4^OKubI+d6gO$oq4}JI&I5C{d13vlgAu+&h z6D%1Zc2Sj7GMutG6$Cj3=5DPGdN7!2$HvaRyI7(l5XM$e4#f}%hNjoYSdWX7k6!#~ za8!&+QCrQcV(dP9Om+z$2Z)BS?$dP!W;FzoVd3Qq^$eYXQCo)qTcU)c>pP8N{pshQ z{sdN^cx+k%J~pph4e6fofcHV{*4pw6&nB!`2$1L>;f2ma{`U3_hE~Ax&r1Pu8L`_( zIyRtrP2Ry$rfwH|pr5&&ZafSI9$O=PUOLB>nq$c>X@gmD_XWp+;r1Muxsa&D<6z}L z@t)izY-v-FgjOAzj#?;uhiaHG)k1f-3?B{%B(B?THCMrjkTGy{{sK6OYhWfD&6Z6l zK&`tKrcFk`oW`6*wg-n`I3a!f33KPFT2kX$B|AyQVs|u@fFS~Mv>2An6Zqol`liMG z;Mx|0IsdyWO!WPiO7_n3iKB5vz4=`1p_Ss`gq&O7Q&q&mWom$BNRgNc2cQcX+hGW! z>t{f{3nQ!N^h32-5pXgf*$`!}#SJ=P_Hb(hTW&5V%NHfCFlz|lHQD#f;;I~|6?5;M zfV9X#cNAZO|9ay$;HgQ_Ql3h-9N)_-oVS0$qzN+WI>lIrQn`htW^S?N11EUHvX zDw8H)g{m~D`Y>#UVNB1B$~JK4t&nX_5=`8Cm9Lc;9tl}<&&p`nD&HAgkO9)?`S`U~ z?h&^02RHk{oW6As6a*tM$_V#-aLMVH;igBIpJSE*_FH!SK+}S58IO%GaXxzYW!S(r zUtvswZZJ^9gM;in8^zoV=OE>fowk(Dbr~;$_Co~RtH9~9fdkXio8qu47)P!w%bDwH zIVs~Ej@@WAVrXAyFE3UJ$v2gPCm_iuPw~DnmJV+xqZPsDsP=J*Mz)i#p1dxHJ0!5C zq4hzGFxv0GR{+j5Po+Zfj6Hc|D_^|i3?1JxDG0K{J?b>Ydc$9cB>Xn7augH+NO@W z;6S+YW3;HiN3A1l#y2`VGv!D;P-YFDt5ndzagZrWJyDa_yC0EoYKRfl+nTaq254iW?hhNtHa4jeRb{{j1Y*k(Nl3jT;tsfN`bwtf3s>fHi2JPKs%>jU%rR=xnsS!3SRdp8%MyLjjv zo7C}27JKDmZys(F;L-Q5gA;f%(8KfHi6Fiexl{Wgz)q9c=Y&(K`dp!xcM!B4cKq|& z<>3^sxaS+8xmML?xiQk@5SSNLJIT+t9Jlo|5YCu%fEeLLZ;H>B?OCwIzya7kfWKY= zv7esUX8gL<2vfW%mYL$B1l*BorN`MS*!Kzx zHvhwZG2*Cvb~b(XChVLwP%?zi!lg5BfO*r==I609;xoknV{8n!%&C|koZ;8SUa)Bc zx%0un1~<%NapOMtadYrMX*|rn5m35{kNWgj?P7Gk3AWQG;0Z)L@K*-=pK3vb>M= zT@?7S4kI;Zggswif%3Bk^Vf%$a%=st?!4`rV!o>m^Jjx#6RH=&Tc1s-IO$x6!5tys uGt~9-5rg<6yY}vk>bcLavBuIN+c|MEZ6uak28dCGC0;vJ=$Z7;@P7m3`PLW! literal 0 HcmV?d00001 diff --git a/champ-service/src/main/config/ajsc-jetty.xml b/champ-service/src/main/config/ajsc-jetty.xml new file mode 100644 index 0000000..98cc02e --- /dev/null +++ b/champ-service/src/main/config/ajsc-jetty.xml @@ -0,0 +1,114 @@ + + + + + + + + true + + + /etc/runner-web.xml + /etc/ajsc-override-web.xml + true + + + false + + + /extJars/champ-service.jar,/extJars/json-20160212.jar,/extJars/javax.ws.rs-api-2.0.1.jar,/extJars/jersey-client-2.23.jar + + + + + + + + + + + + + + + + + + + + + + + + /extApps + 10 + true + + + + + + + + + file:/auth/tomcat_keystore + + + + + + + + + + + true + true + + + + + + + + + + + + + http/1.1 + + + + + + + + + + + + + + + + + + + + + + 30000 + + + + + + + + + false + + + diff --git a/champ-service/src/main/config/ajsc-override-web.xml b/champ-service/src/main/config/ajsc-override-web.xml new file mode 100644 index 0000000..8e02d6d --- /dev/null +++ b/champ-service/src/main/config/ajsc-override-web.xml @@ -0,0 +1,50 @@ + + + + + InterceptorFilter + /services/* + + + InterceptorFilter + /rest/* + + + + springSecurityFilterChain + /* + + + + ManagementServlet + /mgmt + + + + RestletServlet + /rest/* + + + + CamelServlet + /services/* + + + + jsp + *.jsp + *.jspf + *.jspx + *.xsp + *.JSP + *.JSPF + *.JSPX + *.XSP + + + default + /* + + \ No newline at end of file diff --git a/champ-service/src/main/config/ajscJetty.jks b/champ-service/src/main/config/ajscJetty.jks new file mode 100644 index 0000000000000000000000000000000000000000..48cdbff4a8344b9bfa164b340c2fd3b4f7020c41 GIT binary patch literal 3736 zcmcIm`)`xy75+Zo;@EM*>Rd47o-~jPU}JKFn8b+*gxq6897y6^aPAj^NkW*tv>V%4 zyRF*Rc3M>xRjX8OrCU)iVyiZ!iWb^R6&;0+l1^fqRQ0F+3ws`)k1rMKualnhoO9my z^Y^~zyyrcizq$6eZyrKX6az#}iZwQUHo7o6AH_gG9_fKn6tm)nHbLC!7Kg3UqMFnS z!}nCxtZ~`P?CJNqmyXXx;aI2o792JhsgV548_!HZo2o&;_RpUv+ae~{GJf#q z!MdVh8R!xP4nfL{AQh4e5$xF~Iy}(66IPBsk$|-o5>E$Jn_VvLL1hkp0YpcwRi{JyRN4$I;F!}LQV-;fNJSJM_^pU+{Hynlzw2I@?=fy~jM<2ZK zYMg0YqvWj1I5XlGbA?L-Ou3FzW4(#FkNygOh_9TL3HA6+f68Y+hvRAh<;y5IQ>>7;EBd2S36TyJ}*wf9SB8?IRywf@kmB1)ixQLB5S$xjotN$7L)J zY8rA<+=HTYjwS9ruRHay3dFnnV`w8U64wb&uw;1R4}SN?zux3CtbXF@=fJ1(vcPqa z_;C=W8**~&SZ(DbJ;vQh0!~1fkCxM*20JtK!~~P zR{D;@%HsVhs$l7rP4gheg3(ed51PvZU835#YjL;8Y6yLur?!wkF7(58= z{_wy9!|lv~Yb65KL5G*4!sl1`j#<{vynA=Dxxo}@XUgDs8^-y1;PZ>^>`2=oGpxsM z2GiPBzwF|X@l=7rGcn#Ko?H3xV&1d1yKjJX)MhedfLR54xlO^@Vl$I}M!YN@Hoy`F z&O^9;mi{QqOxq>PdI;iy2;O@(8P1lLn{PU7EQ>&diCc!Szq%nhjAEU?{x0i*DFGG_ zBwui@T^nL}jqFcA#luwbKD$dcvm2KAIjA6Hh*Wq+d!vg*dnOIU1+`nh1Ev-nEWshD zi5~U)`}$zaSO!*ZKO2KJEVJOyHqd7mbf1X^_-gG7!Cg->P+uJziVp&?-E4Lh<7T!7 zTE}J!G3iMS#Mh=Cm#6bZ33u}nENn))zae|$7Y0^_fWIzbL1=Zmv8VAl3l40L&%-|CqzOtKIdAVhpm_jooBJElq=JFqjV2 z@v^!dHcKjlJput7HdVFb4^r4;cc)s6$4nNd;aKpYV|5x1`#oFmw+S;T&J=&B!`~J1 zd(!wC3^{C0qdye#IBae^eY?}t66^`+zR_v&9}Tv+^K%?F&px-;Q|GDn)>rR6A%2ag zM)UvA>myLL_`5>KUqGIVnvwjAs5)#0da42jPVN}&GM8>V0n=eCVQmHPzHDbtnq_eS zY;}k4yai^<2~zGq11`A3Is1@?xi+=$Na&vRSReQzet(b+d zr~LDZ!Kf+>uE<^B&O>qLrJJ%%nLH*zBM;=?KfN03=Z$6e5*Ty8t59%9l7*rw+jfN9 zmUJH;wrc^yteUGYfy#ueLwXT!ls`fcz3j_XfRey^6e+2yW?*8^z2Ar=h zvnn&#vUrn^L71LVrlOQ*|PW9frj&V8Ix8l3)CaF^zwDO~%1DUQGTe;RWhYSm*+l zN8zI>VTe_hLe2roM}OkE1N=7kiK%mgZoy#NyZwrcFj+i==)HHg$Ow3=w%0FS8TAIV d$UppJT1E%vmLWa}Z$I0*0!fDe1J|Dh{|_E2uSEa= literal 0 HcmV?d00001 diff --git a/champ-service/src/main/config/cadi.properties b/champ-service/src/main/config/cadi.properties new file mode 100644 index 0000000..cc527ed --- /dev/null +++ b/champ-service/src/main/config/cadi.properties @@ -0,0 +1,28 @@ +#This properties file is used for defining AAF properties related to the CADI framework. This file is used for running AAF framework +hostname=mywebserver.att.com + +#Setting csp_domain to PROD will allow for testing using your attuid and password through GLO. +csp_domain=PROD +csp_devl_localhost=true + +basic_realm=csp.att.com +#basic_realm=aaf.att.com +basic_warn=TRUE + +cadi_loglevel=WARN +cadi_keyfile=target/swm/package/nix/dist_files/appl/champ-service/etc/keyfile + +# Configure AAF +#These are dummy values add appropriate values required +aaf_url=url + +#AJSC - MECHID +#These are dummy values add appropriate values required +aaf_id=dummyid@ajsc.att.com +aaf_password=enc:277edqJCjT0RlUI3BtbDQa-3Ha-CQGd +aaf_timeout=5000 +aaf_clean_interval=30000 +aaf_user_expires=5000 +aaf_high_count=1000 + + diff --git a/champ-service/src/main/config/jul-redirect.properties b/champ-service/src/main/config/jul-redirect.properties new file mode 100644 index 0000000..8b6624d --- /dev/null +++ b/champ-service/src/main/config/jul-redirect.properties @@ -0,0 +1,13 @@ + +# Bridge JUL->slf4j Logging Configuration File +# +# This file bridges the JUL logging infrastructure into +# SLF4J so JUL logs go to logback implementation provided +# in this project. SLF4J also captures log4j and has +# other framework options as well providing a common +# logging infrastructure for capturing all logs from different +# libraries using different frameworks in one place. + +# Global properties +handlers=org.slf4j.bridge.SLF4JBridgeHandler +.level= ALL diff --git a/champ-service/src/main/config/keyfile b/champ-service/src/main/config/keyfile new file mode 100644 index 0000000..882e86a --- /dev/null +++ b/champ-service/src/main/config/keyfile @@ -0,0 +1,27 @@ +ZuIwp0TkyVPDeX1Up-8JtkMWvjsCpoiu1_VKeWrtrvxunvAke8_tiFyHPPyb2nkhepFYj6tXzpfS +rGz5XF_TH9NbsKaP8u0HV5clz2WriYQRvHS85vjY7hXxkpFuLb7zkLAPqTyIDpj7FiW61NzsRUAq +TM8jH16jr7mBNnb56w24mNGOwznMPcIZKcjgZU1ekaPDFpWyhQElU7Y0q_94P_Gkk45r66Hj22sU +OiOaaftmudZlswLw8-8Zaakqf2yW9HjMVfuYCwSodBHCW5rdB3Ctb5W36rnD_AQco3Ky2PgPmqvk +QkJYuUHpbuDqVHqLOajlKSIGMTIqAIBg51fRaaONtD-Q5xzY8E5wO1YWTLKcP5tsNvUpzM8Wu3NS +ynpGpUcvlTqWWsGzTbzOyamyKkdNdx97sSqjM25Zh1-ps48h6cddGYWpab7SUvqRCS11QBUyLTry +2iwTEHMhHRIbo7PO99ALQfuq9gI1zKGfurJdvLBeBaFs5SCF0AiCZ3WcDO8Rv3HpxVZ2_ShbDxb0 +eMoO6SotXu51fj8Y3-WqsfZziQyEsHyqpg5uQ6yUtz01h5YHLEoVuotF1U4agmQR6kEkYk-wNOiZ +v-8gaA9gtbLoAdKhuKFxQgQLNMf6GzVzZNujbmDzLoZAP_mXAv29aBPaf64Ugzv-Oa5GZdBgD-Xd +_pahML-ionw99r0TnkpShYmDqMKhMdjaP3m87WIAZkIB-L-VTyKcEsJ4340VSzCOsv3waiM0S89u +4cMcG5y-PLY8IoipIlLUPTWD3SjcQ9DV1Dt3T5KjdWLsj48D3W4K4e9PB8yxs0gtUjgVUR2_xEir +G5eDO9Ac1eHFWGDFFP0SgG-TbHJUKlvy9mwLzmU0fC3xPjhqmIr-v0HxF7HN-tmb1LHDorno8tSN +u7kUGcKSchIiFfvkd066crUb2mH7PnXTaWmAjyVj9VsBExFUYEdpHMAV4sAP9-RxZGDRt46UhrDK +QZvvNhBVyOEjHPHWI4vl1r1v8HNH1_2jZu5DVJWyHWR56aCo1lhFH9_X6UAHUHbnXViDONZOVXlT +9-WD0tk2zJGuwrhdZDAnPnAmjfwbwbpnr5Hmex1i1JiD7WVyP1kbfoej2TmdiYbxr9oBYaGQ29JI +aHod7MQCLtvL1z5XgnDPLZ4y3_9SbqHKYbNa8UgZkTLF5EacGThYVFDLA9cbafHDtR1kMGE3vv4D +EJ-0pAYTOGmKlVI7DwNyKsY9JTyudrxTqhOxi9jgcJNWiUaNe9yhL8Pyc2YBqUTTYhh_a2d1rvkZ +0Gh1crviVxqBrIkRKaMRXZ4f1vDLz-3NvG_vwPOo8WRFo5nGmSdTw7CjBaigJ_cYCfDhoP11pEnw +cndsZNcHs-v05LlxeIIMDD_f5Bvz-il_DLA4eK2HqgLdxh8ziSDl2azk14MJY4amzz6reEXUuKLV +RsZGf_jbDGKhE2HuDQ5ovoLOi4OqE1oRuqh-dGxitrYouP2SN1l_1tCEMRth86FMV-6AQtZsvdUo +y9MtQ7e35atjA8nHtgADlDTmJBKQiUHUsOZ77p1qp17HAFMovUkc739opfEYnKUn6Itpw5Ipm_Is +ra6chJUfMpOFof5rb5OjqFAN27c_-mPo1lQU3ndYlKGh_n5V8ufX6v2Yri8WzOPf6hjVYotkmoMP +NPAICDCB8W5ddBjsopzLVVEtaXDu9Qj6-zf77hT4iQ7rBd2Ner8iLqN3Kis0dvkNM3_uH8onau1G +Y_YYw7PPSZyd2S_7Dd6G-IG4ayO6e5DD6oUwwekyiQI_3rTXNa_wldGxqW9u818010ekE4Qdlfcj +beIn7fAeaOjReZ87hRgWyMs-EgTVHw8RL3yI_O6VvRTVRONRF1Y4C_-IYa8z-bfrwXx3BBd9TTgb +EnS9wVOyC2OgUN6BhPLGLhxzkJ05nEjizXEc9t5EPYoSRwesajGGrrG_0-qWbuU5hKLPLkyeJLHb +5HXOTVsrUR59Vov2M3_EswkxcImblox3k3VS2yihZMGyfqLzZIUXgd8ufkevKKU6DxwacGTb \ No newline at end of file diff --git a/champ-service/src/main/config/runner-web.xml b/champ-service/src/main/config/runner-web.xml new file mode 100644 index 0000000..5f65183 --- /dev/null +++ b/champ-service/src/main/config/runner-web.xml @@ -0,0 +1,94 @@ + + + + + contextConfigLocation + /WEB-INF/spring-servlet.xml, + classpath:applicationContext.xml + + + + + spring.profiles.default + nooauth + + + + org.springframework.web.context.ContextLoaderListener + + + + ManagementServlet + ajsc.ManagementServlet + + + + + InterceptorFilter + ajsc.filters.InterceptorFilter + + preProcessor_interceptor_config_file + /etc/PreProcessorInterceptors.properties + + + postProcessor_interceptor_config_file + /etc/PostProcessorInterceptors.properties + + + + + + RestletServlet + ajsc.restlet.RestletSpringServlet + + org.restlet.component + restletComponent + + + + + CamelServlet + ajsc.servlet.AjscCamelServlet + + + + + springSecurityFilterChain + org.springframework.web.filter.DelegatingFilterProxy + + + + spring + org.springframework.web.servlet.DispatcherServlet + 1 + + + + + + + + jsp + org.apache.jasper.servlet.JspServlet + + + + + + + + + default + org.eclipse.jetty.servlet.DefaultServlet + + dirAllowed + true + + + + diff --git a/champ-service/src/main/docker/Dockerfile b/champ-service/src/main/docker/Dockerfile new file mode 100644 index 0000000..cf299a2 --- /dev/null +++ b/champ-service/src/main/docker/Dockerfile @@ -0,0 +1,34 @@ +FROM ubuntu:14.04 + +ARG MICRO_HOME=/opt/app/champ-service +ARG BIN_HOME=$MICRO_HOME/bin +ARG GRAPHLIB_HOME=$MICRO_HOME/graph-deps + +RUN apt-get update + +# Install and setup java8 +RUN apt-get update && apt-get install -y software-properties-common +RUN sudo -E add-apt-repository ppa:openjdk-r/ppa && apt-get update && apt-get install -y openjdk-8-jdk +ENV JAVA_HOME usr/lib/jvm/java-8-openjdk-amd64 +RUN export JAVA_HOME + +# Build up the deployment folder structure +RUN mkdir -p $MICRO_HOME +ADD swm/package/nix/dist_files/appl/champ-service/* $MICRO_HOME/ +RUN mkdir -p $GRAPHLIB_HOME +ADD graph-deps $GRAPHLIB_HOME +RUN mkdir -p $BIN_HOME +COPY *.sh $BIN_HOME +RUN chmod 755 $BIN_HOME/* +RUN ln -s /logs $MICRO_HOME/logs + +# Create the aai user +RUN mkdir /opt/aaihome && \ + groupadd -g 492381 aaiadmin && \ + useradd -r -u 341790 -g 492381 -ms /bin/bash -d /opt/aaihome/aaiadmin aaiadmin && \ + chown -R aaiadmin:aaiadmin $MICRO_HOME +USER aaiadmin + +EXPOSE 9522 9522 + +CMD ["/opt/app/champ-service/bin/start.sh"] diff --git a/champ-service/src/main/java/org/onap/champ/ChampRESTAPI.java b/champ-service/src/main/java/org/onap/champ/ChampRESTAPI.java new file mode 100644 index 0000000..3d7e074 --- /dev/null +++ b/champ-service/src/main/java/org/onap/champ/ChampRESTAPI.java @@ -0,0 +1,568 @@ +package org.onap.champ; + +import java.io.IOException; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Timer; + +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.Consumes; +import javax.ws.rs.DELETE; +import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.HttpHeaders; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import javax.ws.rs.core.Response.Status; +import javax.ws.rs.core.UriInfo; + +import org.json.JSONException; +import org.json.JSONObject; +import org.onap.aai.champcore.ChampTransaction; +import org.onap.aai.champcore.exceptions.ChampObjectNotExistsException; +import org.onap.aai.champcore.exceptions.ChampRelationshipNotExistsException; +import org.onap.aai.champcore.exceptions.ChampTransactionException; +import org.onap.aai.champcore.exceptions.ChampUnmarshallingException; +import org.onap.aai.champcore.model.ChampObject; +import org.onap.aai.champcore.model.ChampRelationship; +import org.onap.aai.cl.api.Logger; +import org.onap.aai.cl.eelf.LoggerFactory; +import org.onap.champ.async.ChampAsyncRequestProcessor; +import org.onap.champ.entity.ChampObjectDeserializer; +import org.onap.champ.entity.ChampObjectSerializer; +import org.onap.champ.entity.ChampRelationshipDeserializer; +import org.onap.champ.entity.ChampRelationshipSerializer; +import org.onap.champ.exception.ChampServiceException; +import org.onap.champ.service.ChampDataService; +import org.onap.champ.service.logging.ChampMsgs; +import org.onap.champ.service.logging.LoggingUtil; +import org.onap.champ.util.ChampProperties; +import org.onap.champ.util.ChampServiceConstants; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.module.SimpleModule; + +@Path(value = "/") +public class ChampRESTAPI { + + private ObjectMapper mapper; + + private ChampDataService champDataService; + private String TRANSACTION_METHOD = "method"; + private Timer timer; + + private Logger logger = LoggerFactory.getInstance().getLogger(ChampRESTAPI.class); + Logger auditLogger = LoggerFactory.getInstance().getAuditLogger(ChampRESTAPI.class.getName()); + private static Logger metricsLogger = LoggerFactory.getInstance().getMetricsLogger(ChampRESTAPI.class.getName()); + + public ChampRESTAPI(ChampDataService champDataService, ChampAsyncRequestProcessor champAsyncRequestProcessor) { + this.champDataService = champDataService; + + // Async request handling is optional. + if (champAsyncRequestProcessor != null) { + timer = new Timer("ChampAsyncRequestProcessor-1"); + timer.schedule(champAsyncRequestProcessor, champAsyncRequestProcessor.getRequestPollingTimeSeconds(), + champAsyncRequestProcessor.getRequestPollingTimeSeconds()); + } + + mapper = new ObjectMapper(); + SimpleModule module = new SimpleModule(); + module.addSerializer(ChampObject.class, new ChampObjectSerializer()); + module.addDeserializer(ChampObject.class, new ChampObjectDeserializer()); + module.addSerializer(ChampRelationship.class, new ChampRelationshipSerializer()); + module.addDeserializer(ChampRelationship.class, new ChampRelationshipDeserializer()); + mapper.registerModule(module); + } + + @GET + @Path("echo") + @Produces(MediaType.TEXT_PLAIN) + public Response echo() { + return Response.ok().entity("alive").build(); + } + + @GET + @Path("objects/{objectId}") + @Produces(MediaType.APPLICATION_JSON) + public Response getObject(@PathParam("objectId") String objectId, @QueryParam("transactionId") String tId, + @Context HttpHeaders headers, @Context UriInfo uriInfo, @Context HttpServletRequest req) { + LoggingUtil.initMdcContext(req, headers); + long startTimeInMs = System.currentTimeMillis(); + logger.info(ChampMsgs.INCOMING_REQUEST, tId, objectId); + + Response response = null; + ChampObject retrieved; + + try { + ChampTransaction transaction = champDataService.getTransaction(tId); + + if (tId != null && transaction == null) { + throw new ChampServiceException("transactionId not found", Status.BAD_REQUEST); + } + retrieved = champDataService.getObject(objectId, Optional.ofNullable(transaction)); + if (retrieved == null) { + response = Response.status(Status.NOT_FOUND).entity(objectId + " not found").build(); + } else { + response = Response.status(Status.OK).entity(mapper.writeValueAsString(retrieved)).build(); + } + + } catch (JsonProcessingException e) { + response = Response.status(Status.BAD_REQUEST).entity(e.getMessage()).build(); + } catch (ChampServiceException ce) { + response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build(); + } finally { + logger.debug(response.getEntity().toString()); + LoggingUtil.logRestRequest(logger, auditLogger, req, response); + metricsLogger.info(ChampMsgs.PROCESSED_REQUEST, "GET", Long.toString(System.currentTimeMillis() - startTimeInMs)); + } + + return response; + } + + @DELETE + @Path("objects/{objectId}") + public Response deleteObject(@PathParam("objectId") String objectId, @QueryParam("transactionId") String tId, + @Context HttpHeaders headers, @Context UriInfo uriInfo, @Context HttpServletRequest req) { + LoggingUtil.initMdcContext(req, headers); + long startTimeInMs = System.currentTimeMillis(); + logger.info(ChampMsgs.INCOMING_REQUEST, tId, objectId); + ChampObject retrieved; + Response response = null; + try { + ChampTransaction transaction = champDataService.getTransaction(tId); + + if (tId != null && transaction == null) { + throw new ChampServiceException("transactionId not found", Status.BAD_REQUEST); + } + champDataService.deleteObject(objectId, Optional.ofNullable(transaction)); + + response = Response.status(Status.OK).build(); + } catch (ChampObjectNotExistsException e) { + response = Response.status(Status.NOT_FOUND).entity(objectId + " not found").build(); + } catch (ChampServiceException ce) { + response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build(); + } catch (ChampTransactionException | ChampUnmarshallingException e) { + response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build(); + } finally { + LoggingUtil.logRestRequest(logger, auditLogger, req, response); + metricsLogger.info(ChampMsgs.PROCESSED_REQUEST, "DELETE", + Long.toString(System.currentTimeMillis() - startTimeInMs)); + } + return response; + } + + @POST + @Path("objects") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Response postObject(String champObj, @QueryParam("transactionId") String tId, @Context HttpHeaders headers, + @Context UriInfo uriInfo, @Context HttpServletRequest req) { + LoggingUtil.initMdcContext(req, headers); + long startTimeInMs = System.currentTimeMillis(); + logger.info(ChampMsgs.INCOMING_REQUEST, tId, champObj); + Response response = null; + try { + ChampTransaction transaction = champDataService.getTransaction(tId); + if (tId != null && transaction == null) { + throw new ChampServiceException("transactionId not found", Status.BAD_REQUEST); + } + ChampObject champObject = mapper.readValue(champObj, ChampObject.class); + + ChampObject created = champDataService.storeObject(champObject, Optional.ofNullable(transaction)); + response = Response.status(Status.CREATED).entity(mapper.writeValueAsString(created)).build(); + } catch (IOException e) { + response = Response.status(Status.BAD_REQUEST).entity("Unable to parse the payload").build(); + } catch (ChampServiceException ce) { + response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build(); + } catch (Exception e) { + response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build(); + LoggingUtil.logInternalError(logger, e); + } finally { + LoggingUtil.logRestRequest(logger, auditLogger, req, response); + metricsLogger.info(ChampMsgs.PROCESSED_REQUEST, "POST", + Long.toString(System.currentTimeMillis() - startTimeInMs)); + } + return response; + } + + @PUT + @Path("objects/{objectId}") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Response putObject(@PathParam("objectId") String objectId, String champObj, + @QueryParam("transactionId") String tId, @Context HttpHeaders headers, @Context UriInfo uriInfo, + @Context HttpServletRequest req) { + LoggingUtil.initMdcContext(req, headers); + long startTimeInMs = System.currentTimeMillis(); + logger.info(ChampMsgs.INCOMING_REQUEST, tId, objectId + " " + champObj); + + Response response = null; + try { + ChampTransaction transaction = champDataService.getTransaction(tId); + if (tId != null && transaction == null) { + throw new ChampServiceException("transactionId not found", Status.BAD_REQUEST); + } + + ChampObject co = mapper.readValue(champObj, ChampObject.class); + // check if key is present or if it equals the key that is in the URI + ChampObject updated = champDataService.replaceObject(co, objectId, Optional.ofNullable(transaction)); + + response = Response.status(Status.OK).entity(mapper.writeValueAsString(updated)).build(); + } catch (IOException e) { + response = Response.status(Status.BAD_REQUEST).entity("Unable to parse the payload").build(); + } catch (ChampServiceException ce) { + response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build(); + } catch (Exception e) { + response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build(); + LoggingUtil.logInternalError(logger, e); + } finally { + LoggingUtil.logRestRequest(logger, auditLogger, req, response); + metricsLogger.info(ChampMsgs.PROCESSED_REQUEST, "PUT", Long.toString(System.currentTimeMillis() - startTimeInMs)); + } + return response; + } + + @GET + @Path("objects/relationships/{oId}") + @Produces(MediaType.APPLICATION_JSON) + public Response getEdges(@PathParam("oId") String oId, @QueryParam("transactionId") String tId, + @Context HttpHeaders headers, @Context UriInfo uriInfo, @Context HttpServletRequest req) { + LoggingUtil.initMdcContext(req, headers); + long startTimeInMs = System.currentTimeMillis(); + List retrieved; + Optional rObject; + Response response = null; + ChampTransaction transaction = null; + try { + + retrieved = champDataService.getRelationshipsByObject(oId, Optional.ofNullable(transaction)); + response = Response.status(Status.OK).entity(mapper.writeValueAsString(retrieved)).build(); + } catch (JsonProcessingException e) { + response = Response.status(Status.BAD_REQUEST).entity(e.getMessage()).build(); + } catch (ChampServiceException ce) { + response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build(); + } catch (Exception e) { + response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build(); + LoggingUtil.logInternalError(logger, e); + } finally { + LoggingUtil.logRestRequest(logger, auditLogger, req, response); + metricsLogger.info(ChampMsgs.PROCESSED_REQUEST, "GET", Long.toString(System.currentTimeMillis() - startTimeInMs)); + } + return response; + } + + @GET + @Path("objects/filter/") + @Produces(MediaType.APPLICATION_JSON) + public Response filterObject(@Context HttpHeaders headers, @Context UriInfo uriInfo, + @Context HttpServletRequest req) { + LoggingUtil.initMdcContext(req, headers); + long startTimeInMs = System.currentTimeMillis(); + String propertiesKey = ChampProperties.get(ChampServiceConstants.CHAMP_COLLECTION_PROPERTIES_KEY); + List objects; + Map filter = new HashMap<>(); + + for (Map.Entry> e : uriInfo.getQueryParameters().entrySet()) { + if (!e.getKey().equals(propertiesKey)) { + filter.put(e.getKey(), e.getValue().get(0)); + } + } + + HashSet properties; + if (uriInfo.getQueryParameters().containsKey(propertiesKey)) { + properties = new HashSet<>(uriInfo.getQueryParameters().get(propertiesKey)); + } else { + properties = new HashSet<>(); + } + + Response response = null; + try { + objects = champDataService.queryObjects(filter, properties); + response = Response.status(Status.OK).type(MediaType.APPLICATION_JSON).entity(mapper.writeValueAsString(objects)) + .build(); + } catch (JsonProcessingException e) { + e.printStackTrace(); + response = Response.status(Status.BAD_REQUEST).entity(e.getMessage()).build(); + } catch (ChampServiceException e1) { + response = Response.status(e1.getHttpStatus()).entity(e1.getMessage()).build(); + } catch (Exception e) { + response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build(); + LoggingUtil.logInternalError(logger, e); + } finally { + LoggingUtil.logRestRequest(logger, auditLogger, req, response); + metricsLogger.info(ChampMsgs.PROCESSED_REQUEST, "GET", Long.toString(System.currentTimeMillis() - startTimeInMs)); + } + return response; + } + + @GET + @Path("relationships/{rId}") + @Produces(MediaType.APPLICATION_JSON) + public Response getRelationship(@PathParam("rId") String rId, @QueryParam("transactionId") String tId, + @Context HttpHeaders headers, @Context UriInfo uriInfo, @Context HttpServletRequest req) { + LoggingUtil.initMdcContext(req, headers); + long startTimeInMs = System.currentTimeMillis(); + logger.info(ChampMsgs.INCOMING_REQUEST, tId, rId); + ChampRelationship retrieved; + Response response = null; + try { + ChampTransaction transaction = champDataService.getTransaction(tId); + + if (tId != null && transaction == null) { + throw new ChampServiceException("transactionId not found", Status.BAD_REQUEST); + } + retrieved = champDataService.getRelationship(rId, Optional.ofNullable(transaction)); + if (retrieved == null) { + response = Response.status(Status.NOT_FOUND).entity(rId + " not found").build(); + return response; + } + response = Response.status(Status.OK).entity(mapper.writeValueAsString(retrieved)).build(); + + } catch (IOException e) { + response = Response.status(Status.BAD_REQUEST).entity("Unable to parse the payload").build(); + } catch (ChampServiceException ce) { + response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build(); + } catch (Exception e) { + response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build(); + LoggingUtil.logInternalError(logger, e); + } finally { + LoggingUtil.logRestRequest(logger, auditLogger, req, response); + metricsLogger.info(ChampMsgs.PROCESSED_REQUEST, "GET", Long.toString(System.currentTimeMillis() - startTimeInMs)); + } + return response; + } + + @POST + @Path("relationships") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Response postRelationships(String relationship, @QueryParam("transactionId") String tId, + @Context HttpHeaders headers, @Context UriInfo uriInfo, @Context HttpServletRequest req) { + LoggingUtil.initMdcContext(req, headers); + long startTimeInMs = System.currentTimeMillis(); + logger.info(ChampMsgs.INCOMING_REQUEST, tId, relationship); + Response response = null; + try { + ChampTransaction transaction = champDataService.getTransaction(tId); + if (tId != null && transaction == null) { + throw new ChampServiceException("transactionId not found", Status.BAD_REQUEST); + } + ChampRelationship r = mapper.readValue(relationship, ChampRelationship.class); + + ChampRelationship created = champDataService.storeRelationship(r, Optional.ofNullable(transaction)); + + response = Response.status(Status.CREATED).entity(mapper.writeValueAsString(created)).build(); + } catch (IOException e) { + response = Response.status(Status.BAD_REQUEST).entity("Unable to parse the payload").build(); + } catch (ChampServiceException ce) { + response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build(); + } catch (Exception e) { + response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build(); + LoggingUtil.logInternalError(logger, e); + } finally { + LoggingUtil.logRestRequest(logger, auditLogger, req, response); + metricsLogger.info(ChampMsgs.PROCESSED_REQUEST, "POST", + Long.toString(System.currentTimeMillis() - startTimeInMs)); + } + return response; + } + + @PUT + @Path("relationships/{rId}") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + public Response updateRelationship(@PathParam("rId") String rId, String relationship, + @QueryParam("transactionId") String tId, @Context HttpHeaders headers, @Context UriInfo uriInfo, + @Context HttpServletRequest req) { + LoggingUtil.initMdcContext(req, headers); + long startTimeInMs = System.currentTimeMillis(); + logger.info(ChampMsgs.INCOMING_REQUEST, tId, relationship); + + Response response = null; + try { + ChampTransaction transaction = champDataService.getTransaction(tId); + if (tId != null && transaction == null) { + throw new ChampServiceException("transactionId not found", Status.BAD_REQUEST); + } + ChampRelationship r = mapper.readValue(relationship, ChampRelationship.class); + ChampRelationship updated = champDataService.updateRelationship(r, rId, Optional.ofNullable(transaction)); + + response = Response.status(Status.OK).entity(mapper.writeValueAsString(updated)).build(); + } catch (IOException e) { + response = Response.status(Status.BAD_REQUEST).entity("Unable to parse the payload").build(); + } catch (ChampServiceException ce) { + response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build(); + } catch (Exception e) { + response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build(); + LoggingUtil.logInternalError(logger, e); + } finally { + LoggingUtil.logRestRequest(logger, auditLogger, req, response); + metricsLogger.info(ChampMsgs.PROCESSED_REQUEST, "PUT", Long.toString(System.currentTimeMillis() - startTimeInMs)); + } + return response; + } + + @DELETE + @Path("relationships/{relationshipId}") + public Response deleteRelationship(@PathParam("relationshipId") String relationshipId, + @QueryParam("transactionId") String tId, @Context HttpHeaders headers, @Context UriInfo uriInfo, + @Context HttpServletRequest req) { + LoggingUtil.initMdcContext(req, headers); + long startTimeInMs = System.currentTimeMillis(); + logger.info(ChampMsgs.INCOMING_REQUEST, tId, relationshipId); + + Response response = null; + try { + ChampTransaction transaction = champDataService.getTransaction(tId); + if (tId != null && transaction == null) { + throw new ChampServiceException("transactionId not found", Status.BAD_REQUEST); + } + champDataService.deleteRelationship(relationshipId, Optional.ofNullable(transaction)); + response = Response.status(Status.OK).build(); + + } catch (ChampRelationshipNotExistsException e) { + response = Response.status(Status.NOT_FOUND).entity(relationshipId + " not found").build(); + } catch (ChampServiceException ce) { + response = Response.status(ce.getHttpStatus()).entity(ce.getMessage()).build(); + } catch (ChampTransactionException | ChampUnmarshallingException e) { + response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build(); + } finally { + LoggingUtil.logRestRequest(logger, auditLogger, req, response); + metricsLogger.info(ChampMsgs.PROCESSED_REQUEST, "DELETE", + Long.toString(System.currentTimeMillis() - startTimeInMs)); + } + return response; + } + + @GET + @Path("relationships/filter/") + @Produces(MediaType.APPLICATION_JSON) + public Response filterMethod(@Context HttpHeaders headers, @Context UriInfo uriInfo, + @Context HttpServletRequest req) { + LoggingUtil.initMdcContext(req, headers); + long startTimeInMs = System.currentTimeMillis(); + List list; + Map filter = new HashMap<>(); + for (Map.Entry> e : uriInfo.getQueryParameters().entrySet()) { + filter.put(e.getKey(), e.getValue().get(0)); + } + Response response = null; + try { + list = champDataService.queryRelationships(filter); + response = Response.status(Status.OK).type(MediaType.APPLICATION_JSON).entity(mapper.writeValueAsString(list)) + .build(); + } catch (JsonProcessingException e) { + e.printStackTrace(); + response = Response.status(Status.BAD_REQUEST).entity(e.getMessage()).build(); + } catch (ChampServiceException e1) { + response = Response.status(e1.getHttpStatus()).entity(e1.getMessage()).build(); + } catch (Exception e) { + response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build(); + LoggingUtil.logInternalError(logger, e); + } finally { + LoggingUtil.logRestRequest(logger, auditLogger, req, response); + metricsLogger.info(ChampMsgs.PROCESSED_REQUEST, "GET", Long.toString(System.currentTimeMillis() - startTimeInMs)); + } + return response; + } + + @POST + @Path("transaction") + @Produces(MediaType.TEXT_PLAIN) + public Response openTransaction(@Context HttpHeaders headers, @Context UriInfo uriInfo, + @Context HttpServletRequest req) { + LoggingUtil.initMdcContext(req, headers); + long startTimeInMs = System.currentTimeMillis(); + Status s; + String transaction = champDataService.openTransaction(); + + s = Status.OK; + Response response = Response.status(s).entity(transaction).build(); + logger.info(ChampMsgs.PROCESS_EVENT, "Opened Transaction with ID: " + transaction, s.toString()); + LoggingUtil.logRestRequest(logger, auditLogger, req, response); + metricsLogger.info(ChampMsgs.PROCESSED_REQUEST, "POST", Long.toString(System.currentTimeMillis() - startTimeInMs)); + return response; + } + + @GET + @Path("transaction/{tId}") + public Response getSpecificTransaction(@PathParam("tId") String tId, @Context HttpHeaders headers, + @Context UriInfo uriInfo, @Context HttpServletRequest req) { + LoggingUtil.initMdcContext(req, headers); + long startTimeInMs = System.currentTimeMillis(); + + Response response = null; + ChampTransaction transaction = champDataService.getTransaction(tId); + if (transaction == null) { + response = Response.status(Status.NOT_FOUND).entity("transaction " + tId + " not found").build(); + return response; + } + + try { + response = Response.status(Status.OK).entity(mapper.writeValueAsString(tId + " is OPEN")).build(); + } catch (JsonProcessingException e) { + response = Response.status(Status.BAD_REQUEST).entity(e.getMessage()).build(); + } catch (Exception e) { + response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build(); + LoggingUtil.logInternalError(logger, e); + } finally { + LoggingUtil.logRestRequest(logger, auditLogger, req, response); + metricsLogger.info(ChampMsgs.PROCESSED_REQUEST, "GET", Long.toString(System.currentTimeMillis() - startTimeInMs)); + } + return response; + } + + @PUT + @Path("transaction/{tId}") + @Produces(MediaType.TEXT_PLAIN) + @Consumes(MediaType.APPLICATION_JSON) + public Response updateTransaction(String t, @PathParam("tId") String tId, @Context HttpHeaders headers, + @Context UriInfo uriInfo, @Context HttpServletRequest req) { + LoggingUtil.initMdcContext(req, headers); + long startTimeInMs = System.currentTimeMillis(); + logger.info(ChampMsgs.INCOMING_REQUEST, tId, "COMMIT/ROLLBACK"); + + Response response = null; + try { + JSONObject jsonObj = new JSONObject(t); + String method = jsonObj.getString(this.TRANSACTION_METHOD); + + if (method.equals("commit")) { + champDataService.commitTransaction(tId); + response = Response.status(Status.OK).entity("COMMITTED").build(); + + } else if (method.equals("rollback")) { + champDataService.rollbackTransaction(tId); + response = Response.status(Status.OK).entity("ROLLED BACK").build(); + } else { + response = Response.status(Status.BAD_REQUEST).entity("Invalid Method: " + method).build(); + return response; + } + + } catch (ChampTransactionException e) { + response = Response.status(Status.BAD_REQUEST).entity(e.getMessage()).build(); + } catch (JSONException e) { + response = Response.status(Status.BAD_REQUEST).entity(e.getMessage()).build(); + } catch (ChampServiceException e) { + response = Response.status(e.getHttpStatus()).entity(e.getMessage()).build(); + } catch (Exception e) { + response = Response.status(Status.INTERNAL_SERVER_ERROR).entity(e.getMessage()).build(); + LoggingUtil.logInternalError(logger, e); + } finally { + LoggingUtil.logRestRequest(logger, auditLogger, req, response); + metricsLogger.info(ChampMsgs.PROCESSED_REQUEST, "PUT", Long.toString(System.currentTimeMillis() - startTimeInMs)); + } + return response; + } + +} diff --git a/champ-service/src/main/java/org/onap/champ/async/ChampAsyncRequestProcessor.java b/champ-service/src/main/java/org/onap/champ/async/ChampAsyncRequestProcessor.java new file mode 100644 index 0000000..af2ab20 --- /dev/null +++ b/champ-service/src/main/java/org/onap/champ/async/ChampAsyncRequestProcessor.java @@ -0,0 +1,327 @@ +/** + * ============LICENSE_START======================================================= + * Gizmo + * ================================================================================ + * Copyright © 2017 AT&T Intellectual Property. + * Copyright © 2017 Amdocs + * All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR 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. + */ +package org.onap.champ.async; + +import java.util.Optional; +import java.util.TimerTask; +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadPoolExecutor; + +import javax.naming.OperationNotSupportedException; +import javax.ws.rs.core.Response.Status; + +import org.onap.aai.champcore.ChampTransaction; +import org.onap.aai.cl.api.Logger; +import org.onap.aai.cl.eelf.LoggerFactory; +import org.onap.champ.ChampRESTAPI; +import org.onap.champ.event.GraphEvent; +import org.onap.champ.event.GraphEvent.GraphEventResult; +import org.onap.champ.event.GraphEventEdge; +import org.onap.champ.event.GraphEventVertex; +import org.onap.champ.exception.ChampServiceException; +import org.onap.champ.service.ChampDataService; +import org.onap.champ.service.ChampThreadFactory; +import org.onap.champ.service.logging.ChampMsgs; + +import org.onap.aai.event.api.EventConsumer; + +/** + * This Class polls the Graph events from request topic perform the necessary + * CRUD operation by calling champDAO and queues up the response to be consumed + * by response handler. + */ +public class ChampAsyncRequestProcessor extends TimerTask { + + private Logger logger = LoggerFactory.getInstance().getLogger(ChampAsyncRequestProcessor.class); + + private ChampDataService champDataService; + + /** + * Number of events that can be queued up. + */ + private Integer requestProcesserQueueSize; + + /** + * Number of event publisher worker threads. + */ + private Integer requestProcesserPoolSize; + + /** + * Number of event publisher worker threads. + */ + private Integer requestPollingTimeSeconds; + + /** + * Internal queue where outgoing events will be buffered until they can be + * serviced by. + **/ + private BlockingQueue requestProcesserEventQueue; + + /** + * Pool of worker threads that do the work of publishing the events to the + * event bus. + */ + private ThreadPoolExecutor requestProcesserPool; + + private ChampAsyncResponsePublisher champAsyncResponsePublisher; + + private EventConsumer asyncRequestConsumer; + + private static final Integer DEFAULT_ASYNC_REQUEST_PROCESS_QUEUE_CAPACITY = 10000; + + private static final Integer DEFAULT_ASYNC_REQUEST_PROCESS_THREAD_POOL_SIZE = 10; + private static final Integer DEFAULT_ASYNC_REQUEST_PROCESS_POLLING_SECOND = 30000; + private static final String CHAMP_GRAPH_REQUEST_PROCESS_THREAD_NAME = "ChampAsyncGraphRequestEventProcessor"; + Logger auditLogger = LoggerFactory.getInstance().getAuditLogger(ChampRESTAPI.class.getName()); + + public ChampAsyncRequestProcessor(ChampDataService champDataService, + ChampAsyncResponsePublisher champAsyncResponsePublisher, EventConsumer asyncRequestConsumer) { + + this.requestProcesserQueueSize = DEFAULT_ASYNC_REQUEST_PROCESS_QUEUE_CAPACITY; + + this.requestProcesserPoolSize = DEFAULT_ASYNC_REQUEST_PROCESS_THREAD_POOL_SIZE; + + this.requestPollingTimeSeconds = DEFAULT_ASYNC_REQUEST_PROCESS_POLLING_SECOND; + requestProcesserEventQueue = new ArrayBlockingQueue(requestProcesserQueueSize); + requestProcesserPool = (ThreadPoolExecutor) Executors.newFixedThreadPool(requestProcesserPoolSize, + new ChampThreadFactory(CHAMP_GRAPH_REQUEST_PROCESS_THREAD_NAME)); + + for (int i = 0; i < requestProcesserPoolSize; i++) { + requestProcesserPool.submit(new ChampProcessorWorker()); + } + + this.champDataService = champDataService; + this.champAsyncResponsePublisher = champAsyncResponsePublisher; + this.asyncRequestConsumer = asyncRequestConsumer; + logger.info(ChampMsgs.CHAMP_ASYNC_REQUEST_PROCESSOR_INFO, + "ChampAsyncRequestProcessor initialized SUCCESSFULLY! with event consumer " + + asyncRequestConsumer.getClass().getName()); + } + + + + public ChampAsyncRequestProcessor(ChampDataService champDataService, + ChampAsyncResponsePublisher champAsyncResponsePublisher, EventConsumer asyncRequestConsumer, + Integer requestProcesserQueueSize, Integer requestProcesserPoolSize, Integer requestPollingTimeSeconds) { + + this.requestProcesserQueueSize = requestProcesserQueueSize; + + this.requestProcesserPoolSize = requestProcesserPoolSize; + + this.requestPollingTimeSeconds = requestPollingTimeSeconds; + + requestProcesserEventQueue = new ArrayBlockingQueue(requestProcesserQueueSize); + requestProcesserPool = (ThreadPoolExecutor) Executors.newFixedThreadPool(requestProcesserPoolSize, + new ChampThreadFactory(CHAMP_GRAPH_REQUEST_PROCESS_THREAD_NAME)); + + for (int i = 0; i < requestProcesserPoolSize; i++) { + requestProcesserPool.submit(new ChampProcessorWorker()); + } + + this.champDataService = champDataService; + this.champAsyncResponsePublisher = champAsyncResponsePublisher; + this.asyncRequestConsumer = asyncRequestConsumer; + logger.info(ChampMsgs.CHAMP_ASYNC_REQUEST_PROCESSOR_INFO, + "ChampAsyncRequestProcessor initialized SUCCESSFULLY! with event consumer " + + asyncRequestConsumer.getClass().getName()); + } + + private class ChampProcessorWorker implements Runnable { + + @Override + public void run() { + + while (true) { + + GraphEvent event = null; + try { + // Get the next event to be published from the queue. + event = requestProcesserEventQueue.take(); + } catch (InterruptedException e) { + // Restore the interrupted status. + Thread.currentThread().interrupt(); + } + + // Parse the event and call champ Dao to process , Create the + // response event and put it on response queue + event.setResult(GraphEventResult.SUCCESS); + + // Check if this request is part of an ongoing DB transaction + ChampTransaction transaction = champDataService.getTransaction(event.getDbTransactionId()); + if ( (event.getDbTransactionId() != null) && (transaction == null) ) { + event.setResult(GraphEventResult.FAILURE); + event.setErrorMessage("Database transactionId " + event.getDbTransactionId() + " not found"); + event.setHttpErrorStatus(Status.BAD_REQUEST); + } + + if (event.getResult() != GraphEventResult.FAILURE) { + try { + if (event.getVertex() != null) { + + switch (event.getOperation()) { + case CREATE: + event.setVertex(GraphEventVertex.fromChampObject( + champDataService.storeObject(event.getVertex().toChampObject(), Optional.ofNullable(transaction)), + event.getVertex().getModelVersion())); + break; + + case UPDATE: + event.setVertex(GraphEventVertex.fromChampObject( + champDataService.replaceObject(event.getVertex().toChampObject(), event.getVertex().getId(), Optional.ofNullable(transaction)), + event.getVertex().getModelVersion())); + break; + case DELETE: + champDataService.deleteObject(event.getVertex().getId(), Optional.ofNullable(transaction)); + break; + default: + // log error + } + } else if (event.getEdge() != null) { + switch (event.getOperation()) { + case CREATE: + event.setEdge(GraphEventEdge.fromChampRelationship( + champDataService.storeRelationship(event.getEdge().toChampRelationship(), Optional.ofNullable(transaction)), + event.getEdge().getModelVersion())); + break; + + case UPDATE: + event.setEdge(GraphEventEdge.fromChampRelationship(champDataService + .updateRelationship(event.getEdge().toChampRelationship(), event.getEdge().getId(), Optional.ofNullable(transaction)), + event.getEdge().getModelVersion())); + + break; + case DELETE: + champDataService.deleteRelationship(event.getEdge().getId(), Optional.ofNullable(transaction)); + break; + default: + logger.error(ChampMsgs.CHAMP_ASYNC_REQUEST_PROCESSOR_ERROR, + "Invalid operation for event transactionId: " + event.getTransactionId()); + } + + } else { + logger.error(ChampMsgs.CHAMP_ASYNC_REQUEST_PROCESSOR_ERROR, + "Invalid payload for event transactionId: " + event.getTransactionId()); + } + } catch (ChampServiceException champException) { + logger.error(ChampMsgs.CHAMP_ASYNC_REQUEST_PROCESSOR_ERROR, champException.getMessage()); + event.setResult(GraphEventResult.FAILURE); + event.setErrorMessage(champException.getMessage()); + event.setHttpErrorStatus(champException.getHttpStatus()); + + } catch (Exception ex) { + logger.error(ChampMsgs.CHAMP_ASYNC_REQUEST_PROCESSOR_ERROR, ex.getMessage()); + event.setResult(GraphEventResult.FAILURE); + event.setErrorMessage(ex.getMessage()); + event.setHttpErrorStatus(Status.INTERNAL_SERVER_ERROR); + } + } + + if (event.getResult().equals(GraphEventResult.SUCCESS)) { + logger.info(ChampMsgs.CHAMP_ASYNC_REQUEST_PROCESSOR_INFO, + "Event processed of type: " + event.getObjectType() + " with key: " + event.getObjectKey() + + " , transaction-id: " + event.getTransactionId() + " , operation: " + + event.getOperation().toString() + " , result: " + event.getResult()); + } else { + logger.info(ChampMsgs.CHAMP_ASYNC_REQUEST_PROCESSOR_INFO, + "Event processed of type: " + event.getObjectType() + " with key: " + event.getObjectKey() + + " , transaction-id: " + event.getTransactionId() + " , operation: " + + event.getOperation().toString() + " , result: " + event.getResult() + " , error: " + + event.getErrorMessage()); + } + + champAsyncResponsePublisher.publishResponseEvent(event); + + } + } + } + + @Override + public void run() { + + logger.info(ChampMsgs.CHAMP_ASYNC_REQUEST_PROCESSOR_INFO, "Listening for graph events"); + + if (asyncRequestConsumer == null) { + logger.error(ChampMsgs.CHAMP_ASYNC_REQUEST_PROCESSOR_ERROR, "Unable to initialize ChampAsyncRequestProcessor"); + } + + Iterable events = null; + try { + events = asyncRequestConsumer.consume(); + } catch (Exception e) { + logger.error(ChampMsgs.CHAMP_ASYNC_REQUEST_PROCESSOR_ERROR, e.getMessage()); + return; + } + + if (events == null || !events.iterator().hasNext()) { + logger.info(ChampMsgs.CHAMP_ASYNC_REQUEST_PROCESSOR_INFO, "No events recieved"); + + } + + for (String event : events) { + try { + GraphEvent requestEvent = GraphEvent.fromJson(event); + auditLogger.info(ChampMsgs.CHAMP_ASYNC_REQUEST_PROCESSOR_INFO, + "Event received of type: " + requestEvent.getObjectType() + " with key: " + requestEvent.getObjectKey() + + " , transaction-id: " + requestEvent.getTransactionId() + " , operation: " + + requestEvent.getOperation().toString()); + logger.info(ChampMsgs.CHAMP_ASYNC_REQUEST_PROCESSOR_INFO, + "Event received of type: " + requestEvent.getObjectType() + " with key: " + requestEvent.getObjectKey() + + " , transaction-id: " + requestEvent.getTransactionId() + " , operation: " + + requestEvent.getOperation().toString()); + logger.debug(ChampMsgs.CHAMP_ASYNC_REQUEST_PROCESSOR_INFO, "Event received with payload:" + event); + + // Try to submit the event to be published to the event bus. + if (!requestProcesserEventQueue.offer(requestEvent)) { + logger.error(ChampMsgs.CHAMP_ASYNC_REQUEST_PROCESSOR_ERROR, + "Event could not be published to the event bus due to: Internal buffer capacity exceeded."); + } + + } catch (Exception e) { + logger.error(ChampMsgs.CHAMP_ASYNC_REQUEST_PROCESSOR_ERROR, e.getMessage()); + } + } + + try { + asyncRequestConsumer.commitOffsets(); + } catch(OperationNotSupportedException e) { + //Dmaap doesnt support commit with offset + logger.debug(ChampMsgs.CHAMP_ASYNC_REQUEST_PROCESSOR_WARN, e.getMessage()); + } + catch (Exception e) { + logger.error(ChampMsgs.CHAMP_ASYNC_REQUEST_PROCESSOR_WARN, e.getMessage()); + } + + } + + + + public Integer getRequestPollingTimeSeconds() { + return requestPollingTimeSeconds; + } + + +} diff --git a/champ-service/src/main/java/org/onap/champ/async/ChampAsyncResponsePublisher.java b/champ-service/src/main/java/org/onap/champ/async/ChampAsyncResponsePublisher.java new file mode 100644 index 0000000..8c31a53 --- /dev/null +++ b/champ-service/src/main/java/org/onap/champ/async/ChampAsyncResponsePublisher.java @@ -0,0 +1,160 @@ +/** + * ============LICENSE_START======================================================= + * + * ================================================================================ + * Copyright © 2017 AT&T Intellectual Property. + * Copyright © 2017 Amdocs + * All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR 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. + */ +package org.onap.champ.async; + +import java.util.concurrent.ArrayBlockingQueue; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadPoolExecutor; + +import org.onap.aai.cl.api.Logger; +import org.onap.aai.cl.eelf.LoggerFactory; +import org.onap.champ.event.GraphEvent; +import org.onap.champ.event.GraphEvent.GraphEventResult; +import org.onap.champ.service.ChampThreadFactory; +import org.onap.champ.service.logging.ChampMsgs; + +import org.onap.aai.event.api.EventPublisher; + +public class ChampAsyncResponsePublisher { + + private EventPublisher asyncResponsePublisher; + + /** + * Number of events that can be queued up. + */ + private Integer responsePublisherQueueSize; + + /** + * Number of event publisher worker threads. + */ + private Integer responsePublisherPoolSize; + + /** + * Internal queue where outgoing events will be buffered. + **/ + private BlockingQueue responsePublisherEventQueue; + + /** + * Pool of worker threads that do the work of publishing the events to the + * event bus. + */ + private ThreadPoolExecutor responsePublisherPool; + + private static final Integer DEFAULT_ASYNC_RESPONSE_PUBLISH_QUEUE_CAPACITY = 10000; + + private static final Integer DEFAULT_ASYNC_RESPONSE_PUBLISH_THREAD_POOL_SIZE = 10; + private static final String CHAMP_GRAPH_RESPONSE_PUBLISH_THREAD_NAME = "ChampAsyncGraphResponseEventPublisher"; + + private static Logger logger = LoggerFactory.getInstance().getLogger(ChampAsyncRequestProcessor.class.getName()); + + public ChampAsyncResponsePublisher(EventPublisher asyncResponsePublisher, Integer responsePublisherQueueSize, + Integer responsePublisherPoolSize) { + this.responsePublisherQueueSize = responsePublisherQueueSize; + + this.responsePublisherPoolSize = responsePublisherPoolSize; + + responsePublisherEventQueue = new ArrayBlockingQueue(responsePublisherQueueSize); + responsePublisherPool = (ThreadPoolExecutor) Executors.newFixedThreadPool(responsePublisherPoolSize, + new ChampThreadFactory(CHAMP_GRAPH_RESPONSE_PUBLISH_THREAD_NAME)); + + for (int i = 0; i < responsePublisherPoolSize; i++) { + responsePublisherPool.submit(new GizmoResponsePublisherWorker()); + } + this.asyncResponsePublisher = asyncResponsePublisher; + + logger.info(ChampMsgs.CHAMP_ASYNC_RESPONSE_PUBLISHER_INFO, + "ChampAsyncResponsePublisher initialized SUCCESSFULLY! with event publisher " + + asyncResponsePublisher.getClass().getName()); + } + + public ChampAsyncResponsePublisher(EventPublisher asyncResponsePublisher) { + responsePublisherQueueSize = DEFAULT_ASYNC_RESPONSE_PUBLISH_QUEUE_CAPACITY; + + responsePublisherPoolSize = DEFAULT_ASYNC_RESPONSE_PUBLISH_THREAD_POOL_SIZE; + + responsePublisherEventQueue = new ArrayBlockingQueue(responsePublisherQueueSize); + responsePublisherPool = (ThreadPoolExecutor) Executors.newFixedThreadPool(responsePublisherPoolSize, + new ChampThreadFactory(CHAMP_GRAPH_RESPONSE_PUBLISH_THREAD_NAME)); + + for (int i = 0; i < responsePublisherPoolSize; i++) { + responsePublisherPool.submit(new GizmoResponsePublisherWorker()); + } + this.asyncResponsePublisher = asyncResponsePublisher; + + logger.info(ChampMsgs.CHAMP_ASYNC_RESPONSE_PUBLISHER_INFO, + "CrudAsyncResponsePublisher initialized SUCCESSFULLY! with event publisher " + + asyncResponsePublisher.getClass().getName()); + } + + public void publishResponseEvent(GraphEvent event) { + responsePublisherEventQueue.offer(event); + + } + + private class GizmoResponsePublisherWorker implements Runnable { + + @Override + public void run() { + + while (true) { + + GraphEvent event = null; + try { + + // Get the next event to be published from the queue. + event = responsePublisherEventQueue.take(); + + } catch (InterruptedException e) { + + // Restore the interrupted status. + Thread.currentThread().interrupt(); + } + // Publish the response + + try { + event.setTimestamp(System.currentTimeMillis()); + asyncResponsePublisher.sendSync(event.toJson()); + if (event.getResult().equals(GraphEventResult.SUCCESS)) { + logger.info(ChampMsgs.CHAMP_ASYNC_RESPONSE_PUBLISHER_INFO, + "Response published for Event of type: " + event.getObjectType() + " with key: " + event.getObjectKey() + + " , transaction-id: " + event.getTransactionId() + " , operation: " + + event.getOperation().toString() + " , result: " + event.getResult()); + } else { + logger.info(ChampMsgs.CHAMP_ASYNC_RESPONSE_PUBLISHER_INFO, + "Response published for Event of type: " + event.getObjectType() + " with key: " + event.getObjectKey() + + " , transaction-id: " + event.getTransactionId() + " , operation: " + + event.getOperation().toString() + " , result: " + event.getResult() + " , error: " + + event.getErrorMessage()); + } + } catch (Exception ex) { + logger.error(ChampMsgs.CHAMP_ASYNC_RESPONSE_PUBLISHER_ERROR, ex.getMessage()); + } + + } + } + } + +} diff --git a/champ-service/src/main/java/org/onap/champ/entity/ChampObjectDeserializer.java b/champ-service/src/main/java/org/onap/champ/entity/ChampObjectDeserializer.java new file mode 100644 index 0000000..cee7763 --- /dev/null +++ b/champ-service/src/main/java/org/onap/champ/entity/ChampObjectDeserializer.java @@ -0,0 +1,67 @@ +/** + * ============LICENSE_START========================================== + * org.onap.aai + * =================================================================== + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 Amdocs + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END============================================ + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.champ.entity; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import org.onap.aai.champcore.model.ChampObject; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; + +public class ChampObjectDeserializer extends StdDeserializer { + + private static final long serialVersionUID = -3625275249560680339L; + + public ChampObjectDeserializer() { + this(null); + } + + protected ChampObjectDeserializer(Class t) { + super(t); + } + + public ChampObject deserialize(JsonParser jparser, DeserializationContext dctx) + throws IOException, JsonProcessingException { + + JsonNode node = jparser.getCodec().readTree(jparser); + JsonNode type = node.get("type"); + JsonNode key = node.get("key"); + Map props = new HashMap<>(); + JsonNode propNode = node.get("properties"); + propNode.fields().forEachRemaining((x)->props.put(x.getKey(), x.getValue().asText())); + + ChampObject.Builder builder = new ChampObject.Builder(type.asText()).properties(props); + + if(key != null){ + builder.key(key.asText()); + } + + return builder.build(); + } + +} diff --git a/champ-service/src/main/java/org/onap/champ/entity/ChampObjectSerializer.java b/champ-service/src/main/java/org/onap/champ/entity/ChampObjectSerializer.java new file mode 100644 index 0000000..c43b6bf --- /dev/null +++ b/champ-service/src/main/java/org/onap/champ/entity/ChampObjectSerializer.java @@ -0,0 +1,54 @@ +/** + * ============LICENSE_START========================================== + * org.onap.aai + * =================================================================== + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 Amdocs + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END============================================ + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.champ.entity; + +import java.io.IOException; + +import org.onap.aai.champcore.model.ChampObject; + +import com.fasterxml.jackson.core.JsonGenerationException; +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.ser.std.StdSerializer; + +public class ChampObjectSerializer extends StdSerializer { + + private static final long serialVersionUID = -4057960968983473983L; + + public ChampObjectSerializer() { + this(null); + } + + protected ChampObjectSerializer(Class t) { + super(t); + } + + public void serialize(ChampObject co, JsonGenerator jgen, SerializerProvider ser) + throws IOException, JsonGenerationException { + jgen.writeStartObject(); + jgen.writeStringField("key", co.getKeyValue().toString()); + jgen.writeStringField("type", co.getType()); + jgen.writeObjectField("properties", co.getProperties()); + jgen.writeEndObject(); + } + +} diff --git a/champ-service/src/main/java/org/onap/champ/entity/ChampRelationshipDeserializer.java b/champ-service/src/main/java/org/onap/champ/entity/ChampRelationshipDeserializer.java new file mode 100644 index 0000000..63b9e0c --- /dev/null +++ b/champ-service/src/main/java/org/onap/champ/entity/ChampRelationshipDeserializer.java @@ -0,0 +1,73 @@ +/** + * ============LICENSE_START========================================== + * org.onap.aai + * =================================================================== + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 Amdocs + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END============================================ + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.champ.entity; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.deser.std.StdDeserializer; + +import org.onap.aai.champcore.model.ChampObject; +import org.onap.aai.champcore.model.ChampRelationship; + +public class ChampRelationshipDeserializer extends StdDeserializer { + + private static final long serialVersionUID = -3625275249560680339L; + + public ChampRelationshipDeserializer() { + this(null); + } + + protected ChampRelationshipDeserializer(Class t) { + super(t); + } + + public ChampRelationship deserialize(JsonParser jparser, DeserializationContext dctx) + throws IOException, JsonProcessingException { + + JsonNode node = jparser.getCodec().readTree(jparser); + JsonNode type = node.get("type"); + JsonNode key = node.get("key"); + Map props = new HashMap<>(); + JsonNode propNode = node.get("properties"); + propNode.fields().forEachRemaining((x)->props.put(x.getKey(), x.getValue().asText())); + + JsonNode srcNode = node.get("source"); + JsonNode targetNode = node.get("target"); + + ChampObject src = jparser.getCodec ().treeToValue ( srcNode, ChampObject.class ); + ChampObject target = jparser.getCodec ().treeToValue ( targetNode, ChampObject.class ); + + ChampRelationship.Builder builder = new ChampRelationship.Builder(src, target, type.asText()).properties(props); + + if(key != null){ + builder.key(key.asText()); + } + + return builder.build(); + } + +} diff --git a/champ-service/src/main/java/org/onap/champ/entity/ChampRelationshipSerializer.java b/champ-service/src/main/java/org/onap/champ/entity/ChampRelationshipSerializer.java new file mode 100644 index 0000000..5d21aa5 --- /dev/null +++ b/champ-service/src/main/java/org/onap/champ/entity/ChampRelationshipSerializer.java @@ -0,0 +1,55 @@ +/** + * ============LICENSE_START========================================== + * org.onap.aai + * =================================================================== + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 Amdocs + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END============================================ + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.champ.entity; + +import com.fasterxml.jackson.core.JsonGenerationException; +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.databind.SerializerProvider; +import com.fasterxml.jackson.databind.ser.std.StdSerializer; +import org.onap.aai.champcore.model.ChampRelationship; + +import java.io.IOException; + +public class ChampRelationshipSerializer extends StdSerializer { + + private static final long serialVersionUID = -4057960968983473983L; + + public ChampRelationshipSerializer() { + this(null); + } + + protected ChampRelationshipSerializer(Class t) { + super(t); + } + + public void serialize( ChampRelationship cr, JsonGenerator jgen, SerializerProvider ser) + throws IOException, JsonGenerationException { + jgen.writeStartObject(); + jgen.writeStringField("key", cr.getKeyValue().toString()); + jgen.writeStringField("type", cr.getType()); + jgen.writeObjectField("properties", cr.getProperties()); + jgen.writeObjectField ("source", cr.getSource()); + jgen.writeObjectField ("target", cr.getTarget ()); + jgen.writeEndObject(); + } + +} diff --git a/champ-service/src/main/java/org/onap/champ/event/GraphEvent.java b/champ-service/src/main/java/org/onap/champ/event/GraphEvent.java new file mode 100644 index 0000000..d649a3e --- /dev/null +++ b/champ-service/src/main/java/org/onap/champ/event/GraphEvent.java @@ -0,0 +1,245 @@ +/** + * ============LICENSE_START======================================================= + * Gizmo + * ================================================================================ + * Copyright © 2017 AT&T Intellectual Property. + * Copyright © 2017 Amdocs + * All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR 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. + */ +package org.onap.champ.event; + +import javax.ws.rs.core.Response.Status; + +import org.onap.champ.exception.ChampServiceException; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.annotations.SerializedName; + +public class GraphEvent { + + public enum GraphEventOperation { + CREATE, UPDATE, DELETE + } + + public enum GraphEventResult { + SUCCESS, FAILURE + } + + private GraphEventOperation operation; + + @SerializedName("transaction-id") + private String transactionId; + + @SerializedName("database-transaction-id") + private String dbTransactionId; + + private long timestamp; + + private GraphEventVertex vertex; + + private GraphEventEdge edge; + + private GraphEventResult result; + + @SerializedName("error-message") + private String errorMessage; + + private Status httpErrorStatus; + + /** + * Marshaller/unmarshaller for converting to/from JSON. + */ + private static final Gson gson = new GsonBuilder().disableHtmlEscaping() + .setPrettyPrinting().create(); + + public static Builder builder(GraphEventOperation operation) { + return new Builder(operation); + } + + public GraphEventOperation getOperation() { + return operation; + } + + public String getTransactionId() { + return transactionId; + } + + public String getDbTransactionId() { + return dbTransactionId; + } + + public void setDbTransactionId(String id) { + dbTransactionId = id; + } + + public long getTimestamp() { + return timestamp; + } + + public GraphEventVertex getVertex() { + return vertex; + } + + public GraphEventEdge getEdge() { + return edge; + } + + public GraphEventResult getResult() { + return result; + } + + public String getErrorMessage() { + return errorMessage; + } + + public void setResult(GraphEventResult result) { + this.result = result; + } + + + public Status getHttpErrorStatus() { + return httpErrorStatus; + } + + public void setHttpErrorStatus(Status httpErrorStatus) { + this.httpErrorStatus = httpErrorStatus; + } + + public void setTimestamp(long timestamp) { + this.timestamp = timestamp; + } + + public void setErrorMessage(String errorMessage) { + this.errorMessage = errorMessage; + } + + public void setVertex(GraphEventVertex vertex) { + this.vertex = vertex; + } + + public void setEdge(GraphEventEdge edge) { + this.edge = edge; + } + + /** + * Unmarshalls this Vertex object into a JSON string. + * + * @return - A JSON format string representation of this Vertex. + */ + public String toJson() { + return gson.toJson(this); + } + + /** + * Marshalls the provided JSON string into a Vertex object. + * + * @param json - The JSON string to produce the Vertex from. + * @return - A Vertex object. + * @throws SpikeException + */ + public static GraphEvent fromJson(String json) throws ChampServiceException { + + try { + + // Make sure that we were actually provided a non-empty string + // before we + // go any further. + if (json == null || json.isEmpty()) { + throw new ChampServiceException("Empty or null JSON string.", Status.BAD_REQUEST); + } + + // Marshall the string into a Vertex object. + return gson.fromJson(json, GraphEvent.class); + + } catch (Exception ex) { + throw new ChampServiceException("Unable to parse JSON string: ", Status.BAD_REQUEST); + } + } + + @Override + public String toString() { + + return toJson(); + } + + public String getObjectKey() { + if (this.getVertex() != null) { + return this.getVertex().getId(); + } else if (this.getEdge() != null) { + return this.getEdge().getId(); + } + + return null; + } + + public String getObjectType() { + if (this.getVertex() != null) { + return "vertex->" + this.getVertex().getType(); + } else if (this.getEdge() != null) { + return "edge->" + this.getEdge().getType(); + } + + return null; + } + + public static class Builder { + + GraphEvent event = null; + + public Builder(GraphEventOperation operation) { + event = new GraphEvent(); + event.operation = operation; + } + + public Builder vertex(GraphEventVertex vertex) { + event.vertex = vertex; + return this; + } + + public Builder edge(GraphEventEdge edge) { + event.edge = edge; + return this; + } + + public Builder result(GraphEventResult result) { + event.result = result; + return this; + } + + public Builder errorMessage(String errorMessage) { + event.errorMessage = errorMessage; + return this; + } + + public Builder httpErrorStatus(Status httpErrorStatus) { + event.httpErrorStatus = httpErrorStatus; + return this; + } + + public GraphEvent build() { + + event.timestamp = System.currentTimeMillis(); + event.transactionId = java.util.UUID.randomUUID().toString(); + + return event; + } + } + +} diff --git a/champ-service/src/main/java/org/onap/champ/event/GraphEventEdge.java b/champ-service/src/main/java/org/onap/champ/event/GraphEventEdge.java new file mode 100644 index 0000000..1ab4804 --- /dev/null +++ b/champ-service/src/main/java/org/onap/champ/event/GraphEventEdge.java @@ -0,0 +1,221 @@ +/** + * ============LICENSE_START======================================================= + * Gizmo + * ================================================================================ + * Copyright © 2017 AT&T Intellectual Property. + * Copyright © 2017 Amdocs + * All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR 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. + */ +package org.onap.champ.event; + +import java.util.Map; + +import javax.ws.rs.core.Response.Status; + +import org.onap.aai.champcore.model.ChampObject; +import org.onap.aai.champcore.model.ChampRelationship; +import org.onap.champ.exception.ChampServiceException; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.annotations.SerializedName; +import com.google.gson.reflect.TypeToken; + +/** + * This class provides a generic representation of an Edge as provided by the + * graph data store. + */ +public class GraphEventEdge { + + /** + * The unique identifier used to identify this edge in the graph data store. + */ + @SerializedName("key") + private String id; + + @SerializedName("schema-version") + private String modelVersion; + + /** + * Type label assigned to this vertex. + */ + private String type; + + /** + * Source vertex for our edge. + */ + private GraphEventVertex source; + + /** + * Target vertex for our edge. + */ + private GraphEventVertex target; + + /** + * Map of all of the properties assigned to this vertex. + */ + private JsonElement properties; + + /** + * Marshaller/unmarshaller for converting to/from JSON. + */ + private static final Gson gson = new GsonBuilder().disableHtmlEscaping().create(); + + public GraphEventEdge(String id, String modelVersion, String type, GraphEventVertex source, + GraphEventVertex target, JsonElement properties) { + this.id = id; + this.modelVersion = modelVersion; + this.type = type; + this.source = source; + this.target = target; + this.properties = properties; + } + + public GraphEventEdge() { + + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public GraphEventVertex getSource() { + return source; + } + + public void setSource(GraphEventVertex source) { + this.source = source; + } + + public GraphEventVertex getTarget() { + return target; + } + + public void setTarget(GraphEventVertex target) { + this.target = target; + } + + public JsonElement getProperties() { + return properties; + } + + public void setProperties(JsonElement properties) { + this.properties = properties; + } + + public String getModelVersion() { + return modelVersion; + } + + public void setModelVersion(String modelVersion) { + this.modelVersion = modelVersion; + } + + /** + * Unmarshalls this Edge object into a JSON string. + * + * @return - A JSON format string representation of this Edge. + */ + public String toJson() { + return gson.toJson(this); + } + + /** + * Marshalls the provided JSON string into a Edge object. + * + * @param json - The JSON string to produce the Edge from. + * @return - A Edge object. + * @throws SpikeException + */ + public static GraphEventEdge fromJson(String json) throws ChampServiceException { + + try { + + // Make sure that we were actually provided a non-empty string + // before we + // go any further. + if (json == null || json.isEmpty()) { + throw new ChampServiceException("Unable to parse JSON string: ", Status.BAD_REQUEST); + } + + // Marshall the string into an Edge object. + return gson.fromJson(json, GraphEventEdge.class); + + } catch (Exception ex) { + throw new ChampServiceException("Unable to parse JSON string: ", Status.BAD_REQUEST); + } + } + + public static GraphEventEdge fromChampRelationship(ChampRelationship edge, String modelVersion) { + + java.lang.reflect.Type mapType = new TypeToken>() {}.getType(); + JsonObject props = gson.toJsonTree(edge.getProperties(), mapType).getAsJsonObject(); + + GraphEventEdge graphEventEdge = new GraphEventEdge(edge.getKey().orElse("").toString(), modelVersion, + edge.getType(), new GraphEventVertex(edge.getSource().getKey().orElse("").toString(), null, + edge.getSource().getType(), null), new GraphEventVertex(edge.getTarget().getKey().orElse("").toString(), + null, edge.getTarget().getType(), null), props); + + return graphEventEdge; + + } + + public ChampRelationship toChampRelationship() { + ChampObject sourceChampObject=null; + ChampObject targetChampObject=null; + if (this.getSource() != null) { + sourceChampObject = new ChampObject.Builder(this.getSource().getType()).key(this.getSource().getId()) + .build(); + } + if (this.getTarget() != null) { + targetChampObject = new ChampObject.Builder(this.getTarget().getType()).key(this.getTarget().getId()) + .build(); + } + + ChampRelationship.Builder builder = new ChampRelationship.Builder(sourceChampObject, targetChampObject, type); + if(this.getId()!=null && !this.getId().isEmpty()){ + builder.key(this.getId()); + } + + + if (this.getProperties() != null) { + java.lang.reflect.Type mapType = new TypeToken>() {}.getType(); + Map propertiesMap = gson.fromJson(this.getProperties(), mapType); + for (String key : propertiesMap.keySet()) { + builder.property(key, propertiesMap.get(key)); + } + } + return builder.build(); + + } +} diff --git a/champ-service/src/main/java/org/onap/champ/event/GraphEventVertex.java b/champ-service/src/main/java/org/onap/champ/event/GraphEventVertex.java new file mode 100644 index 0000000..553ba46 --- /dev/null +++ b/champ-service/src/main/java/org/onap/champ/event/GraphEventVertex.java @@ -0,0 +1,187 @@ +/** + * ============LICENSE_START======================================================= + * Gizmo + * ================================================================================ + * Copyright © 2017 AT&T Intellectual Property. + * Copyright © 2017 Amdocs + * All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR 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. + */ +package org.onap.champ.event; + +import java.util.Map; + +import javax.ws.rs.core.Response.Status; + +import org.onap.aai.champcore.model.ChampObject; +import org.onap.champ.exception.ChampServiceException; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.annotations.SerializedName; +import com.google.gson.reflect.TypeToken; + +/** + * This class provides a generic representation of a Vertex as provided by the + * graph data store. + */ +public class GraphEventVertex { + + /** + * The unique identifier used to identify this vertex in the graph data + * store. + */ + @SerializedName("key") + private String id; + + @SerializedName("schema-version") + private String modelVersion; + + /** + * Type label assigned to this vertex. + */ + private String type; + + /** + * Map of all of the properties assigned to this vertex. + */ + private JsonElement properties; + + /** + * Marshaller/unmarshaller for converting to/from JSON. + */ + private static final Gson gson = new GsonBuilder().disableHtmlEscaping().create(); + + public GraphEventVertex(String id, String modelVersion, String type, JsonElement properties) { + this.id = id; + this.modelVersion = modelVersion; + this.type = type; + this.properties = properties; + } + + public GraphEventVertex() { + + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + + public JsonElement getProperties() { + return properties; + } + + public void setProperties(JsonElement properties) { + this.properties = properties; + } + + public String getModelVersion() { + return modelVersion; + } + + public void setModelVersion(String modelVersion) { + this.modelVersion = modelVersion; + } + + /** + * Unmarshalls this Vertex object into a JSON string. + * + * @return - A JSON format string representation of this Vertex. + */ + public String toJson() { + return gson.toJson(this); + } + + /** + * Marshalls the provided JSON string into a Vertex object. + * + * @param json - The JSON string to produce the Vertex from. + * @return - A Vertex object. + * @throws SpikeException + */ + public static GraphEventVertex fromJson(String json) throws ChampServiceException { + + try { + + // Make sure that we were actually provided a non-empty string + // before we + // go any further. + if (json == null || json.isEmpty()) { + throw new ChampServiceException("Empty or null JSON string.", Status.BAD_REQUEST); + } + + // Marshall the string into a Vertex object. + return gson.fromJson(json, GraphEventVertex.class); + + } catch (Exception ex) { + throw new ChampServiceException("Unable to parse JSON string: ", Status.BAD_REQUEST); + } + } + + @Override + public String toString() { + + return toJson(); + } + + + public static GraphEventVertex fromChampObject(ChampObject champObject, String modelVersion) { + + java.lang.reflect.Type mapType = new TypeToken>() {}.getType(); + JsonObject props = gson.toJsonTree(champObject.getProperties(), mapType).getAsJsonObject(); + GraphEventVertex graphEventVertex = new GraphEventVertex(champObject.getKey().orElse("").toString(), + modelVersion, champObject.getType(), props); + return graphEventVertex; + + } + + + public ChampObject toChampObject() { + ChampObject.Builder builder = new ChampObject.Builder(this.getType()); + if(this.getId()!=null && !this.getId().isEmpty()){ + builder.key(this.getId()); + } + + if (this.getProperties() != null) { + java.lang.reflect.Type mapType = new TypeToken>() {}.getType(); + Map propertiesMap = gson.fromJson(this.getProperties(), mapType); + for (String key : propertiesMap.keySet()) { + builder.property(key, propertiesMap.get(key)); + } + } + + return builder.build(); + + } + +} diff --git a/champ-service/src/main/java/org/onap/champ/exception/ChampServiceException.java b/champ-service/src/main/java/org/onap/champ/exception/ChampServiceException.java new file mode 100644 index 0000000..6e5e8c2 --- /dev/null +++ b/champ-service/src/main/java/org/onap/champ/exception/ChampServiceException.java @@ -0,0 +1,62 @@ +/** + * ============LICENSE_START======================================================= + * Gizmo + * ================================================================================ + * Copyright © 2017 AT&T Intellectual Property. + * Copyright © 2017 Amdocs + * All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR 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 is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.champ.exception; + +import javax.ws.rs.core.Response.Status; + +public class ChampServiceException extends Exception { + + private static final long serialVersionUID = 8162385108397238865L; + + private Status httpStatus; + + public ChampServiceException() { + } + + public ChampServiceException(String message, Status httpStatus) { + super(message); + this.setHttpStatus(httpStatus); + } + + public ChampServiceException(Throwable cause) { + super(cause); + } + + public ChampServiceException(String message, Throwable cause) { + super(message, cause); + } + + public ChampServiceException(String message, Throwable cause, boolean enableSuppression, + boolean writableStackTrace) { + super(message, cause, enableSuppression, writableStackTrace); + } + + public Status getHttpStatus() { + return httpStatus; + } + + public void setHttpStatus(Status httpStatus) { + this.httpStatus = httpStatus; + } +} diff --git a/champ-service/src/main/java/org/onap/champ/service/ChampDataService.java b/champ-service/src/main/java/org/onap/champ/service/ChampDataService.java new file mode 100644 index 0000000..7826fa2 --- /dev/null +++ b/champ-service/src/main/java/org/onap/champ/service/ChampDataService.java @@ -0,0 +1,355 @@ +package org.onap.champ.service; + +import org.onap.aai.champcore.ChampGraph; +import org.onap.aai.champcore.ChampTransaction; +import org.onap.aai.champcore.exceptions.ChampMarshallingException; +import org.onap.aai.champcore.exceptions.ChampObjectNotExistsException; +import org.onap.aai.champcore.exceptions.ChampRelationshipNotExistsException; +import org.onap.aai.champcore.exceptions.ChampSchemaViolationException; +import org.onap.aai.champcore.exceptions.ChampTransactionException; +import org.onap.aai.champcore.exceptions.ChampUnmarshallingException; +import org.onap.aai.champcore.model.ChampElement; +import org.onap.aai.champcore.model.ChampObject; +import org.onap.aai.champcore.model.ChampRelationship; +import org.onap.aai.champcore.model.fluent.object.ObjectBuildOrPropertiesStep; +import org.onap.aai.cl.api.Logger; +import org.onap.aai.cl.eelf.LoggerFactory; +import org.onap.champ.exception.ChampServiceException; +import org.onap.champ.service.logging.ChampMsgs; +import org.onap.champ.util.ChampProperties; +import org.onap.champ.util.ChampServiceConstants; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import javax.ws.rs.core.Response.Status; + +public class ChampDataService { + private ChampUUIDService champUUIDService; + + private ChampGraph graphImpl; + private ChampTransactionCache cache; + private static final String KEY_NAME = ChampProperties.get(ChampServiceConstants.CHAMP_KEY_NAME); + private static final String SOT_NAME = ChampProperties.get(ChampServiceConstants.CHAMP_SOT_NAME); + private static final String CREATED_TS_NAME = ChampProperties.get(ChampServiceConstants.CHAMP_CREATED_TS_NAME); + private static final String LAST_MOD_TS_NAME = ChampProperties.get(ChampServiceConstants.CHAMP_LAST_MOD_TS_NAME); + private Logger logger = LoggerFactory.getInstance().getLogger(ChampDataService.class); + + + public ChampDataService(ChampUUIDService champUUIDService, ChampGraph graphImpl, ChampTransactionCache cache) { + + this.champUUIDService = champUUIDService; + this.graphImpl = graphImpl; + this.cache = cache; + } + + public ChampObject getObject(String id, Optional transaction) throws ChampServiceException { + + Optional retrieved = Optional.empty(); + try { + retrieved = champUUIDService.getObjectbyUUID(id, transaction.orElse(null)); + } catch (ChampUnmarshallingException | ChampTransactionException e) { + throw new ChampServiceException("Error: " + e.getMessage(), Status.INTERNAL_SERVER_ERROR); + } + if (retrieved.isPresent()) { + return (ChampObject) champUUIDService.populateUUIDKey(retrieved.get()); + } else { + return null; + } + } + + public ChampObject storeObject(ChampObject object, Optional transaction) + throws ChampMarshallingException, ChampSchemaViolationException, ChampObjectNotExistsException, + ChampTransactionException, ChampServiceException { + + if (object.getProperty(KEY_NAME).isPresent() || object.getKey().isPresent()) { + throw new ChampServiceException(KEY_NAME + " can't be updated", Status.BAD_REQUEST); + } + + champUUIDService.populateUUIDProperty(object, java.util.UUID.randomUUID().toString()); + addTimestamps(object, null); + ChampObject created = graphImpl.storeObject(object, transaction); + return (ChampObject) champUUIDService.populateUUIDKey(created); + } + + public ChampObject replaceObject(ChampObject object, String objectId, Optional transaction) + throws ChampServiceException, ChampUnmarshallingException, ChampTransactionException, ChampMarshallingException, + ChampSchemaViolationException, ChampObjectNotExistsException { + if (object.getKey().isPresent() && (!object.getKeyValue().equals(objectId))) { + throw new ChampServiceException("Object Id in the URI doesn't match the body.", Status.BAD_REQUEST); + } + + if (object.getProperty(KEY_NAME).isPresent() && !object.getProperty(KEY_NAME).get().toString().equals(objectId)) { + throw new ChampServiceException(KEY_NAME + " can't be updated", Status.BAD_REQUEST); + } + + Optional retrieved = champUUIDService.getObjectbyUUID(objectId, transaction.orElse(null)); + if (!retrieved.isPresent()) { + throw new ChampServiceException(objectId + " not found", Status.NOT_FOUND); + } + ObjectBuildOrPropertiesStep payloadBuilder = ChampObject.create().from(object).withKey(retrieved.get().getKey().get()) + .withProperty(KEY_NAME, objectId); + if (retrieved.get().getProperty(SOT_NAME).isPresent()){ + payloadBuilder = payloadBuilder.withProperty(SOT_NAME, retrieved.get().getProperty(SOT_NAME).get()); + } + + if (object.getProperty(CREATED_TS_NAME).isPresent() && retrieved.get().getProperty(CREATED_TS_NAME).isPresent()) { + // the timestamps in object are parsed as strings regardless of how the input json is. Convert retrieved to string for easy comparison + if (!retrieved.get().getProperty(CREATED_TS_NAME).get().toString().equals(object.getProperty(CREATED_TS_NAME).get())) { + throw new ChampServiceException(CREATED_TS_NAME + " can't be updated", Status.BAD_REQUEST); + } + } + + if (object.getProperty(LAST_MOD_TS_NAME).isPresent() && retrieved.get().getProperty(LAST_MOD_TS_NAME).isPresent()) { + if (!retrieved.get().getProperty(LAST_MOD_TS_NAME).get().toString().equals(object.getProperty(LAST_MOD_TS_NAME).get())) { + throw new ChampServiceException(LAST_MOD_TS_NAME + " can't be updated", Status.BAD_REQUEST); + } + } + + ChampObject payload = payloadBuilder.build(); + addTimestamps(payload, (Long)retrieved.get().getProperty(CREATED_TS_NAME).orElse(null)); + ChampObject updated = graphImpl.replaceObject(payload, transaction); + return (ChampObject) champUUIDService.populateUUIDKey(updated); + } + + public void deleteObject(String objectId, Optional transaction) throws ChampServiceException, + ChampObjectNotExistsException, ChampTransactionException, ChampUnmarshallingException { + Optional retrieved = champUUIDService.getObjectbyUUID(objectId, transaction.orElse(null)); + if (!retrieved.isPresent()) { + throw new ChampServiceException(objectId + " not found", Status.NOT_FOUND); + } + Stream relationships = graphImpl.retrieveRelationships(retrieved.get(), transaction); + + if (relationships.count() > 0) { + throw new ChampServiceException("Attempt to delete vertex with id " + objectId + " which has incident edges.", + Status.BAD_REQUEST); + } + graphImpl.deleteObject(retrieved.get().getKey().get(), transaction); + + } + + public ChampRelationship storeRelationship(ChampRelationship r, Optional transaction) + throws ChampMarshallingException, ChampObjectNotExistsException, ChampSchemaViolationException, + ChampRelationshipNotExistsException, ChampUnmarshallingException, ChampTransactionException, + ChampServiceException { + + if (r.getSource() == null || !r.getSource().getKey().isPresent() || r.getTarget() == null + || !r.getTarget().getKey().isPresent()) { + logger.error(ChampMsgs.CHAMP_DATA_SERVICE_ERROR, "Source/Target Object key must be provided"); + throw new ChampServiceException("Source/Target Object key must be provided", Status.BAD_REQUEST); + } + + if (r.getProperty(KEY_NAME).isPresent() || r.getKey().isPresent()) { + logger.error(ChampMsgs.CHAMP_DATA_SERVICE_ERROR, "key or " + KEY_NAME + " not allowed while creating new Objects"); + throw new ChampServiceException("key or " + KEY_NAME + " not allowed while creating new Objects", Status.BAD_REQUEST); + + } + + Optional source = champUUIDService.getObjectbyUUID(r.getSource().getKey().get().toString(), + transaction.orElse(null)); + Optional target = champUUIDService.getObjectbyUUID(r.getTarget().getKey().get().toString(), + transaction.orElse(null)); + + if (!source.isPresent() || !target.isPresent()) { + logger.error(ChampMsgs.CHAMP_DATA_SERVICE_ERROR, "Source/Target object not found"); + throw new ChampServiceException("Source/Target object not found", Status.BAD_REQUEST); + } + + champUUIDService.populateUUIDProperty(r, java.util.UUID.randomUUID().toString()); + + ChampRelationship payload = new ChampRelationship.Builder(source.get(), target.get(), r.getType()) + .properties(r.getProperties()).build(); + addTimestamps(payload, null); + ChampRelationship created = graphImpl.storeRelationship(payload, transaction); + return (ChampRelationship) champUUIDService.populateUUIDKey(created); + } + + public ChampRelationship updateRelationship(ChampRelationship r, String rId, Optional transaction) + throws ChampServiceException, ChampUnmarshallingException, ChampTransactionException, ChampMarshallingException, + ChampSchemaViolationException, ChampRelationshipNotExistsException { + if (r.getKey().isPresent() && (!r.getKeyValue().equals(rId))) { + + throw new ChampServiceException("Relationship Id in the URI \"" + rId + "\" doesn't match the URI in the body" + + " \"" + r.getKeyValue() + "\"", Status.BAD_REQUEST); + + } + + if (r.getProperty(KEY_NAME).isPresent() && !r.getProperty(KEY_NAME).get().toString().equals(rId)) { + throw new ChampServiceException(KEY_NAME + " can't be updated", Status.BAD_REQUEST); + } + + Optional retrieved = champUUIDService.getRelationshipbyUUID(rId, transaction.orElse(null)); + if (!retrieved.isPresent()) { + throw new ChampServiceException(rId + " not found", Status.NOT_FOUND); + } + // check if key is present or if it equals the key that is in the URI + if (r.getSource() == null || !r.getSource().getKey().isPresent() || r.getTarget() == null + || !r.getTarget().getKey().isPresent()) { + throw new ChampServiceException("Source/Target Object key must be provided", Status.BAD_REQUEST); + } + ChampObject source = retrieved.get().getSource(); + ChampObject target = retrieved.get().getTarget(); + + if (!source.getProperty(KEY_NAME).get().toString().equals(r.getSource().getKey().get().toString()) + || !target.getProperty(KEY_NAME).get().toString().equals(r.getTarget().getKey().get().toString())) { + throw new ChampServiceException("Source/Target cannot be updated", Status.BAD_REQUEST); + } + + if (r.getProperty(CREATED_TS_NAME).isPresent() && retrieved.get().getProperty(CREATED_TS_NAME).isPresent()) { + if (!retrieved.get().getProperty(CREATED_TS_NAME).get().toString().equals(r.getProperty(CREATED_TS_NAME).get())) { + throw new ChampServiceException(CREATED_TS_NAME + " can't be updated", Status.BAD_REQUEST); + } + } + + if (r.getProperty(LAST_MOD_TS_NAME).isPresent() && retrieved.get().getProperty(LAST_MOD_TS_NAME).isPresent()) { + if (!retrieved.get().getProperty(LAST_MOD_TS_NAME).get().toString().equals(r.getProperty(LAST_MOD_TS_NAME).get())) { + throw new ChampServiceException(LAST_MOD_TS_NAME + " can't be updated", Status.BAD_REQUEST); + } + } + + ChampRelationship payload = new ChampRelationship.Builder(source, target, r.getType()) + .key(retrieved.get().getKey().get()).properties(r.getProperties()).property(KEY_NAME, rId).build(); + addTimestamps(payload, (Long)retrieved.get().getProperty(CREATED_TS_NAME).orElse(null)); + ChampRelationship updated = graphImpl.replaceRelationship(payload, transaction); + return (ChampRelationship) champUUIDService.populateUUIDKey(updated); + } + + public void deleteRelationship(String relationshipId, Optional transaction) + throws ChampServiceException, ChampRelationshipNotExistsException, ChampTransactionException, + ChampUnmarshallingException { + Optional retrieved = champUUIDService.getRelationshipbyUUID(relationshipId, + transaction.orElse(null)); + if (!retrieved.isPresent()) { + throw new ChampServiceException(relationshipId + " not found", Status.NOT_FOUND); + } + + graphImpl.deleteRelationship(retrieved.get(), transaction); + + } + + + public List getRelationshipsByObject(String objectId, Optional transaction) + throws ChampServiceException { + try { + Optional retrievedObject = champUUIDService.getObjectbyUUID(objectId, transaction.orElse(null)); + if (!retrievedObject.isPresent()) { + throw new ChampServiceException(objectId + " not found", Status.NOT_FOUND); + } + List relations = new ArrayList(); + + Stream retrieved = graphImpl.retrieveRelationships(retrievedObject.get(), transaction); + relations = champUUIDService.populateUUIDKey(retrieved.collect(Collectors.toList())); + return relations; + } catch (ChampObjectNotExistsException e) { + throw new ChampServiceException(" obj not found", Status.NOT_FOUND); + } catch (ChampUnmarshallingException | ChampTransactionException e) { + throw new ChampServiceException("Internal Error", Status.INTERNAL_SERVER_ERROR); + } + + } + + /** + * Gets the ChampObjects that pass filter + * @param filter key/value pairs that must be present in the returned objects + * @param properties properties that will show up in the object + * @return + * @throws ChampServiceException + */ + public List queryObjects(Map filter, HashSet properties) throws ChampServiceException { + try { + + Stream retrieved = graphImpl.queryObjects(filter); + List objects = champUUIDService.populateUUIDKey(retrieved.collect(Collectors.toList())); + + if (!properties.contains("all")) { + for (ChampObject champObject : objects) { + champObject.dropProperties(properties); + } + } + + return objects; + } catch (ChampTransactionException e) { + throw new ChampServiceException("Internal Error", Status.INTERNAL_SERVER_ERROR); + } + } + + public List queryRelationships(Map filter) throws ChampServiceException { + try { + List relations = new ArrayList(); + Stream retrieved; + + retrieved = graphImpl.queryRelationships(filter); + + relations = champUUIDService.populateUUIDKey(retrieved.collect(Collectors.toList())); + return relations; + } catch (ChampTransactionException e) { + throw new ChampServiceException("Internal Error", Status.INTERNAL_SERVER_ERROR); + } + } + + public ChampRelationship getRelationship(String id, Optional transaction) + throws ChampServiceException { + + Optional retrieved = Optional.empty(); + try { + retrieved = champUUIDService.getRelationshipbyUUID(id, transaction.orElse(null)); + } catch (ChampUnmarshallingException | ChampTransactionException e) { + throw new ChampServiceException("Error: " + e.getMessage(), Status.INTERNAL_SERVER_ERROR); + } + if (retrieved.isPresent()) { + return (ChampRelationship) champUUIDService.populateUUIDKey(retrieved.get()); + } else { + return null; + } + } + + public String openTransaction() { + ChampTransaction transaction = graphImpl.openTransaction(); + String transacId = transaction.id(); + cache.put(transacId, transaction); + return transacId; + + } + + public void commitTransaction(String tId) throws ChampServiceException, ChampTransactionException { + ChampTransaction transaction = cache.get(tId); + if (transaction == null) { + throw new ChampServiceException("Transaction Not found: " + tId, Status.NOT_FOUND); + } + graphImpl.commitTransaction(transaction); + cache.invalidate(tId); + cache.invalidate(transaction.id()); + + } + + public void rollbackTransaction(String tId) throws ChampServiceException, ChampTransactionException { + ChampTransaction transaction = cache.get(tId); + if (transaction == null) { + throw new ChampServiceException("Transaction Not found: " + tId, Status.NOT_FOUND); + } + graphImpl.rollbackTransaction(transaction); + cache.invalidate(tId); + cache.invalidate(transaction.id()); + + } + + public ChampTransaction getTransaction(String id) { + return cache.get(id); + } + + private void addTimestamps(ChampElement e, Long oldCreated) { + Long timestamp = System.currentTimeMillis(); + + if (oldCreated == null) { + e.getProperties().put(CREATED_TS_NAME, timestamp); + } else { + e.getProperties().put(CREATED_TS_NAME, oldCreated); + } + + e.getProperties().put(LAST_MOD_TS_NAME, timestamp); + } +} diff --git a/champ-service/src/main/java/org/onap/champ/service/ChampThreadFactory.java b/champ-service/src/main/java/org/onap/champ/service/ChampThreadFactory.java new file mode 100644 index 0000000..25fe65e --- /dev/null +++ b/champ-service/src/main/java/org/onap/champ/service/ChampThreadFactory.java @@ -0,0 +1,47 @@ +/** + * ============LICENSE_START======================================================= + * Gizmo + * ================================================================================ + * Copyright © 2017 AT&T Intellectual Property. + * Copyright © 2017 Amdocs + * All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR 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. + */ +package org.onap.champ.service; + +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicInteger; + +/** + * Thread factory for workers. + */ +public class ChampThreadFactory implements ThreadFactory { + + private AtomicInteger threadNumber = new AtomicInteger(1); + + private String threadPrefix; + + + public ChampThreadFactory(String threadPrefix) { + this.threadPrefix = threadPrefix; + } + + public Thread newThread(Runnable runnable) { + return new Thread(runnable, threadPrefix + "-" + threadNumber.getAndIncrement()); + } +} diff --git a/champ-service/src/main/java/org/onap/champ/service/ChampTransactionCache.java b/champ-service/src/main/java/org/onap/champ/service/ChampTransactionCache.java new file mode 100644 index 0000000..bb95147 --- /dev/null +++ b/champ-service/src/main/java/org/onap/champ/service/ChampTransactionCache.java @@ -0,0 +1,77 @@ + +package org.onap.champ.service; + +import java.util.concurrent.TimeUnit; + +import org.onap.aai.champcore.ChampGraph; +import org.onap.aai.champcore.ChampTransaction; +import org.onap.aai.champcore.exceptions.ChampTransactionException; +import org.onap.champ.service.logging.ChampMsgs; +import org.onap.aai.cl.api.Logger; +import org.onap.aai.cl.eelf.LoggerFactory; + +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.RemovalCause; +import com.google.common.cache.RemovalListener; +import com.google.common.cache.RemovalNotification; + +/** + * Self expiring Cache to hold request transactionIds . Events are expired + * automatically after configured interval + */ +public class ChampTransactionCache { + private static Logger logger = LoggerFactory.getInstance().getLogger(ChampTransactionCache + .class.getName()); + + + private ChampGraph graphImpl; + private Cache cache; + + + + public ChampTransactionCache(long txTimeOutInSec,ChampGraph graphImpl) { + CacheBuilder builder = CacheBuilder.newBuilder().expireAfterWrite(txTimeOutInSec, TimeUnit.SECONDS) + .removalListener(new RemovalListener() { + + public void onRemoval(RemovalNotification notification) { + if(notification.getCause()==RemovalCause.EXPIRED){ + logger.info(ChampMsgs.CHAMP_TX_CACHE, "Following transaction: "+notification.getKey()+" is being evicted from cache due to timeout of " + txTimeOutInSec+" seconds"); + try { + graphImpl.rollbackTransaction((ChampTransaction) notification.getValue()); + logger.info(ChampMsgs.CHAMP_TX_CACHE, "Transaction rolledback successfully :" + notification.getKey()); + } catch (ChampTransactionException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + } + }); + cache = builder.build(); + + this.graphImpl = graphImpl; + + } + + public void put(String txId, ChampTransaction tx) { + cache.put(txId, tx); + + } + + public ChampTransaction get(String txId) { + if (txId==null) + return null; + if(cache.getIfPresent(txId)==null){ + //cleanup cache so that removalListener is called + cache.cleanUp(); + } + return cache.getIfPresent(txId); + } + + public void invalidate(String txId) { + cache.invalidate(txId); + } + + + +} diff --git a/champ-service/src/main/java/org/onap/champ/service/ChampUUIDService.java b/champ-service/src/main/java/org/onap/champ/service/ChampUUIDService.java new file mode 100644 index 0000000..39c775b --- /dev/null +++ b/champ-service/src/main/java/org/onap/champ/service/ChampUUIDService.java @@ -0,0 +1,115 @@ +package org.onap.champ.service; + +import org.onap.aai.champcore.ChampGraph; +import org.onap.aai.champcore.ChampTransaction; +import org.onap.aai.champcore.exceptions.ChampTransactionException; +import org.onap.aai.champcore.exceptions.ChampUnmarshallingException; +import org.onap.aai.champcore.model.ChampElement; +import org.onap.aai.champcore.model.ChampObject; +import org.onap.aai.champcore.model.ChampRelationship; +import org.onap.champ.exception.ChampServiceException; +import org.onap.champ.util.ChampProperties; +import org.onap.champ.util.ChampServiceConstants; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.stream.Stream; + +public class ChampUUIDService { + private ChampGraph graphImpl; + private static final String KEY_NAME = ChampProperties.get(ChampServiceConstants.CHAMP_KEY_NAME); + + + public ChampUUIDService(ChampGraph graphImpl) { + this.graphImpl = graphImpl; + } + + public List populateUUIDKey(List elements) { + { + List response = new ArrayList(); + for (ChampElement e : elements) { + ChampElement item = populateUUIDKey(e); + if (item != null) { + response.add(item); + } + } + return response; + } + + } + + public ChampElement populateUUIDKey(ChampElement e) { + { + ChampElement response = null; + + if (e.isObject()) { + if (e.asObject().getProperty(KEY_NAME).isPresent()) { + response = (ChampObject.create().from(e.asObject()) + .withKey(e.asObject().getProperty(KEY_NAME).get().toString()).build()); + } + } else { + if (e.asRelationship().getProperty(KEY_NAME).isPresent() + && e.asRelationship().getSource().getProperty(KEY_NAME).isPresent() + && e.asRelationship().getTarget().getProperty(KEY_NAME).isPresent()) { + ChampObject source = ChampObject.create().from(e.asRelationship().getSource()) + .withKey(e.asRelationship().getSource().getProperty(KEY_NAME).get().toString()).build(); + ChampObject target = ChampObject.create().from(e.asRelationship().getTarget()) + .withKey(e.asRelationship().getTarget().getProperty(KEY_NAME).get().toString()).build(); + ChampRelationship rel = new ChampRelationship.Builder(source, target, e.asRelationship().getType()) + .key(e.asRelationship().getProperty(KEY_NAME).get().toString()) + .properties(e.asRelationship().getProperties()).build(); + response = rel; + } + + } + + return response; + } + + } + + public void populateUUIDProperty(ChampElement e, String uuid) { + e.getProperties().put(KEY_NAME, uuid); + } + + + public Optional getObjectbyUUID(String uuid, ChampTransaction transaction) + throws ChampUnmarshallingException, ChampTransactionException, ChampServiceException { + Optional response = Optional.empty(); + + Stream s; + Map filter = new HashMap<>(); + filter.put(KEY_NAME, uuid); + + s = graphImpl.queryObjects(filter, Optional.ofNullable(transaction)); + Object[] objs = s.toArray(); + if (objs.length == 0) { + return response; + } + response = graphImpl.retrieveObject(((ChampObject) objs[0]).getKey().get(), Optional.ofNullable(transaction)); + return response; + } + + public Optional getRelationshipbyUUID(String uuid, ChampTransaction transaction) + throws ChampUnmarshallingException, ChampTransactionException, ChampServiceException { + Optional response = Optional.empty(); + + + Stream s; + Map filter = new HashMap<>(); + filter.put(KEY_NAME, uuid); + + s = graphImpl.queryRelationships(filter, Optional.ofNullable(transaction)); + Object[] objs = s.toArray(); + if (objs.length == 0) { + return response; + } + response = graphImpl.retrieveRelationship(((ChampRelationship) objs[0]).getKey().get(), + Optional.ofNullable(transaction)); + return response; + } + +} diff --git a/champ-service/src/main/java/org/onap/champ/service/EchoService.java b/champ-service/src/main/java/org/onap/champ/service/EchoService.java new file mode 100644 index 0000000..c8236b1 --- /dev/null +++ b/champ-service/src/main/java/org/onap/champ/service/EchoService.java @@ -0,0 +1,54 @@ +/** + * ============LICENSE_START========================================== + * org.onap.aai + * =================================================================== + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 Amdocs + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END============================================ + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.champ.service; + +import org.onap.aai.cl.api.Logger; +import org.onap.aai.cl.eelf.LoggerFactory; + +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.HttpHeaders; +import javax.ws.rs.core.UriInfo; + + +public class EchoService { + + private static Logger logger = LoggerFactory.getInstance() + .getLogger(EchoService.class.getName()); + private static Logger auditLogger = LoggerFactory.getInstance() + .getAuditLogger(EchoService.class.getName()); + + @GET + @Path("echo/{input}") + @Produces("text/plain") + public String ping(@PathParam("input") String input, + @Context HttpHeaders headers, + @Context UriInfo info, + @Context HttpServletRequest req) { + + return "Hello, " + input + "."; + } +} \ No newline at end of file diff --git a/champ-service/src/main/java/org/onap/champ/service/logging/ChampMsgs.java b/champ-service/src/main/java/org/onap/champ/service/logging/ChampMsgs.java new file mode 100644 index 0000000..2ddbff4 --- /dev/null +++ b/champ-service/src/main/java/org/onap/champ/service/logging/ChampMsgs.java @@ -0,0 +1,130 @@ +/** + * ============LICENSE_START========================================== + * org.onap.aai + * =================================================================== + * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * Copyright © 2017 Amdocs + * =================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END============================================ + * ECOMP is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.champ.service.logging; + +import com.att.eelf.i18n.EELFResourceManager; +import org.onap.aai.cl.eelf.LogMessageEnum; + +public enum ChampMsgs implements LogMessageEnum { + + /** + * Received request {0} {1} from {2}. Sending response: {3} + * + *

+ * Arguments: {0} = operation {1} = target URL {2} = source {3} = response + * code + */ + PROCESS_REST_REQUEST, + /** + * Processed event {0}. Result: {1}. + * + * Arguments: {0} = event {1} = result + */ + PROCESS_EVENT, + + /** + * Query: {0} + * Arguments: {0} = query + */ + QUERY, + + /** + * Arguments: {0} = transactionID, {1} = request + */ + INCOMING_REQUEST, + + /** + * Arguments: {0} = HTTP request type, {1} = time to process in milliseconds + */ + PROCESSED_REQUEST, + + /** + * Arguments: {0} = transaction ID + */ + TRANSACTION_NOT_FOUND, + + /** + * Arguments: {0} = request, {1} = Error + */ + BAD_REQUEST, + + /** + * Arguments: {0} = Info + */ + CHAMP_TX_CACHE, + + /** + * Any info log related to CHAMP_ASYNC_REQUEST_PROCESSOR_INFO + * + *

Arguments: + * {0} - Info. + */ + CHAMP_ASYNC_REQUEST_PROCESSOR_INFO, + CHAMP_ASYNC_REQUEST_PROCESSOR_WARN, + + /** + * Any error log related to CHAMP_ASYNC_REQUEST_PROCESSOR_ERROR + * + *

Arguments: + * {0} - Error. + */ + CHAMP_ASYNC_REQUEST_PROCESSOR_ERROR, + + /** + * Any info log related to CHAMP_DATA_SERVICE_INFO + * + *

Arguments: + * {0} - Info. + */ + CHAMP_DATA_SERVICE_INFO, + + /** + * Any error log related to CHAMP_DATA_SERVICE_INFO + * + *

Arguments: + * {0} - Error. + */ + CHAMP_DATA_SERVICE_ERROR, + + + /** + * Any info log related to CHAMP_ASYNC_RESPONSE_PUBLISHER_INFO + * + *

Arguments: + * {0} - Info. + */ + CHAMP_ASYNC_RESPONSE_PUBLISHER_INFO, + + /** + * Any error log related to CHAMP_ASYNC_RESPONSE_PUBLISHER_ERROR + * + *

Arguments: + * {0} - Error. + */ + CHAMP_ASYNC_RESPONSE_PUBLISHER_ERROR; + /** + * Static initializer to ensure the resource bundles for this class are loaded... + */ + static { + EELFResourceManager.loadMessageBundle("logging/ChampMsgs"); + } +} diff --git a/champ-service/src/main/java/org/onap/champ/service/logging/LoggingUtil.java b/champ-service/src/main/java/org/onap/champ/service/logging/LoggingUtil.java new file mode 100644 index 0000000..b7f0e77 --- /dev/null +++ b/champ-service/src/main/java/org/onap/champ/service/logging/LoggingUtil.java @@ -0,0 +1,92 @@ +/** + * ============LICENSE_START======================================================= + * Gizmo + * ================================================================================ + * Copyright © 2017 AT&T Intellectual Property. + * Copyright © 2017 Amdocs + * All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR 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 is a trademark and service mark of AT&T Intellectual Property. + */ +package org.onap.champ.service.logging; + +import org.onap.aai.cl.api.LogFields; +import org.onap.aai.cl.api.LogLine; +import org.onap.aai.cl.api.Logger; +import org.onap.aai.cl.mdc.MdcContext; + +import org.slf4j.MDC; + +import java.io.PrintWriter; +import java.io.StringWriter; + +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.core.HttpHeaders; +import javax.ws.rs.core.Response; + +public class LoggingUtil { + /** + * Initializes mdc context. + */ + public static void initMdcContext(HttpServletRequest httpReq, HttpHeaders headers) { + String fromIp = httpReq.getRemoteAddr(); + String fromAppId = ""; + String transId = null; + + if (headers.getRequestHeaders().getFirst("X-FromAppId") != null) { + fromAppId = headers.getRequestHeaders().getFirst("X-FromAppId"); + } + + if ((headers.getRequestHeaders().getFirst("X-TransactionId") == null) + || headers.getRequestHeaders().getFirst("X-TransactionId").isEmpty()) { + transId = java.util.UUID.randomUUID().toString(); + } else { + transId = headers.getRequestHeaders().getFirst("X-TransactionId"); + } + + MdcContext.initialize(transId, "ChampService", "", fromAppId, fromIp); + } + + /** + * Logs the rest request. + */ + public static void logRestRequest(Logger logger, Logger auditLogger, HttpServletRequest req, Response response) { + String respStatusString = ""; + if (Response.Status.fromStatusCode(response.getStatus()) != null) { + respStatusString = Response.Status.fromStatusCode(response.getStatus()).toString(); + } + + // Generate error log + logger.info(ChampMsgs.PROCESS_REST_REQUEST, req.getMethod(), req.getRequestURL().toString(), + req.getRemoteHost(), Integer.toString(response.getStatus())); + + // Generate audit log. + auditLogger.info(ChampMsgs.PROCESS_REST_REQUEST, + new LogFields().setField(LogLine.DefinedFields.RESPONSE_CODE, response.getStatus()) + .setField(LogLine.DefinedFields.RESPONSE_DESCRIPTION, respStatusString), + (req != null) ? req.getMethod() : "Unknown", (req != null) ? req.getRequestURL().toString() : "Unknown", + (req != null) ? req.getRemoteHost() : "Unknown", Integer.toString(response.getStatus()) + " payload: " + + (response.getEntity() == null ? "" : response.getEntity().toString())); + MDC.clear(); + } + + public static void logInternalError(Logger logger, Exception ex) { + StringWriter writer = new StringWriter(); + PrintWriter printWriter = new PrintWriter(writer); + ex.printStackTrace(printWriter); + logger.error(ChampMsgs.CHAMP_DATA_SERVICE_ERROR, "Internal error: " + ex.getMessage() + "\n" + writer.toString()); + } +} diff --git a/champ-service/src/main/java/org/onap/champ/util/ChampProperties.java b/champ-service/src/main/java/org/onap/champ/util/ChampProperties.java new file mode 100644 index 0000000..178da97 --- /dev/null +++ b/champ-service/src/main/java/org/onap/champ/util/ChampProperties.java @@ -0,0 +1,53 @@ +package org.onap.champ.util; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.Properties; + +public class ChampProperties { + + private static Properties properties; + + static { + properties = new Properties(); + File file = new File(ChampServiceConstants.CHAMP_CONFIG_FILE); + try { + properties.load(new FileInputStream(file)); + } catch (IOException e) { + e.printStackTrace(); + Runtime.getRuntime().halt(1); + } + } + + public static String get(String key) { + return properties.getProperty(key); + } + + public static String get(String key, String defaultValue) { + return properties.getProperty(key, defaultValue); + } + + public static void put(String key, String value) { + properties.setProperty(key, value); + FileOutputStream fileOut = null; + try { + fileOut = new FileOutputStream(new File(ChampServiceConstants.CHAMP_CONFIG_FILE)); + properties.store(fileOut, "Added property: " + key); + } catch (Exception e) { + e.printStackTrace(); + } finally { + + try { + fileOut.close(); + } catch (IOException ex) { + ex.printStackTrace(); + } + } + + } + + +} diff --git a/champ-service/src/main/java/org/onap/champ/util/ChampServiceConstants.java b/champ-service/src/main/java/org/onap/champ/util/ChampServiceConstants.java new file mode 100644 index 0000000..94a9972 --- /dev/null +++ b/champ-service/src/main/java/org/onap/champ/util/ChampServiceConstants.java @@ -0,0 +1,14 @@ +package org.onap.champ.util; + +public class ChampServiceConstants { + public static final String CHAMP_FILESEP = (System.getProperty("file.separator") == null) ? "/" + : System.getProperty("file.separator"); + + public static final String CHAMP_SPECIFIC_CONFIG = System.getProperty("CONFIG_HOME") + CHAMP_FILESEP; + public static final String CHAMP_CONFIG_FILE = CHAMP_SPECIFIC_CONFIG + "champ-api.properties"; + public static final String CHAMP_KEY_NAME = "keyName"; + public static final String CHAMP_SOT_NAME = "sourceOfTruthName"; + public static final String CHAMP_CREATED_TS_NAME = "createdTsName"; + public static final String CHAMP_LAST_MOD_TS_NAME = "lastModTsName"; + public static final String CHAMP_COLLECTION_PROPERTIES_KEY = "collectionPropertiesKey"; +} \ No newline at end of file diff --git a/champ-service/src/main/resources/META-INF/services/javax.ws.rs.client.ClientBuilder b/champ-service/src/main/resources/META-INF/services/javax.ws.rs.client.ClientBuilder new file mode 100644 index 0000000..48b9fa5 --- /dev/null +++ b/champ-service/src/main/resources/META-INF/services/javax.ws.rs.client.ClientBuilder @@ -0,0 +1 @@ +org.glassfish.jersey.client.JerseyClientBuilder \ No newline at end of file diff --git a/champ-service/src/main/resources/logging/ChampMsgs.properties b/champ-service/src/main/resources/logging/ChampMsgs.properties new file mode 100644 index 0000000..776b178 --- /dev/null +++ b/champ-service/src/main/resources/logging/ChampMsgs.properties @@ -0,0 +1,78 @@ +#Resource key=Error Code|Message text|Resolution text |Description text +####### +#Newlines can be utilized to add some clarity ensuring continuing line +#has atleast one leading space +#ResourceKey=\ +# ERR0000E\ +# Sample error msg txt\ +# Sample resolution msg\ +# Sample description txt +# +###### +#Error code classification category +#000 Info/Debug +#100 Permission errors +#200 Availability errors/Timeouts +#300 Data errors +#400 Schema Interface type/validation errors +#500 Business process errors +#900 Unknown errors +# +######################################################################## +PROCESS_REST_REQUEST=\ + CS0005I|\ + Received request {0} {1} from {2}. Sending response: {3}|\ + None. Received the specified REST request from the source specified.|\ + Received the specified REST request from the source specified, and the CHAMP service sent the specified response. + +PROCESS_EVENT=\ + CS0001I|\ + Processed event {0} Result: {1} + +QUERY=\ + CS0002I|\ + Query Recieved: {0} + +INCOMING_REQUEST=\ + CS0003I|\ + Incoming Request with Transaction ID {0} and request {1} + +PROCESSED_REQUEST=\ + CS0004I|\ + Processed Champ {0} request in {1} ms + +TRANSACTION_NOT_FOUND=\ + CS0001E|\ + Transaction with ID {0} was not found. + +BAD_REQUEST=\ + CS0002E|\ + Bad Request {0}. Error is {1} + +CHAMP_TX_CACHE=\ + CS0006I|\ + ChampTransactionCache: {0} +CHAMP_DATA_SERVICE_ERROR=\ + CRD0510E|\ + ChampDataService Error: {0} +CHAMP_DATA_CACHE_INFO=\ + CRD0511I|\ + ChampDataService: {0} +CHAMP_ASYNC_REQUEST_PROCESSOR_ERROR=\ + CRD0512E|\ + ChampAsyncRequestProcessor Error: {0} +CHAMP_ASYNC_REQUEST_PROCESSOR_WARN=\ + CRD0514E|\ + ChampAsyncRequestProcessor Warning: {0} +CHAMP_ASYNC_REQUEST_PROCESSOR_INFO=\ + CRD0512I|\ + ChampAsyncRequestProcessor: {0} +CHAMP_ASYNC_RESPONSE_PUBLISHER_ERROR=\ + CRD0513E|\ + ChampAsyncRequestProcessor Error: {0} +CHAMP_ASYNC_RESPONSE_PUBLISHER_INFO=\ + CRD0513I|\ + ChampAsyncRequestProcessor: {0} + + + diff --git a/champ-service/src/main/runtime/context/__module.ajsc.namespace.name__#__module.ajsc.namespace.version__.context b/champ-service/src/main/runtime/context/__module.ajsc.namespace.name__#__module.ajsc.namespace.version__.context new file mode 100644 index 0000000..8514196 --- /dev/null +++ b/champ-service/src/main/runtime/context/__module.ajsc.namespace.name__#__module.ajsc.namespace.version__.context @@ -0,0 +1 @@ +{"context":{"contextClass":"ajsc.Context","contextId":"__module_ajsc_namespace_name__:__module_ajsc_namespace_version__","contextName":"__module_ajsc_namespace_name__","contextVersion":"__module_ajsc_namespace_version__","description":"__module_ajsc_namespace_name__ Context"}} \ No newline at end of file diff --git a/champ-service/src/main/runtime/context/default#0.context b/champ-service/src/main/runtime/context/default#0.context new file mode 100644 index 0000000..d1b5ab4 --- /dev/null +++ b/champ-service/src/main/runtime/context/default#0.context @@ -0,0 +1 @@ +{"context":{"contextClass":"ajsc.Context","contextId":"default:0","contextName":"default","contextVersion":"0","description":"Default Context"}} \ No newline at end of file diff --git a/champ-service/src/main/runtime/deploymentPackage/__module.ajsc.namespace.name__#__module.ajsc.namespace.version__.json b/champ-service/src/main/runtime/deploymentPackage/__module.ajsc.namespace.name__#__module.ajsc.namespace.version__.json new file mode 100644 index 0000000..d0954cf --- /dev/null +++ b/champ-service/src/main/runtime/deploymentPackage/__module.ajsc.namespace.name__#__module.ajsc.namespace.version__.json @@ -0,0 +1 @@ +{"deploymentPackage":{"Class":"ajsc.DeploymentPackage","Id":"__module.ajsc.namespace.name__:__module_ajsc_namespace_version__","namespace":"__module_ajsc_namespace_name__","namespaceVersion":"__module_ajsc_namespace_version__","description":"__module_ajsc_namespace_name__ __module_ajsc_namespace_version__ - default description","userId":"ajsc"}} \ No newline at end of file diff --git a/champ-service/src/main/runtime/shiroRole/ajscadmin.json b/champ-service/src/main/runtime/shiroRole/ajscadmin.json new file mode 100644 index 0000000..f5e981e --- /dev/null +++ b/champ-service/src/main/runtime/shiroRole/ajscadmin.json @@ -0,0 +1 @@ +{"shiroRoleClass":"ajsc.auth.ShiroRole","shiroRoleId":"ajscadmin","name":"ajscadmin","permissions":"[ajscadmin:*, ajsc:*]"} \ No newline at end of file diff --git a/champ-service/src/main/runtime/shiroRole/contextadmin#__module.ajsc.namespace.name__.json b/champ-service/src/main/runtime/shiroRole/contextadmin#__module.ajsc.namespace.name__.json new file mode 100644 index 0000000..2dae9f5 --- /dev/null +++ b/champ-service/src/main/runtime/shiroRole/contextadmin#__module.ajsc.namespace.name__.json @@ -0,0 +1 @@ +{"shiroRoleClass":"ajsc.auth.ShiroRole","shiroRoleId":"contextadmin:__module_ajsc_namespace_name__","name":"contextadmin:__module_ajsc_namespace_name__","permissions":"[]"} \ No newline at end of file diff --git a/champ-service/src/main/runtime/shiroRole/contextadmin#default.json b/champ-service/src/main/runtime/shiroRole/contextadmin#default.json new file mode 100644 index 0000000..5de814e --- /dev/null +++ b/champ-service/src/main/runtime/shiroRole/contextadmin#default.json @@ -0,0 +1 @@ +{"shiroRoleClass":"ajsc.auth.ShiroRole","shiroRoleId":"contextadmin:default","name":"contextadmin:default","permissions":"[]"} \ No newline at end of file diff --git a/champ-service/src/main/runtime/shiroUser/ajsc.json b/champ-service/src/main/runtime/shiroUser/ajsc.json new file mode 100644 index 0000000..f4c7855 --- /dev/null +++ b/champ-service/src/main/runtime/shiroUser/ajsc.json @@ -0,0 +1 @@ +{"shiroUserClass":"ajsc.auth.ShiroUser","shiroUserId":"ajsc","passwordHash":"9471697417008c880720ba54c6038791ad7e98f3b88136fe34f4d31a462dd27a","permissions":"[*:*]","username":"ajsc"} \ No newline at end of file diff --git a/champ-service/src/main/runtime/shiroUserRole/ajsc#ajscadmin.json b/champ-service/src/main/runtime/shiroUserRole/ajsc#ajscadmin.json new file mode 100644 index 0000000..cb8d483 --- /dev/null +++ b/champ-service/src/main/runtime/shiroUserRole/ajsc#ajscadmin.json @@ -0,0 +1 @@ +{"shiroUserRoleClass":"ajsc.auth.ShiroUserRole","shiroUserRoleId":"ajsc:ajscadmin","roleId":"ajscadmin","userId":"ajsc"} \ No newline at end of file diff --git a/champ-service/src/main/runtime/shiroUserRole/ajsc#contextadmin#__module.ajsc.namespace.name__.json b/champ-service/src/main/runtime/shiroUserRole/ajsc#contextadmin#__module.ajsc.namespace.name__.json new file mode 100644 index 0000000..95d2361 --- /dev/null +++ b/champ-service/src/main/runtime/shiroUserRole/ajsc#contextadmin#__module.ajsc.namespace.name__.json @@ -0,0 +1 @@ +{"shiroUserRoleClass":"ajsc.auth.ShiroUserRole","shiroUserRoleId":"ajsc:contextadmin:__module_ajsc_namespace_name__","roleId":"contextadmin:__module_ajsc_namespace_name__","userId":"ajsc"} \ No newline at end of file diff --git a/champ-service/src/main/runtime/shiroUserRole/ajsc#contextadmin#default.json b/champ-service/src/main/runtime/shiroUserRole/ajsc#contextadmin#default.json new file mode 100644 index 0000000..2bd5063 --- /dev/null +++ b/champ-service/src/main/runtime/shiroUserRole/ajsc#contextadmin#default.json @@ -0,0 +1 @@ +{"shiroUserRoleClass":"ajsc.auth.ShiroUserRole","shiroUserRoleId":"ajsc:contextadmin:default","roleId":"contextadmin:default","userId":"ajsc"} \ No newline at end of file diff --git a/pom.xml b/pom.xml index 7a1c572..86affb3 100755 --- a/pom.xml +++ b/pom.xml @@ -1,398 +1,18 @@ - - 4.0.0 - - org.onap.oparent - oparent - 1.0.0-SNAPSHOT - + + 4.0.0 - org.onap.aai - champ - 1.1.0-SNAPSHOT - aai-champ - - 3.0.1-incubating - /content/sites/site/org/onap/aai/${project.artifactId}/${project.version} - java - jacoco - ${project.build.directory}/surefire-reports - ${project.build.directory}/code-coverage/jacoco-ut.exec - false - ${project.version} - - - - ecomp-site - dav:${onap.nexus.url}${sitePath} - - - - - junit - junit - 4.12 - test - - - ch.qos.logback - logback-classic - 1.2.1 - true - - - org.apache.tinkerpop - tinkergraph-gremlin - ${tinkerpop.version} - - - org.apache.tinkerpop - gremlin-core - ${tinkerpop.version} - - - org.slf4j - slf4j-log4j12 - - - org.slf4j - jcl-over-slf4j - - - - - com.thinkaurelius.titan - titan-cassandra - 1.0.0 - true - - - org.apache.tinkerpop - gremlin-groovy - - - org.slf4j - slf4j-log4j12 - - - ch.qos.logback - logback-classic - - - org.apache.tinkerpop - gremlin-core - - - - - com.thinkaurelius.titan - titan-hbase - 1.0.0 - true - - - org.apache.tinkerpop - gremlin-groovy - - - org.slf4j - slf4j-log4j12 - - - ch.qos.logback - logback-classic - - - org.apache.tinkerpop - gremlin-core - - - - - org.apache.hbase - hbase-client - 0.98.4-hadoop2 - - - org.slf4j - slf4j-log4j12 - - - com.google.guava - guava - - - - - jdk.tools - jdk.tools - 1.8 - system - ${JAVA_HOME}/lib/tools.jar - - - org.jacoco - org.jacoco.agent - 0.7.9 - runtime - test - + org.onap.aai + champ + cc-champ + pom + 1.2.0-SNAPSHOT - - - com.att.nsa - cambriaClient - 0.0.1 - - - - org.apache.httpcomponents - httpclient - 4.5 - - - - - - - org.codehaus.mojo - sonar-maven-plugin - 3.2 - - - org.jacoco - jacoco-maven-plugin - 0.7.9 - - - - **/AbstractGremlinChampGraph* - **/DseChampGraphImpl* - **/DseChampformer* - - **/ChampAPIPerformanceTest* - - - - - default-prepare-agent - - prepare-agent - - - - default-report - prepare-package - - report - - - - default-check - - check - - - - - - BUNDLE - - - - INSTRUCTION - COVEREDRATIO - .75 - - - BRANCH - COVEREDRATIO - .74 - - - COMPLEXITY - COVEREDRATIO - .75 - - - LINE - COVEREDRATIO - .80 - - - METHOD - COVEREDRATIO - .90 - - - CLASS - MISSEDCOUNT - 0 - - - - - - - - - - org.apache.maven.plugins - maven-assembly-plugin - 3.0.0 - - - jar-with-dependencies - - - - - make-jar-with-dependencies - package - - single - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.6.1 - - 1.8 - 1.8 - - - - maven-release-plugin - 2.4.2 - - - org.apache.maven.scm - maven-scm-provider-gitexe - 1.8.1 - - - - - org.apache.maven.plugins - maven-source-plugin - 3.0.1 - - - attach-sources - - jar - - - - - - org.apache.maven.plugins - maven-javadoc-plugin - 2.9.1 - - - attach-javadocs - - jar - - - - - - org.apache.maven.plugins - maven-surefire-plugin - - - target/jacoco.exec - - - - - org.apache.maven.plugins - maven-deploy-plugin - 2.8.2 - - - default-deploy - none - - - - - org.sonatype.plugins - nexus-staging-maven-plugin - 1.6.7 - true - - ${onap.nexus.url} - 176c31dfe190a - ecomp-staging - - - - org.apache.maven.plugins - maven-site-plugin - 3.6 - - - org.apache.maven.wagon - wagon-webdav-jackrabbit - 2.10 - - - - - com.mycila - license-maven-plugin - 3.0 - -

License.txt
- - **/*.java - **/*.ksh - **/*.sh - **/*.ftl - **/*.xsd - **/*.xjb - **/*.yml - **/*.yaml - **/aai*.xml - **/*logback*.xml - **/*aaiconfig*.properties - **/*titan*.properties - - - - - - format - - process-sources - - - - - - - - - org.apache.maven.plugins - maven-javadoc-plugin - 2.10.4 - - false - org.umlgraph.doclet.UmlGraphDoc - - org.umlgraph - umlgraph - 5.6 - - -views - true - - - - - + + champ-lib + champ-service + champ-service-deps-janus + champ-service-deps-titan + + + \ No newline at end of file diff --git a/src/main/java/org/onap/aai/champ/ChampGraph.java b/src/main/java/org/onap/aai/champ/ChampGraph.java deleted file mode 100644 index 2762e43..0000000 --- a/src/main/java/org/onap/aai/champ/ChampGraph.java +++ /dev/null @@ -1,308 +0,0 @@ -/** - * ============LICENSE_START========================================== - * org.onap.aai - * =================================================================== - * Copyright © 2017 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017 Amdocs - * =================================================================== - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END============================================ - * ECOMP is a trademark and service mark of AT&T Intellectual Property. - */ -package org.onap.aai.champ; - -import java.util.Map; -import java.util.Optional; -import java.util.stream.Stream; - -import org.onap.aai.champ.exceptions.ChampIndexNotExistsException; -import org.onap.aai.champ.exceptions.ChampMarshallingException; -import org.onap.aai.champ.exceptions.ChampObjectNotExistsException; -import org.onap.aai.champ.exceptions.ChampRelationshipNotExistsException; -import org.onap.aai.champ.exceptions.ChampSchemaViolationException; -import org.onap.aai.champ.exceptions.ChampUnmarshallingException; -import org.onap.aai.champ.graph.impl.InMemoryChampGraphImpl; -import org.onap.aai.champ.graph.impl.TitanChampGraphImpl; -import org.onap.aai.champ.model.ChampObject; -import org.onap.aai.champ.model.ChampObjectConstraint; -import org.onap.aai.champ.model.ChampObjectIndex; -import org.onap.aai.champ.model.ChampPartition; -import org.onap.aai.champ.model.ChampRelationship; -import org.onap.aai.champ.model.ChampRelationshipConstraint; -import org.onap.aai.champ.model.ChampRelationshipIndex; -import org.onap.aai.champ.model.ChampSchema; - -public interface ChampGraph { - - /** - * Types that the Factory is capable of constructing - */ - public enum Type { - IN_MEMORY, - TITAN/*, - DSE //DSE is still in beta, so leave it out for now - */ - } - - /** - * A factory for constructing basic ChampAPI implementations (minimal). - * If finer control is needed, you should consider accessing an implementation's - * constructors/builders. - */ - public static final class Factory { - private Factory(){ - //not called - } - public static ChampGraph newInstance(ChampGraph.Type type, String graphName) { - switch (type) { - case IN_MEMORY: - return new InMemoryChampGraphImpl.Builder().build(); - case TITAN: - return new TitanChampGraphImpl.Builder(graphName) - .property("storage.backend", "inmemory") - .build(); - /* - case DSE: //See above, DSE still in beta - */ - default: - throw new RuntimeException("Unknown type of ChampAPI implementation"); - } - } - } - - /** - * Create/Update an object. If the ChampObject key is present, an update will be attempted, - * otherwise a create will be attempted. Each implementation has different guarantees on - * validation - see the specific implementation for more details on this. - * @param object - The ChampObject that you wish to store in the graph - * @return The ChampObject as it was stored - * @throws ChampMarshallingException If the {@code object} is not able to be marshalled into the backend representation - * @throws ChampSchemaViolationException If the {@code object} violates the constraints specifed by {@link ChampGraph#retrieveSchema} - * @throws ChampObjectNotExistsException If {@link org.onap.aai.champ.model.ChampObject#getKey}.isPresent() but the object cannot be found in the graph - */ - public ChampObject storeObject(ChampObject object) throws ChampMarshallingException, ChampSchemaViolationException, ChampObjectNotExistsException; - - /** - * Replace an object. ChampObject key is mandatory - * Each implementation has different guarantees on - * validation - see the specific implementation for more details on this. - * @param object - The ChampObject that you wish to replace in the graph - * @return The ChampObject as it was stored - * @throws ChampMarshallingException If the {@code object} is not able to be marshalled into the backend representation - * @throws ChampSchemaViolationException If the {@code object} violates the constraints specifed by {@link ChampGraph#retrieveSchema} - * @throws ChampObjectNotExistsException If {@link org.onap.aai.champ.model.ChampObject#getKey} is not present or object not found in the graph - */ - public ChampObject replaceObject(ChampObject object) throws ChampMarshallingException, ChampSchemaViolationException, ChampObjectNotExistsException; - - /** - * Retrieve an object by its key. - * @param key The key of the ChampObject in the graph {@link org.onap.aai.champ.model.ChampObject#getKey()} - * @return The {@link org.onap.aai.champ.model.ChampObject} if it was present, otherwise {@link Optional#empty()} - * @throws ChampUnmarshallingException If the object was found, but could not be unmarshalled - */ - public Optional retrieveObject(Object key) throws ChampUnmarshallingException; - - /** - * Delete an object by its key. - * @param key The key of the ChampObject in the graph {@link ChampObject#getKey} - * @throws ChampObjectNotExistsException If the object did not exist in the graph - */ - public void deleteObject(Object key) throws ChampObjectNotExistsException; - - /** - * Retrieve all the objects whose properties match the given {@code queryParams} - * @param queryParams The key/value pairs which are found in {@link ChampObject#getProperties} - * @return A {@link Stream} where each {@link ChampObject#getProperties} contains the {@code queryParams} - */ - public Stream queryObjects(Map queryParams); - - /** - * Create/Update a relationship. If the ChampRelationship key is present, an update will be attempted, - * otherwise a create will be attempted. Each implementation has different guarantees on - * validation - see the specific implementation for more details on this. - * @param relationship - The ChampRelationship that you wish to store in the graph - * @return The ChampRelationship as it was stored - * @throws ChampMarshallingException If the {@code relationship} is not able to be marshalled into the backend representation - * @throws ChampSchemaViolationException If the {@code relationship} violates the constraints specifed by {@link ChampGraph#retrieveSchema} - * @throws ChampObjectNotExistsException If either the source or target object referenced by this relationship does not exist in the graph - * @throws ChampRelationshipNotExistsException If {@link org.onap.aai.champ.model.ChampRelationship#getKey}.isPresent() but the object cannot be found in the graph - * @throws ChampUnmarshallingException If the edge which was created could not be unmarshalled into a ChampRelationship - */ - public ChampRelationship storeRelationship(ChampRelationship relationship) throws ChampMarshallingException, ChampObjectNotExistsException, ChampSchemaViolationException, ChampRelationshipNotExistsException, ChampUnmarshallingException; - - /** - * Replace a relationship. ChampRelationship key is mandatory .The main purpose of this method is to replace the entire properties of an existing relationship .Source/Target can't be updated with this method - * Each implementation has different guarantees on - * validation - see the specific implementation for more details on this. - * @param relationship - The ChampRelationship that you wish to replace in the graph - * @return The ChampRelationship as it was stored - * @throws ChampMarshallingException If the {@code relationship} is not able to be marshalled into the backend representation - * @throws ChampSchemaViolationException If the {@code relationship} violates the constraints specifed by {@link ChampGraph#retrieveSchema} - * @throws ChampRelationshipNotExistsException If {@link org.onap.aai.champ.model.ChampRelationship#getKey} is not present or object not found in the graph - * @throws ChampUnmarshallingException If the edge which was created could not be unmarshalled into a ChampRelationship - */ - public ChampRelationship replaceRelationship(ChampRelationship relationship) throws ChampMarshallingException, ChampSchemaViolationException, ChampRelationshipNotExistsException, ChampUnmarshallingException; - - - /** - * Retrieve a relationship by its key. - * @param key The key of the ChampRelationship in the graph {@link org.onap.aai.champ.model.ChampRelationship#getKey()} - * @return The {@link org.onap.aai.champ.model.ChampRelationship} if it was present, otherwise {@link Optional#empty()} - * @throws ChampUnmarshallingException If the relationship was found, but could not be unmarshalled - */ - public Optional retrieveRelationship(Object key) throws ChampUnmarshallingException; - - /** - * Delete a relationship by its key. - * @param relationship The ChampRelationship in the graph ({@link ChampRelationship#getKey must be present}) - * @throws ChampRelationshipNotExistsException If the object did not exist in the graph - */ - public void deleteRelationship(ChampRelationship relationship) throws ChampRelationshipNotExistsException; - - /** - * Retrieve the relationships which are incident to the {@code object} - * @param object The object you wish to find incident relationships for - * @return A {@link Stream} where each {@link ChampRelationship} has this {@code object} as either a source or target object - * @throws ChampUnmarshallingException If any of the ChampRelationship objects could not be unmarshalled - * @throws ChampObjectNotExistsException If the {@code object} does not exist in this graph - */ - public Stream retrieveRelationships(ChampObject object) throws ChampUnmarshallingException, ChampObjectNotExistsException; - - /** - * Retrieve the relationships whose properties match the given {@code queryParams} - * @param queryParams The key/value pairs to search for in the {@link ChampRelationship#getProperties} - * @return A {@link Stream} where each {@link ChampRelationship#getProperties} contains the {@code queryParams} - */ - public Stream queryRelationships(Map queryParams); - - /** - * Create/Update a {@link ChampPartition}. If any of the ChampObjects or ChampRelationships - * present in this ChampPartition already exist, an update will be attempted, otherwise a create - * will be attempted. Each implementation has different guarantees on validation - - * see the specific implementation details for more information on this. - * @param partition The ChampPartition you wish to store in this graph - * @throws ChampMarshallingException If any of the objects or relationships contained in this - * partition could not be marshalled into its backed representation - * @throws ChampObjectNotExistsException If any of the objects being updated do not exist, or if a relationship - * contain objects which do not exist in the graph. - * @throws ChampSchemaViolationException If any of the objects or relationships violate the schema provided by {@link retrieveSchema} - * @throws ChampRelationshipNotExistsException If any of the relationships which are being updated do not exist - * @return The ChampPartition as is was stored in the graph (contains keys for each newly created object) - */ - public ChampPartition storePartition(ChampPartition partition) throws ChampMarshallingException, ChampObjectNotExistsException, ChampSchemaViolationException, ChampRelationshipNotExistsException; - - /** - * Delete the {@code partition} from the graph - * @param partition The partition to delete from the graph - */ - public void deletePartition(ChampPartition partition); - - /** - * Create/Update an object index on the graph - * @param index The index to create on this {@code graph} - */ - public void storeObjectIndex(ChampObjectIndex index); - - /** - * Retrieve an object index on the graph by its {@code indexName} - * @param indexName The name of the index to retrieve from the graph - * @return The {@link ChampObjectIndex} which matches the given @{code indexName} in the graph - */ - public Optional retrieveObjectIndex(String indexName); - - /** - * Retrieve the object indices on the graph - * @return A {@link Stream} where each {@link ChampObjectIndex} exists in the graph - */ - public Stream retrieveObjectIndices(); - - /** - * Delete the object index on the graph by its {@code indexName} - * @param indexName The name of the index to delete from the graph - * @throws ChampIndexNotExistsException If an index does not exist with the given {@code indexName} in the graph - */ - public void deleteObjectIndex(String indexName) throws ChampIndexNotExistsException; - - /** - * Create/Update a relationship index on the graph - * @param index The relationship index to create on the graph - */ - public void storeRelationshipIndex(ChampRelationshipIndex index); - - /** - * Retrieve a relationship index from the graph - * @param indexName The name of the relationship index to retrieve from the graph - * @return The {@link ChampRelationshipIndex} which matches the given {@code indexName} in the graph - * or {@link Optional#empty} if no such relationship index exists - */ - public Optional retrieveRelationshipIndex(String indexName); - - /** - * Retrieve the relationship indices from the graph - * @return A {@link Stream} where each {@link ChampRelationshipIndex} exists in the graph - */ - public Stream retrieveRelationshipIndices(); - - /** - * Delete a relationship index from the graph - * @param indexName THe name of the index to delete from the graph - * @throws ChampIndexNotExistsException If an index does not exist with the give {@code indexName} in the graph - */ - public void deleteRelationshipIndex(String indexName) throws ChampIndexNotExistsException; - - /** - * Create/Update the schema for a graph - * @param schema The {@link ChampSchema} to create or update on the graph - * @throws ChampSchemaViolationException If this schema update would violate the current schema - */ - public void storeSchema(ChampSchema schema) throws ChampSchemaViolationException; - - /** - * Retrieve the schema for a graph - * @return The {@link ChampSchema} for the graph - */ - public ChampSchema retrieveSchema(); - - /** - * Create/Update an object constraint on a schema - * @param objectConstraint The object constraint you wish to create/update for the graph - * @throws ChampSchemaViolationException If this schema update would violate the current schema - */ - public void updateSchema(ChampObjectConstraint objectConstraint) throws ChampSchemaViolationException; - - /** - * Create/Update a relationship constraint on a schema - * @param schema The relationship constraint you wish to create/update for the graph - * @throws ChampSchemaViolationException If this schema update would violate the current schema - */ - public void updateSchema(ChampRelationshipConstraint schema) throws ChampSchemaViolationException; - - /** - * Delete the schema for a graph - */ - public void deleteSchema(); - - /** - * Shutdown the ChampAPI. It is up to the caller to synchronize access to the ChampAPI - * so that shutting it down does not interfere with concurrent operations. - */ - public void shutdown(); - - /** - * Used to determine what the outcome of certain ChampGraph operations will be. For example, - * if this graph is not capable of deleting object indices, you can expect those calls to fail. - * @see ChampCapabilities - * @return What this graph is capable of performing - */ - public ChampCapabilities capabilities(); -} diff --git a/src/main/java/org/onap/aai/champ/graph/impl/AbstractGremlinChampGraph.java b/src/main/java/org/onap/aai/champ/graph/impl/AbstractGremlinChampGraph.java deleted file mode 100644 index 8f806bf..0000000 --- a/src/main/java/org/onap/aai/champ/graph/impl/AbstractGremlinChampGraph.java +++ /dev/null @@ -1,350 +0,0 @@ -/** - * ============LICENSE_START========================================== - * org.onap.aai - * =================================================================== - * Copyright © 2017 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017 Amdocs - * =================================================================== - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END============================================ - * ECOMP is a trademark and service mark of AT&T Intellectual Property. - */ -package org.onap.aai.champ.graph.impl; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Optional; -import java.util.Set; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal; -import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversalSource; -import org.apache.tinkerpop.gremlin.structure.Edge; -import org.apache.tinkerpop.gremlin.structure.Vertex; -import org.apache.tinkerpop.gremlin.structure.VertexProperty; -import org.onap.aai.champ.exceptions.ChampMarshallingException; -import org.onap.aai.champ.exceptions.ChampObjectNotExistsException; -import org.onap.aai.champ.exceptions.ChampRelationshipNotExistsException; -import org.onap.aai.champ.exceptions.ChampUnmarshallingException; -import org.onap.aai.champ.graph.impl.TitanChampGraphImpl.Builder; -import org.onap.aai.champ.model.ChampElement; -import org.onap.aai.champ.model.ChampObject; -import org.onap.aai.champ.model.ChampPartition; -import org.onap.aai.champ.model.ChampRelationship; -import org.onap.aai.champ.model.fluent.partition.CreateChampPartitionable; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public abstract class AbstractGremlinChampGraph extends AbstractValidatingChampGraph { - - private static final Logger LOGGER = LoggerFactory.getLogger(AbstractGremlinChampGraph.class); - - protected abstract GraphTraversalSource startTraversal(); - protected abstract Stream runTraversal(GraphTraversal traversal); - - protected AbstractGremlinChampGraph(Map properties) { - super(properties); - } - - @Override - public Optional retrieveObject(Object key) throws ChampUnmarshallingException { - if (isShutdown()) throw new IllegalStateException("Cannot use ChampAPI after calling shutdown()"); - - final Stream elements = runTraversal(startTraversal().V(key).limit(1)); - - if (elements.count() == 0) { - return Optional.empty(); - } - - return Optional.of(elements.findFirst().get().asObject()); - } - - public void executeDeleteObject(Object key) throws ChampObjectNotExistsException { - if (isShutdown()) throw new IllegalStateException("Cannot use ChampAPI after calling shutdown()"); - - final Stream elements = runTraversal(startTraversal().V(key).limit(1)); - - if (elements.count() == 0) { - throw new ChampObjectNotExistsException(); - } - - runTraversal(startTraversal().V(key).drop()); - } - - @Override - public Stream queryObjects(Map queryParams) { - if (isShutdown()) throw new IllegalStateException("Cannot use ChampAPI after calling shutdown()"); - - //If they provided the object key, do this the quick way rather than creating a traversal - if (queryParams.containsKey(ChampObject.ReservedPropertyKeys.CHAMP_OBJECT_KEY.toString())) { - try { - final Optional object = retrieveObject(queryParams.get(ChampObject.ReservedPropertyKeys.CHAMP_OBJECT_KEY.toString())); - - if (object.isPresent()) return Stream.of(object.get()); - else return Stream.empty(); - } catch (ChampUnmarshallingException e) { - LOGGER.warn("Failed to unmarshall object", e); - return Stream.empty(); - } - } - - final GraphTraversal traversal = startTraversal().V(); - - for (Entry filter : queryParams.entrySet()) { - if (filter.getKey().equals(ChampObject.ReservedPropertyKeys.CHAMP_OBJECT_TYPE.toString())) { - continue; //For performance reasons, the label is the last thing to be added - } else { - traversal.has(filter.getKey(), filter.getValue()); - } - } - - if (queryParams.containsKey(ChampObject.ReservedPropertyKeys.CHAMP_OBJECT_TYPE.toString())) { - traversal.hasLabel((String) queryParams.get(ChampObject.ReservedPropertyKeys.CHAMP_OBJECT_TYPE.toString())); - } - - - return runTraversal(traversal).map(element -> { - return element.asObject(); //Safe, since we're only operating on vertices - }); - } - - @Override - public Optional retrieveRelationship(Object key) throws ChampUnmarshallingException { - if (isShutdown()) throw new IllegalStateException("Cannot use ChampAPI after calling shutdown()"); - - final Stream elements = runTraversal(startTraversal().E(key).limit(1)); - - if (elements.count() == 0) return Optional.empty(); - - return Optional.of(elements.findFirst().get().asRelationship()); - } - - public void executeDeleteRelationship(ChampRelationship relationship) throws ChampRelationshipNotExistsException { - if (isShutdown()) throw new IllegalStateException("Cannot use ChampAPI after calling shutdown()"); - if (!relationship.getKey().isPresent()) throw new IllegalArgumentException("Key must be provided when deleting a relationship"); - - final Stream elements = runTraversal(startTraversal().E(relationship.getKey().get()).limit(1)); - - if (elements.count() == 0) { - throw new ChampRelationshipNotExistsException(); - } - - runTraversal(startTraversal().E(relationship.getKey().get()).drop()); - } - - @Override - public Stream retrieveRelationships(ChampObject object) - throws ChampUnmarshallingException, ChampObjectNotExistsException { - if (isShutdown()) throw new IllegalStateException("Cannot use ChampAPI after calling shutdown()"); - - final Stream elements = runTraversal(startTraversal().V(object.getKey().get()).limit(1).bothE()); - - return elements.map(element -> { - return element.asRelationship(); //Safe, since we're only operating on edges - }); - } - - @Override - public Stream queryRelationships(Map queryParams) { - if (isShutdown()) throw new IllegalStateException("Cannot use ChampAPI after calling shutdown()"); - - //If they provided the relationship key, do this the quick way rather than creating a traversal - if (queryParams.containsKey(ChampRelationship.ReservedPropertyKeys.CHAMP_RELATIONSHIP_KEY.toString())) { - try { - final Optional relationship = retrieveRelationship(queryParams.get(ChampRelationship.ReservedPropertyKeys.CHAMP_RELATIONSHIP_KEY.toString())); - - if (relationship.isPresent()) return Stream.of(relationship.get()); - else return Stream.empty(); - } catch (ChampUnmarshallingException e) { - LOGGER.warn("Failed to unmarshall relationship", e); - return Stream.empty(); - } - } - - final GraphTraversal traversal = startTraversal().E(); - - for (Entry filter : queryParams.entrySet()) { - if (filter.getKey().equals(ChampRelationship.ReservedPropertyKeys.CHAMP_RELATIONSHIP_TYPE.toString())) { - continue; //Add the label last for performance reasons - } else { - traversal.has(filter.getKey(), filter.getValue()); - } - } - - if (queryParams.containsKey(ChampRelationship.ReservedPropertyKeys.CHAMP_RELATIONSHIP_TYPE.toString())) { - traversal.hasLabel((String) queryParams.get(ChampRelationship.ReservedPropertyKeys.CHAMP_RELATIONSHIP_TYPE.toString())); - } - - return runTraversal(traversal).map(element -> { - return element.asRelationship(); //Safe, since we are only operating on edges - }); - } - - @Override - public void executeDeletePartition(ChampPartition graph) { - if (isShutdown()) throw new IllegalStateException("Cannot use ChampAPI after calling shutdown()"); - - final Object[] objectIds = graph.getChampObjects() - .stream() - .filter(o -> o.getKey().isPresent()) - .map(o -> { return o.getKey().get(); }) - .collect(Collectors.toList()) - .toArray(); - - final Object[] relationshipIds = graph.getChampRelationships() - .stream() - .filter(o -> o.getKey().isPresent()) - .map(o -> { return o.getKey().get(); }) - .collect(Collectors.toList()) - .toArray(); - - runTraversal(startTraversal().V(objectIds).drop()); - runTraversal(startTraversal().E(relationshipIds).drop()); - } - - @Override - protected ChampObject doStoreObject(ChampObject object) - throws ChampMarshallingException, ChampObjectNotExistsException { - final GraphTraversal traversal; - - if (object.getKey().isPresent()) { - traversal = startTraversal().V(object.getKey().get()); - } else { - traversal = startTraversal().addV(object.getType()); - } - - for (Entry property : object.getProperties().entrySet()) { - - if (property.getValue() instanceof List) { - for (Object subPropertyValue : (List) property.getValue()) { - traversal.property(VertexProperty.Cardinality.list, property.getKey(), subPropertyValue); - } - } else if (property.getValue() instanceof Set) { - for (Object subPropertyValue : (Set) property.getValue()) { - traversal.property(VertexProperty.Cardinality.set, property.getKey(), subPropertyValue); - } - } else { - traversal.property(property.getKey(), property.getValue()); - } - } - - return runTraversal(traversal).findFirst().get().asObject(); //TODO check if this return the updated vertices - } - - @Override - protected ChampObject doReplaceObject(ChampObject object) - throws ChampMarshallingException, ChampObjectNotExistsException { - //TODO: implement the replace method when required - throw new UnsupportedOperationException("Method not implemented"); - } - - @Override - protected ChampRelationship doReplaceRelationship(ChampRelationship relationship) throws ChampRelationshipNotExistsException, ChampMarshallingException { - //TODO: implement the replace method when required - throw new UnsupportedOperationException("Method not implemented"); - } - - @Override - protected ChampRelationship doStoreRelationship(ChampRelationship relationship) throws ChampObjectNotExistsException, ChampRelationshipNotExistsException, ChampMarshallingException { - - /* FIXME: Only compatible with Tinkerpop 3.2.3 (Titan uses 3.0.1-incubating). - - final GraphTraversal sourceBuilder; - - if (relationship.getSource().getKey().isPresent()) { - sourceBuilder = startTraversal().V(relationship.getSource().getKey().get()).as("source"); - } else { - sourceBuilder = startTraversal().addV(relationship.getSource().getType()); - } - - for (Entry sourceProperty : relationship.getSource().getProperties().entrySet()) { - sourceBuilder.property(sourceProperty.getKey(), sourceProperty.getValue()); - } - - final GraphTraversal targetBuilder; - - if (relationship.getTarget().getKey().isPresent()) { - targetBuilder = sourceBuilder.V(relationship.getTarget().getKey().get()).as("target"); - } else { - targetBuilder = sourceBuilder.addV(relationship.getTarget().getType()); - } - - for (Entry targetProperty : relationship.getTarget().getProperties().entrySet()) { - targetBuilder.property(targetProperty.getKey(), targetProperty.getValue()); - } - - final GraphTraversal edgeBuilder = targetBuilder.addE(relationship.getType()).from("source"); - - for (Entry property : relationship.getProperties().entrySet()) { - edgeBuilder.property(property.getKey(), property.getValue()); - } - - return runTraversal(edgeBuilder).filter(e -> e.isRelationship()).findFirst().get().asRelationship(); - */ - - throw new UnsupportedOperationException("Cannot store relationships because of project setup (Incompatible Tinkerpop version in use)"); - } - - @Override - protected ChampPartition doStorePartition(ChampPartition submittedPartition) throws ChampObjectNotExistsException, ChampMarshallingException, ChampRelationshipNotExistsException { - if (isShutdown()) throw new IllegalStateException("Cannot use ChampAPI after calling shutdown()"); - - try { - final HashMap objectsWithKeys = new HashMap (); - final CreateChampPartitionable storedPartition = ChampPartition.create(); - - for (ChampObject champObject : submittedPartition.getChampObjects()) { - - final ChampObject objectWithKey = doStoreObject(champObject); - objectsWithKeys.put(champObject, objectWithKey); - } - - for (ChampRelationship champRelationship : submittedPartition.getChampRelationships()) { - if (!objectsWithKeys.containsKey(champRelationship.getSource())) { - final ChampObject objectWithKey = doStoreObject(champRelationship.getSource()); - - objectsWithKeys.put(champRelationship.getSource(), objectWithKey); - } - - if (!objectsWithKeys.containsKey(champRelationship.getTarget())) { - final ChampObject objectWithKey = doStoreObject(champRelationship.getTarget()); - - objectsWithKeys.put(champRelationship.getTarget(), objectWithKey); - } - - final ChampRelationship.Builder relWithKeysBuilder = new ChampRelationship.Builder(objectsWithKeys.get(champRelationship.getSource()), - objectsWithKeys.get(champRelationship.getTarget()), - champRelationship.getType()); - - if (champRelationship.getKey().isPresent()) relWithKeysBuilder.key(champRelationship.getKey().get()); - - relWithKeysBuilder.properties(champRelationship.getProperties()); - - final ChampRelationship relationship = doStoreRelationship(relWithKeysBuilder.build()); - - storedPartition.withRelationship(relationship); - } - - for (ChampObject object : objectsWithKeys.values()) { - storedPartition.withObject(object); - } - - return storedPartition.build(); - } catch (ChampObjectNotExistsException | ChampMarshallingException e) { - throw e; - } - } -} diff --git a/src/main/java/org/onap/aai/champ/graph/impl/AbstractTinkerpopChampGraph.java b/src/main/java/org/onap/aai/champ/graph/impl/AbstractTinkerpopChampGraph.java deleted file mode 100644 index fbe30f7..0000000 --- a/src/main/java/org/onap/aai/champ/graph/impl/AbstractTinkerpopChampGraph.java +++ /dev/null @@ -1,753 +0,0 @@ -/** - * ============LICENSE_START========================================== - * org.onap.aai - * =================================================================== - * Copyright © 2017 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017 Amdocs - * =================================================================== - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END============================================ - * ECOMP is a trademark and service mark of AT&T Intellectual Property. - */ -package org.onap.aai.champ.graph.impl; - -import java.io.IOException; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.NoSuchElementException; -import java.util.Optional; -import java.util.Set; -import java.util.Spliterator; -import java.util.Spliterators; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.stream.Stream; -import java.util.stream.StreamSupport; - -import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.GraphTraversal; -import org.apache.tinkerpop.gremlin.structure.Direction; -import org.apache.tinkerpop.gremlin.structure.Edge; -import org.apache.tinkerpop.gremlin.structure.Graph; -import org.apache.tinkerpop.gremlin.structure.Property; -import org.apache.tinkerpop.gremlin.structure.Vertex; -import org.apache.tinkerpop.gremlin.structure.VertexProperty; -import org.onap.aai.champ.event.ChampEvent; -import org.onap.aai.champ.event.ChampEvent.ChampOperation; -import org.onap.aai.champ.exceptions.ChampMarshallingException; -import org.onap.aai.champ.exceptions.ChampObjectNotExistsException; -import org.onap.aai.champ.exceptions.ChampRelationshipNotExistsException; -import org.onap.aai.champ.exceptions.ChampSchemaViolationException; -import org.onap.aai.champ.exceptions.ChampUnmarshallingException; -import org.onap.aai.champ.graph.impl.TitanChampGraphImpl.Builder; -import org.onap.aai.champ.model.ChampObject; -import org.onap.aai.champ.model.ChampPartition; -import org.onap.aai.champ.model.ChampRelationship; -import org.onap.aai.champ.model.ChampSchema; -import org.onap.aai.champ.model.fluent.partition.CreateChampPartitionable; -import org.onap.aai.champ.transform.TinkerpopChampformer; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.ObjectMapper; - -public abstract class AbstractTinkerpopChampGraph extends AbstractValidatingChampGraph { - - private static final Logger LOGGER = LoggerFactory.getLogger(AbstractTinkerpopChampGraph.class); - private static final TinkerpopChampformer TINKERPOP_CHAMPFORMER = new TinkerpopChampformer(); - private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); - - private static final int COMMIT_RETRY_COUNT = 3; - - private volatile AtomicBoolean isShutdown; - - protected AbstractTinkerpopChampGraph(Map properties) { - super(properties); - - isShutdown = new AtomicBoolean(false); - Runtime.getRuntime().addShutdownHook(shutdownHook); - } - - private static final TinkerpopChampformer getChampformer() { - return TINKERPOP_CHAMPFORMER; - } - - private static final ObjectMapper getObjectMapper() { - return OBJECT_MAPPER; - } - - private Vertex writeVertex(ChampObject object) throws ChampObjectNotExistsException, ChampMarshallingException { - final Vertex vertex; - - if (object.getKey().isPresent()) { - final Iterator vertexIter = getGraph().vertices(object.getKey().get()); - - if (vertexIter.hasNext()) { - vertex = vertexIter.next(); - } else throw new ChampObjectNotExistsException(); - } else { - vertex = getGraph().addVertex(object.getType()); - } - - for (Entry property : object.getProperties().entrySet()) { - - if (property.getValue() instanceof List) { - for (Object subPropertyValue : (List) property.getValue()) { - vertex.property(VertexProperty.Cardinality.list, property.getKey(), subPropertyValue); - } - } else if (property.getValue() instanceof Set) { - for (Object subPropertyValue : (Set) property.getValue()) { - vertex.property(VertexProperty.Cardinality.set, property.getKey(), subPropertyValue); - } - } else { - vertex.property(property.getKey(), property.getValue()); - } - } - - return vertex; - } - - private Vertex replaceVertex(ChampObject object) throws ChampObjectNotExistsException, ChampMarshallingException { - Vertex vertex; - - if (object.getKey().isPresent()) { - final Iterator vertexIter = getGraph().vertices(object.getKey().get()); - - if (vertexIter.hasNext()) { - vertex = vertexIter.next(); - } else throw new ChampObjectNotExistsException(); - } else { - throw new ChampObjectNotExistsException(); - } - - //clear all the existing properties - Iterator> it = vertex.properties(); - while (it.hasNext()) { - it.next().remove(); - } - - for (Entry property : object.getProperties().entrySet()) { - - if (property.getValue() instanceof List) { - for (Object subPropertyValue : (List) property.getValue()) { - vertex.property(VertexProperty.Cardinality.list, property.getKey(), subPropertyValue); - } - } else if (property.getValue() instanceof Set) { - for (Object subPropertyValue : (Set) property.getValue()) { - vertex.property(VertexProperty.Cardinality.set, property.getKey(), subPropertyValue); - } - } else { - vertex.property(property.getKey(), property.getValue()); - } - } - - return vertex; - } - - private Edge writeEdge(ChampRelationship relationship) throws ChampObjectNotExistsException, ChampRelationshipNotExistsException, ChampMarshallingException { - - final Vertex source = writeVertex(relationship.getSource()); - final Vertex target = writeVertex(relationship.getTarget()); - final Edge edge; - - if (relationship.getKey().isPresent()) { - final Iterator edgeIter = getGraph().edges(relationship.getKey().get()); - - if (edgeIter.hasNext()) { - edge = edgeIter.next(); - } else throw new ChampRelationshipNotExistsException(); - } else { - edge = source.addEdge(relationship.getType(), target); - } - - for (Entry property : relationship.getProperties().entrySet()) { - edge.property(property.getKey(), property.getValue()); - } - - return edge; - } - - private Edge replaceEdge(ChampRelationship relationship) throws ChampRelationshipNotExistsException, ChampMarshallingException { - final Edge edge; - - if(!relationship.getSource().getKey().isPresent() || !relationship.getTarget().getKey().isPresent()){ - throw new IllegalArgumentException("Invalid source/target"); - } - - if (relationship.getKey().isPresent()) { - final Iterator edgeIter = getGraph().edges(relationship.getKey().get()); - - if (edgeIter.hasNext()) { - edge = edgeIter.next(); - //validate if the source/target are the same as before. Throw error if not the same - if (!edge.outVertex().id().equals(relationship.getSource().getKey().get()) - || !edge.inVertex().id().equals(relationship.getTarget().getKey().get())) { - throw new IllegalArgumentException("source/target can't be updated"); - } - - } else throw new ChampRelationshipNotExistsException(); - } else { - throw new ChampRelationshipNotExistsException(); - } - - // clear all the existing properties - Iterator> it = edge.properties(); - while (it.hasNext()) { - it.next().remove(); - } - - for (Entry property : relationship.getProperties().entrySet()) { - edge.property(property.getKey(), property.getValue()); - } - - return edge; - } - - private void tryRollback() { - if (getGraph().features().graph().supportsTransactions()) { - getGraph().tx().rollback(); - } - } - - private void tryCommit() { - - if (getGraph().features().graph().supportsTransactions()) { - - final long initialBackoff = (int) (Math.random() * 50); - - for (int i = 0; i < COMMIT_RETRY_COUNT; i++) { - try { - getGraph().tx().commit(); - return; - } catch (Throwable e) { - if (i == COMMIT_RETRY_COUNT - 1) { - LOGGER.error("Maxed out commit attempt retries, client must handle exception and retry", e); - getGraph().tx().rollback(); - throw e; - } - - final long backoff = (long) Math.pow(2, i) * initialBackoff; - LOGGER.warn("Caught exception while retrying transaction commit, retrying in " + backoff + " ms"); - - try { - Thread.sleep(backoff); - } catch (InterruptedException ie) { - LOGGER.info("Interrupted while backing off on transaction commit"); - return; - } - } - } - } - } - - protected abstract Graph getGraph(); - - private Thread shutdownHook = new Thread() { - @Override - public void run() { - try { - shutdown(); - } catch (IllegalStateException e) { - //Suppress, because shutdown() has already been called - } - } - }; - - protected boolean isShutdown() { - return isShutdown.get(); - } - - @Override - public Stream queryObjects(Map queryParams) { - if (isShutdown()) throw new IllegalStateException("Cannot use ChampAPI after calling shutdown()"); - - //If they provided the object key, do this the quick way rather than creating a traversal - if (queryParams.containsKey(ChampObject.ReservedPropertyKeys.CHAMP_OBJECT_KEY.toString())) { - try { - final Optional object = retrieveObject(queryParams.get(ChampObject.ReservedPropertyKeys.CHAMP_OBJECT_KEY.toString())); - - if (object.isPresent()) return Stream.of(object.get()); - else return Stream.empty(); - } catch (ChampUnmarshallingException e) { - LOGGER.warn("Failed to unmarshall object", e); - return Stream.empty(); - } - } - - final GraphTraversal query = getGraph().traversal().V(); - - for (Entry filter : queryParams.entrySet()) { - if (filter.getKey().equals(ChampObject.ReservedPropertyKeys.CHAMP_OBJECT_TYPE.toString())) { - continue; //For performance reasons, the label is the last thing to be added - } else { - query.has(filter.getKey(), filter.getValue()); - } - } - - if (queryParams.containsKey(ChampObject.ReservedPropertyKeys.CHAMP_OBJECT_TYPE.toString())) { - query.hasLabel((String) queryParams.get(ChampObject.ReservedPropertyKeys.CHAMP_OBJECT_TYPE.toString())); - } - - final Iterator objIter = new Iterator () { - - private ChampObject next; - - - @Override - public boolean hasNext() { - while (query.hasNext()) { - try { - next = getChampformer().unmarshallObject(query.next()); - return true; - } catch (ChampUnmarshallingException e) { - LOGGER.warn("Failed to unmarshall tinkerpop vertex during query, returning partial results", e); - } - } - - tryCommit(); //Danger ahead if this iterator is not completely consumed - //then the transaction cache will hold stale values - - next = null; - return false; - } - - @Override - public ChampObject next() { - if (next == null) throw new NoSuchElementException(); - - return next; - } - }; - - return StreamSupport.stream(Spliterators.spliteratorUnknownSize( - objIter, Spliterator.ORDERED | Spliterator.NONNULL), false); - } - - @Override - public Optional retrieveObject(Object key) throws ChampUnmarshallingException { - if (isShutdown()) throw new IllegalStateException("Cannot use ChampAPI after calling shutdown()"); - - final Iterator vertices = getGraph().vertices(key); - final Optional optionalObject; - - if (!vertices.hasNext()) optionalObject = Optional.empty(); - else optionalObject = Optional.of(getChampformer().unmarshallObject(vertices.next())); - - tryCommit(); - - return optionalObject; - } - - @Override - public Stream retrieveRelationships(ChampObject source) throws ChampUnmarshallingException, ChampObjectNotExistsException { - if (isShutdown()) throw new IllegalStateException("Cannot use ChampAPI after calling shutdown()"); - - final Vertex sourceVertex; - - try { - sourceVertex = getGraph().vertices(source.getKey().get()).next(); - } catch (NoSuchElementException e) { - tryRollback(); - - throw new ChampObjectNotExistsException(); - } - - final Iterator edges = sourceVertex.edges(Direction.BOTH); - final Iterator relIter = new Iterator () { - - private ChampRelationship next; - - @Override - public boolean hasNext() { - while (edges.hasNext()) { - try { - next = getChampformer().unmarshallRelationship(edges.next()); - return true; - } catch (ChampUnmarshallingException e) { - LOGGER.warn("Failed to unmarshall tinkerpop edge during query, returning partial results", e); - } - } - - tryCommit();//Danger ahead if this iterator is not completely - //consumed, then the transaction cache will be stale - next = null; - return false; - } - - @Override - public ChampRelationship next() { - if (next == null) throw new NoSuchElementException(); - - return next; - } - }; - - return StreamSupport.stream(Spliterators.spliteratorUnknownSize( - relIter, Spliterator.ORDERED | Spliterator.NONNULL), false); - } - - @Override - public ChampObject doStoreObject(ChampObject object) throws ChampMarshallingException, ChampObjectNotExistsException { - - try { - final Vertex vertex = writeVertex(object); - - tryCommit(); - - return ChampObject.create() - .from(object) - .withKey(vertex.id()) - .build(); - - } catch (ChampObjectNotExistsException e) { - tryRollback(); - - throw e; - } - } - - @Override - public ChampObject doReplaceObject(ChampObject object) throws ChampMarshallingException, ChampObjectNotExistsException { - - try { - final Vertex vertex = replaceVertex(object); - - tryCommit(); - - return ChampObject.create() - .from(object) - .withKey(vertex.id()) - .build(); - - } catch (ChampObjectNotExistsException e) { - tryRollback(); - - throw e; - } - } - - public void executeDeleteObject(Object key) throws ChampObjectNotExistsException { - if (isShutdown()) throw new IllegalStateException("Cannot use ChampAPI after calling shutdown()"); - - final Iterator vertex = getGraph().vertices(key); - - if (!vertex.hasNext()) { - tryRollback(); - - throw new ChampObjectNotExistsException(); - } - - vertex.next().remove(); - - tryCommit(); - } - - @Override - public ChampRelationship doStoreRelationship(ChampRelationship relationship) - throws ChampUnmarshallingException, ChampObjectNotExistsException, ChampRelationshipNotExistsException, ChampMarshallingException { - - try { - final Edge edge = writeEdge(relationship); - - tryCommit(); - - return getChampformer().unmarshallRelationship(edge); - - } catch (ChampObjectNotExistsException | ChampRelationshipNotExistsException | ChampUnmarshallingException | ChampMarshallingException e) { - tryRollback(); - - throw e; - } - } - - @Override - public ChampRelationship doReplaceRelationship(ChampRelationship relationship) - throws ChampUnmarshallingException, ChampRelationshipNotExistsException, ChampMarshallingException { - - try { - final Edge edge = replaceEdge(relationship); - - tryCommit(); - - return getChampformer().unmarshallRelationship(edge); - - } catch ( ChampRelationshipNotExistsException | ChampUnmarshallingException | ChampMarshallingException e) { - tryRollback(); - - throw e; - } - } - - @Override - public Stream queryRelationships(Map queryParams) { - if (isShutdown()) throw new IllegalStateException("Cannot use ChampAPI after calling shutdown()"); - - //If they provided the relationship key, do this the quick way rather than creating a traversal - if (queryParams.containsKey(ChampRelationship.ReservedPropertyKeys.CHAMP_RELATIONSHIP_KEY.toString())) { - try { - final Optional relationship = retrieveRelationship(queryParams.get(ChampRelationship.ReservedPropertyKeys.CHAMP_RELATIONSHIP_KEY.toString())); - - if (relationship.isPresent()) return Stream.of(relationship.get()); - else return Stream.empty(); - } catch (ChampUnmarshallingException e) { - LOGGER.warn("Failed to unmarshall relationship", e); - return Stream.empty(); - } - } - - final GraphTraversal query = getGraph().traversal().E(); - - for (Entry filter : queryParams.entrySet()) { - if (filter.getKey().equals(ChampRelationship.ReservedPropertyKeys.CHAMP_RELATIONSHIP_TYPE.toString())) { - continue; //Add the label last for performance reasons - } else { - query.has(filter.getKey(), filter.getValue()); - } - } - - if (queryParams.containsKey(ChampRelationship.ReservedPropertyKeys.CHAMP_RELATIONSHIP_TYPE.toString())) { - query.hasLabel((String) queryParams.get(ChampRelationship.ReservedPropertyKeys.CHAMP_RELATIONSHIP_TYPE.toString())); - } - - final Iterator objIter = new Iterator () { - - private ChampRelationship next; - - - @Override - public boolean hasNext() { - while (query.hasNext()) { - try { - next = getChampformer().unmarshallRelationship(query.next()); - return true; - } catch (ChampUnmarshallingException e) { - LOGGER.warn("Failed to unmarshall tinkerpop vertex during query, returning partial results", e); - } - } - - tryCommit(); //Danger ahead if this iterator is not completely - //consumed, then the transaction cache will be stale - - next = null; - return false; - } - - @Override - public ChampRelationship next() { - if (next == null) throw new NoSuchElementException(); - - return next; - } - }; - - return StreamSupport.stream(Spliterators.spliteratorUnknownSize( - objIter, Spliterator.ORDERED | Spliterator.NONNULL), false); - } - - @Override - public Optional retrieveRelationship(Object key) - throws ChampUnmarshallingException { - if (isShutdown()) throw new IllegalStateException("Cannot use ChampAPI after calling shutdown()"); - - final Iterator edge = getGraph().edges(key); - final Optional optionalRelationship; - - if (!edge.hasNext()) optionalRelationship = Optional.empty(); - else optionalRelationship = Optional.of(getChampformer().unmarshallRelationship(edge.next())); - - tryCommit(); - - return optionalRelationship; - } - - public void executeDeleteRelationship(ChampRelationship relationship) throws ChampRelationshipNotExistsException { - if (isShutdown()) throw new IllegalStateException("Cannot use ChampAPI after calling shutdown()"); - if (!relationship.getKey().isPresent()) throw new IllegalArgumentException("Key must be provided when deleting a relationship"); - - final Iterator edge = getGraph().edges(relationship.getKey().get()); - - if (!edge.hasNext()) { - tryRollback(); - - throw new ChampRelationshipNotExistsException(); - } - - edge.next().remove(); - - tryCommit(); - } - - @Override - public ChampPartition doStorePartition(ChampPartition submittedPartition) throws ChampMarshallingException, ChampObjectNotExistsException, ChampRelationshipNotExistsException { - if (isShutdown()) throw new IllegalStateException("Cannot use ChampAPI after calling shutdown()"); - - try { - final HashMap objectsWithKeys = new HashMap (); - final CreateChampPartitionable storedPartition = ChampPartition.create(); - - for (ChampObject champObject : submittedPartition.getChampObjects()) { - final Vertex vertex = writeVertex(champObject); - objectsWithKeys.put(champObject, ChampObject.create() - .from(champObject) - .withKey(vertex.id()) - .build()); - } - - for (ChampRelationship champRelationship : submittedPartition.getChampRelationships()) { - if (!objectsWithKeys.containsKey(champRelationship.getSource())) { - final Vertex vertex = writeVertex(champRelationship.getSource()); - - objectsWithKeys.put(champRelationship.getSource(), ChampObject.create() - .from(champRelationship.getSource()) - .withKey(vertex.id()) - .build()); - } - - if (!objectsWithKeys.containsKey(champRelationship.getTarget())) { - final Vertex vertex = writeVertex(champRelationship.getTarget()); - - objectsWithKeys.put(champRelationship.getTarget(), ChampObject.create() - .from(champRelationship.getTarget()) - .withKey(vertex.id()) - .build()); - } - - final ChampRelationship.Builder relWithKeysBuilder = new ChampRelationship.Builder(objectsWithKeys.get(champRelationship.getSource()), - objectsWithKeys.get(champRelationship.getTarget()), - champRelationship.getType()); - - if (champRelationship.getKey().isPresent()) relWithKeysBuilder.key(champRelationship.getKey().get()); - - relWithKeysBuilder.properties(champRelationship.getProperties()); - - final Edge edge = writeEdge(relWithKeysBuilder.build()); - - storedPartition.withRelationship(ChampRelationship.create() - .from(champRelationship) - .withKey(edge.id()) - .build()); - } - - for (ChampObject object : objectsWithKeys.values()) { - storedPartition.withObject(object); - } - - tryCommit(); - - return storedPartition.build(); - - } catch (ChampObjectNotExistsException | ChampMarshallingException e) { - tryRollback(); - - throw e; - } - } - - public void executeDeletePartition(ChampPartition graph) { - if (isShutdown()) throw new IllegalStateException("Cannot use ChampAPI after calling shutdown()"); - - for (ChampObject champObject : graph.getChampObjects()) { - try { - final Object vertexId = champObject.getKey().get(); - final Iterator vertex = getGraph().vertices(vertexId); - - if (vertex.hasNext()) { - vertex.next().remove(); - } - } catch (NoSuchElementException e) { - tryRollback(); - - throw new IllegalArgumentException("Must pass a key to delete an object"); - } - } - - for (ChampRelationship champRelationship : graph.getChampRelationships()) { - try { - final Iterator edge = getGraph().edges(champRelationship.getKey().get()); - - if (edge.hasNext()) { - edge.next().remove(); - } - } catch (NoSuchElementException e) { - tryRollback(); - - throw new IllegalArgumentException("Must pass a key to delete a relationship"); - } - } - - tryCommit(); - - } - - @Override - public void shutdown() { - - if (isShutdown.compareAndSet(false, true)) { - super.shutdown(); - try { - getGraph().close(); - } catch (Throwable t) { - LOGGER.error("Exception while shutting down graph", t); - } - } else { - throw new IllegalStateException("Cannot call shutdown() after shutdown() was already initiated"); - } - } - - @Override - public void storeSchema(ChampSchema schema) throws ChampSchemaViolationException { - if (isShutdown()) throw new IllegalStateException("Cannot call storeSchema() after shutdown has been initiated"); - - if (getGraph().features().graph().variables().supportsVariables()) { - try { - getGraph().variables().set("schema", getObjectMapper().writeValueAsBytes(schema)); - } catch (JsonProcessingException e) { - throw new RuntimeException(e); - } - } else { - super.storeSchema(schema); - } - } - - @Override - public ChampSchema retrieveSchema() { - if (isShutdown()) throw new IllegalStateException("Cannot call retrieveSchema() after shutdown has been initiated"); - - if (getGraph().features().graph().variables().supportsVariables()) { - final Optional schema = getGraph().variables().get("schema"); - - if (schema.isPresent()) { - try { - return getObjectMapper().readValue(schema.get(), ChampSchema.class); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - } - - return super.retrieveSchema(); - } - - @Override - public void deleteSchema() { - if (isShutdown()) throw new IllegalStateException("Cannot call deleteSchema() after shutdown has been initiated"); - - if (getGraph().features().graph().variables().supportsVariables()) { - getGraph().variables().remove("schema"); - } else { - super.deleteSchema(); - } - } -} diff --git a/src/main/java/org/onap/aai/champ/graph/impl/AbstractValidatingChampGraph.java b/src/main/java/org/onap/aai/champ/graph/impl/AbstractValidatingChampGraph.java deleted file mode 100644 index a4161df..0000000 --- a/src/main/java/org/onap/aai/champ/graph/impl/AbstractValidatingChampGraph.java +++ /dev/null @@ -1,176 +0,0 @@ -/** - * ============LICENSE_START========================================== - * org.onap.aai - * =================================================================== - * Copyright © 2017 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017 Amdocs - * =================================================================== - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END============================================ - * ECOMP is a trademark and service mark of AT&T Intellectual Property. - */ -package org.onap.aai.champ.graph.impl; - -import java.util.Map; -import java.util.Optional; - -import org.onap.aai.champ.ChampGraph; -import org.onap.aai.champ.event.AbstractLoggingChampGraph; -import org.onap.aai.champ.event.ChampEvent; -import org.onap.aai.champ.event.ChampEvent.ChampOperation; -import org.onap.aai.champ.exceptions.ChampMarshallingException; -import org.onap.aai.champ.exceptions.ChampObjectNotExistsException; -import org.onap.aai.champ.exceptions.ChampRelationshipNotExistsException; -import org.onap.aai.champ.exceptions.ChampSchemaViolationException; -import org.onap.aai.champ.exceptions.ChampUnmarshallingException; -import org.onap.aai.champ.graph.impl.TitanChampGraphImpl.Builder; -import org.onap.aai.champ.model.ChampObject; -import org.onap.aai.champ.model.ChampObjectConstraint; -import org.onap.aai.champ.model.ChampPartition; -import org.onap.aai.champ.model.ChampRelationship; -import org.onap.aai.champ.model.ChampRelationshipConstraint; -import org.onap.aai.champ.model.ChampSchema; -import org.onap.aai.champ.schema.ChampSchemaEnforcer; - -public abstract class AbstractValidatingChampGraph extends AbstractLoggingChampGraph { - - private ChampSchema schema = ChampSchema.emptySchema(); - - protected abstract ChampSchemaEnforcer getSchemaEnforcer(); - protected abstract boolean isShutdown(); - - protected abstract ChampObject doReplaceObject(ChampObject object) throws ChampMarshallingException, ChampObjectNotExistsException; - protected abstract ChampObject doStoreObject(ChampObject object) throws ChampMarshallingException, ChampObjectNotExistsException; - protected abstract ChampRelationship doReplaceRelationship(ChampRelationship relationship) throws ChampUnmarshallingException, ChampRelationshipNotExistsException, ChampMarshallingException; - protected abstract ChampRelationship doStoreRelationship(ChampRelationship relationship) throws ChampUnmarshallingException, ChampObjectNotExistsException, ChampRelationshipNotExistsException, ChampMarshallingException; - protected abstract ChampPartition doStorePartition(ChampPartition partition) throws ChampRelationshipNotExistsException, ChampMarshallingException, ChampObjectNotExistsException; - - protected AbstractValidatingChampGraph(Map properties) { - super(properties); - } - - public ChampObject executeStoreObject(ChampObject object) - throws ChampMarshallingException, ChampSchemaViolationException, ChampObjectNotExistsException { - if (isShutdown()) throw new IllegalStateException("Cannot use ChampAPI after calling shutdown()"); - - validate(object); - - return doStoreObject(object); - } - - public ChampObject executeReplaceObject(ChampObject object) - throws ChampMarshallingException, ChampSchemaViolationException, ChampObjectNotExistsException { - if (isShutdown()) throw new IllegalStateException("Cannot use ChampAPI after calling shutdown()"); - - validate(object); - - return doReplaceObject(object); - } - - public ChampRelationship executeStoreRelationship(ChampRelationship relationship) - throws ChampUnmarshallingException, ChampMarshallingException, ChampObjectNotExistsException, ChampSchemaViolationException, ChampRelationshipNotExistsException { - if (isShutdown()) throw new IllegalStateException("Cannot use ChampAPI after calling shutdown()"); - - validate(relationship); - - return doStoreRelationship(relationship); - } - - public ChampRelationship executeReplaceRelationship(ChampRelationship relationship) - throws ChampUnmarshallingException, ChampMarshallingException, ChampSchemaViolationException, ChampRelationshipNotExistsException { - if (isShutdown()) throw new IllegalStateException("Cannot use ChampAPI after calling shutdown()"); - - validate(relationship); - - return doReplaceRelationship(relationship); - } - - public ChampPartition executeStorePartition(ChampPartition partition) throws ChampSchemaViolationException, ChampRelationshipNotExistsException, ChampMarshallingException, ChampObjectNotExistsException { - if (isShutdown()) throw new IllegalStateException("Cannot use ChampAPI after calling shutdown()"); - - validate(partition); - - return doStorePartition(partition); - } - - protected void validate(ChampObject object) throws ChampSchemaViolationException { - final Optional objectConstraint = retrieveSchema().getObjectConstraint(object.getType()); - - if (objectConstraint.isPresent()) getSchemaEnforcer().validate(object, objectConstraint.get()); - } - - protected void validate(ChampRelationship relationship) throws ChampSchemaViolationException { - final ChampSchema graphSchema = retrieveSchema(); - final Optional relationshipConstraint = graphSchema.getRelationshipConstraint(relationship.getType()); - final Optional sourceObjConstraint = graphSchema.getObjectConstraint(relationship.getSource().getType()); - final Optional targetObjConstraint = graphSchema.getObjectConstraint(relationship.getTarget().getType()); - - if (relationshipConstraint.isPresent()) getSchemaEnforcer().validate(relationship, relationshipConstraint.get()); - if (sourceObjConstraint.isPresent()) getSchemaEnforcer().validate(relationship.getSource(), sourceObjConstraint.get()); - if (targetObjConstraint.isPresent()) getSchemaEnforcer().validate(relationship.getTarget(), targetObjConstraint.get()); - } - - protected void validate(ChampPartition partition) throws ChampSchemaViolationException { - for (ChampObject object : partition.getChampObjects()) { - validate(object); - } - - for (ChampRelationship relationship : partition.getChampRelationships()) { - validate(relationship); - } - } - - @Override - public void storeSchema(ChampSchema schema) throws ChampSchemaViolationException { - if (isShutdown()) throw new IllegalStateException("Cannot call storeSchema() after shutdown has been initiated"); - - this.schema = schema; - } - - @Override - public ChampSchema retrieveSchema() { - if (isShutdown()) throw new IllegalStateException("Cannot call retrieveSchema() after shutdown has been initiated"); - - return schema; - } - - @Override - public void updateSchema(ChampObjectConstraint objectConstraint) throws ChampSchemaViolationException { - if (isShutdown()) throw new IllegalStateException("Cannot call updateSchema() after shutdown has been initiated"); - - final ChampSchema currentSchema = retrieveSchema(); - final ChampSchema updatedSchema = new ChampSchema.Builder(currentSchema) - .constraint(objectConstraint) - .build(); - - storeSchema(updatedSchema); - } - - @Override - public void updateSchema(ChampRelationshipConstraint relationshipConstraint) throws ChampSchemaViolationException { - if (isShutdown()) throw new IllegalStateException("Cannot call updateSchema() after shutdown has been initiated"); - - final ChampSchema currentSchema = retrieveSchema(); - final ChampSchema updatedSchema = new ChampSchema.Builder(currentSchema) - .constraint(relationshipConstraint) - .build(); - - storeSchema(updatedSchema); - } - - @Override - public void deleteSchema() { - if (isShutdown()) throw new IllegalStateException("Cannot call deleteSchema() after shutdown has been initiated"); - this.schema = ChampSchema.emptySchema(); - } -} diff --git a/src/main/java/org/onap/aai/champ/graph/impl/TitanChampGraphImpl.java b/src/main/java/org/onap/aai/champ/graph/impl/TitanChampGraphImpl.java deleted file mode 100644 index 73f24a5..0000000 --- a/src/main/java/org/onap/aai/champ/graph/impl/TitanChampGraphImpl.java +++ /dev/null @@ -1,458 +0,0 @@ -/** - * ============LICENSE_START========================================== - * org.onap.aai - * =================================================================== - * Copyright © 2017 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017 Amdocs - * =================================================================== - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END============================================ - * ECOMP is a trademark and service mark of AT&T Intellectual Property. - */ -package org.onap.aai.champ.graph.impl; - -import com.thinkaurelius.titan.core.Cardinality; -import com.thinkaurelius.titan.core.EdgeLabel; -import com.thinkaurelius.titan.core.PropertyKey; -import com.thinkaurelius.titan.core.SchemaViolationException; -import com.thinkaurelius.titan.core.TitanEdge; -import com.thinkaurelius.titan.core.TitanFactory; -import com.thinkaurelius.titan.core.TitanGraph; -import com.thinkaurelius.titan.core.TitanVertex; -import com.thinkaurelius.titan.core.schema.SchemaAction; -import com.thinkaurelius.titan.core.schema.SchemaStatus; -import com.thinkaurelius.titan.core.schema.TitanGraphIndex; -import com.thinkaurelius.titan.core.schema.TitanManagement; -import com.thinkaurelius.titan.graphdb.database.management.ManagementSystem; -import org.apache.tinkerpop.gremlin.structure.Edge; -import org.apache.tinkerpop.gremlin.structure.Vertex; -import org.onap.aai.champ.ChampCapabilities; -import org.onap.aai.champ.exceptions.ChampIndexNotExistsException; -import org.onap.aai.champ.exceptions.ChampSchemaViolationException; -import org.onap.aai.champ.model.ChampCardinality; -import org.onap.aai.champ.model.ChampObject; -import org.onap.aai.champ.model.ChampObjectConstraint; -import org.onap.aai.champ.model.ChampObjectIndex; -import org.onap.aai.champ.model.ChampPropertyConstraint; -import org.onap.aai.champ.model.ChampRelationship; -import org.onap.aai.champ.model.ChampRelationshipConstraint; -import org.onap.aai.champ.model.ChampRelationshipIndex; -import org.onap.aai.champ.model.ChampSchema; -import org.onap.aai.champ.schema.ChampSchemaEnforcer; -import org.onap.aai.champ.schema.DefaultChampSchemaEnforcer; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.time.temporal.ChronoUnit; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import java.util.Map.Entry; -import java.util.NoSuchElementException; -import java.util.Optional; -import java.util.Spliterator; -import java.util.Spliterators; -import java.util.concurrent.ExecutionException; -import java.util.stream.Stream; -import java.util.stream.StreamSupport; - -public final class TitanChampGraphImpl extends AbstractTinkerpopChampGraph { - - private static final Logger LOGGER = LoggerFactory.getLogger(TitanChampGraphImpl.class); - private static final String TITAN_CASSANDRA_KEYSPACE = "storage.cassandra.keyspace"; - private static final String TITAN_HBASE_TABLE = "storage.hbase.table"; - private static final ChampSchemaEnforcer SCHEMA_ENFORCER = new DefaultChampSchemaEnforcer(); - private static final int REGISTER_OBJECT_INDEX_TIMEOUT_SECS = 30; - - private static final ChampCapabilities CAPABILITIES = new ChampCapabilities() { - - @Override - public boolean canDeleteObjectIndices() { - return false; - } - - @Override - public boolean canDeleteRelationshipIndices() { - return false; - } - }; - - private final TitanGraph graph; - - private TitanChampGraphImpl(Builder builder) { - super(builder.graphConfiguration); - final TitanFactory.Builder titanGraphBuilder = TitanFactory.build(); - - for (Entry titanGraphProperty : builder.graphConfiguration.entrySet()) { - titanGraphBuilder.set(titanGraphProperty.getKey(), titanGraphProperty.getValue()); - } - - final Object storageBackend = builder.graphConfiguration.get("storage.backend"); - - if ("cassandra".equals(storageBackend) || "cassandrathrift".equals(storageBackend) - || "astyanax".equals(storageBackend) || "embeddedcassandra".equals(storageBackend)) { - titanGraphBuilder.set(TITAN_CASSANDRA_KEYSPACE, builder.graphName); - } else if ("hbase".equals(storageBackend)) { - titanGraphBuilder.set(TITAN_HBASE_TABLE, builder.graphName); - } else if ("berkleyje".equals(storageBackend)) { - throw new RuntimeException("storage.backend=berkleyje cannot handle multiple graphs on a single DB, not usable"); - } else if ("inmemory".equals(storageBackend)) { - } else { - throw new RuntimeException("Unknown storage.backend=" + storageBackend); - } - - this.graph = titanGraphBuilder.open(); - } - - public static class Builder { - private final String graphName; - - private final Map graphConfiguration = new HashMap (); - - public Builder(String graphName) { - this.graphName = graphName; - } - - public Builder properties(Map properties) { - if (properties.containsKey(TITAN_CASSANDRA_KEYSPACE)) - throw new IllegalArgumentException("Cannot use path " + TITAN_CASSANDRA_KEYSPACE - + " in initial configuration - this path is used" - + " to specify graph names"); - - this.graphConfiguration.putAll(properties); - return this; - } - - public Builder property(String path, Object value) { - if (path.equals(TITAN_CASSANDRA_KEYSPACE)) - throw new IllegalArgumentException("Cannot use path " + TITAN_CASSANDRA_KEYSPACE - + " in initial configuration - this path is used" - + " to specify graph names"); - graphConfiguration.put(path, value); - return this; - } - - public TitanChampGraphImpl build() { - return new TitanChampGraphImpl(this); - } - } - - @Override - protected TitanGraph getGraph() { - return graph; - } - - @Override - protected ChampSchemaEnforcer getSchemaEnforcer() { - return SCHEMA_ENFORCER; - } - - public void executeStoreObjectIndex(ChampObjectIndex index) { - if (isShutdown()) throw new IllegalStateException("Cannot call storeObjectIndex() after shutdown has been initiated"); - - final TitanGraph graph = getGraph(); - final TitanManagement createIndexMgmt = graph.openManagement(); - final PropertyKey pk = createIndexMgmt.getOrCreatePropertyKey(index.getField().getName()); - - if (createIndexMgmt.getGraphIndex(index.getName()) != null) { - createIndexMgmt.rollback(); - return; //Ignore, index already exists - } - - createIndexMgmt.buildIndex(index.getName(), Vertex.class).addKey(pk).buildCompositeIndex(); - - createIndexMgmt.commit(); - graph.tx().commit(); - - awaitIndexCreation(index.getName()); - } - - @Override - public Optional retrieveObjectIndex(String indexName) { - if (isShutdown()) throw new IllegalStateException("Cannot call retrieveObjectIndex() after shutdown has been initiated"); - - final TitanManagement retrieveIndexMgmt = getGraph().openManagement(); - final TitanGraphIndex index = retrieveIndexMgmt.getGraphIndex(indexName); - - if (index == null) return Optional.empty(); - if (index.getIndexedElement() != TitanVertex.class) return Optional.empty(); - - return Optional.of(ChampObjectIndex.create() - .ofName(indexName) - .onType(ChampObject.ReservedTypes.ANY.toString()) - .forField(index.getFieldKeys()[0].name()) - .build()); - } - - @Override - public Stream retrieveObjectIndices() { - if (isShutdown()) throw new IllegalStateException("Cannot call retrieveObjectIndices() after shutdown has been initiated"); - - final TitanManagement createIndexMgmt = getGraph().openManagement(); - final Iterator indices = createIndexMgmt.getGraphIndexes(Vertex.class).iterator(); - - final Iterator objIter = new Iterator () { - - private ChampObjectIndex next; - - @Override - public boolean hasNext() { - if (indices.hasNext()) { - final TitanGraphIndex index = indices.next(); - - next = ChampObjectIndex.create() - .ofName(index.name()) - .onType(ChampObject.ReservedTypes.ANY.toString()) - .forField(index.getFieldKeys()[0].name()) - .build(); - return true; - } - - next = null; - return false; - } - - @Override - public ChampObjectIndex next() { - if (next == null) throw new NoSuchElementException(); - - return next; - } - }; - - return StreamSupport.stream(Spliterators.spliteratorUnknownSize( - objIter, Spliterator.ORDERED | Spliterator.NONNULL), false); - } - - public void executeDeleteObjectIndex(String indexName) throws ChampIndexNotExistsException { - if (isShutdown()) throw new IllegalStateException("Cannot call deleteObjectIndex() after shutdown has been initiated"); - - throw new UnsupportedOperationException("Cannot delete indices using the TitanChampImpl"); - } - - public void executeStoreRelationshipIndex(ChampRelationshipIndex index) { - if (isShutdown()) throw new IllegalStateException("Cannot call storeRelationshipIndex() after shutdown has been initiated"); - - final TitanGraph graph = getGraph(); - final TitanManagement createIndexMgmt = graph.openManagement(); - final PropertyKey pk = createIndexMgmt.getOrCreatePropertyKey(index.getField().getName()); - - if (createIndexMgmt.getGraphIndex(index.getName()) != null) return; //Ignore, index already exists - createIndexMgmt.buildIndex(index.getName(), Edge.class).addKey(pk).buildCompositeIndex(); - - createIndexMgmt.commit(); - graph.tx().commit(); - - awaitIndexCreation(index.getName()); - } - - @Override - public Optional retrieveRelationshipIndex(String indexName) { - if (isShutdown()) throw new IllegalStateException("Cannot call retrieveRelationshipIndex() after shutdown has been initiated"); - - final TitanManagement retrieveIndexMgmt = getGraph().openManagement(); - final TitanGraphIndex index = retrieveIndexMgmt.getGraphIndex(indexName); - - if (index == null) return Optional.empty(); - if (index.getIndexedElement() != TitanEdge.class) return Optional.empty(); - - return Optional.of(ChampRelationshipIndex.create() - .ofName(indexName) - .onType(ChampObject.ReservedTypes.ANY.toString()) - .forField(index.getFieldKeys()[0].name()) - .build()); - } - - @Override - public Stream retrieveRelationshipIndices() { - if (isShutdown()) throw new IllegalStateException("Cannot call retrieveRelationshipIndices() after shutdown has been initiated"); - - final TitanManagement createIndexMgmt = getGraph().openManagement(); - final Iterator indices = createIndexMgmt.getGraphIndexes(Edge.class).iterator(); - - final Iterator objIter = new Iterator () { - - private ChampRelationshipIndex next; - - @Override - public boolean hasNext() { - if (indices.hasNext()) { - final TitanGraphIndex index = indices.next(); - - next = ChampRelationshipIndex.create() - .ofName(index.name()) - .onType(ChampRelationship.ReservedTypes.ANY.toString()) - .forField(index.getFieldKeys()[0].name()) - .build(); - return true; - } - - next = null; - return false; - } - - @Override - public ChampRelationshipIndex next() { - if (next == null) throw new NoSuchElementException(); - - return next; - } - }; - - return StreamSupport.stream(Spliterators.spliteratorUnknownSize( - objIter, Spliterator.ORDERED | Spliterator.NONNULL), false); - } - - public void executeDeleteRelationshipIndex(String indexName) throws ChampIndexNotExistsException { - if (isShutdown()) throw new IllegalStateException("Cannot call deleteRelationshipIndex() after shutdown has been initiated"); - - throw new UnsupportedOperationException("Cannot delete indices using the TitanChampImpl"); - } - - private Cardinality getTitanCardinality(ChampCardinality cardinality) { - switch (cardinality) { - case LIST: - return Cardinality.LIST; - case SET: - return Cardinality.SET; - case SINGLE: - return Cardinality.SINGLE; - default: - throw new RuntimeException("Unknown ChampCardinality " + cardinality); - } - } - - private void awaitIndexCreation(String indexName) { - //Wait for the index to become available - try { - if (ManagementSystem.awaitGraphIndexStatus(graph, indexName) - .status(SchemaStatus.ENABLED) - .timeout(1, ChronoUnit.SECONDS) - .call() - .getSucceeded()) { - return; //Empty graphs immediately ENABLE indices - } - - if (!ManagementSystem.awaitGraphIndexStatus(graph, indexName) - .status(SchemaStatus.REGISTERED) - .timeout(REGISTER_OBJECT_INDEX_TIMEOUT_SECS, ChronoUnit.SECONDS) - .call() - .getSucceeded()) { - LOGGER.warn("Object index was created, but timed out while waiting for it to be registered"); - return; - } - } catch (InterruptedException e) { - LOGGER.warn("Interrupted while waiting for object index creation status"); - return; - } - - //Reindex the existing data - - try { - final TitanManagement updateIndexMgmt = graph.openManagement(); - updateIndexMgmt.updateIndex(updateIndexMgmt.getGraphIndex(indexName),SchemaAction.REINDEX).get(); - updateIndexMgmt.commit(); - } catch (InterruptedException e) { - LOGGER.warn("Interrupted while reindexing for object index"); - return; - } catch (ExecutionException e) { - LOGGER.warn("Exception occurred during reindexing procedure for creating object index " + indexName, e); - } - - try { - ManagementSystem.awaitGraphIndexStatus(graph, indexName) - .status(SchemaStatus.ENABLED) - .timeout(10, ChronoUnit.MINUTES) - .call(); - } catch (InterruptedException e) { - LOGGER.warn("Interrupted while waiting for index to transition to ENABLED state"); - return; - } - } - - @Override - public ChampCapabilities capabilities() { - return CAPABILITIES; - } - - @Override - public void storeSchema(ChampSchema schema) throws ChampSchemaViolationException { - if (isShutdown()) throw new IllegalStateException("Cannot call storeSchema() after shutdown has been initiated"); - - final ChampSchema currentSchema = retrieveSchema(); - final TitanManagement mgmt = getGraph().openManagement(); - - try { - for (ChampObjectConstraint objConstraint : schema.getObjectConstraints().values()) { - for (ChampPropertyConstraint propConstraint : objConstraint.getPropertyConstraints()) { - final Optional currentObjConstraint = currentSchema.getObjectConstraint(objConstraint.getType()); - - if (currentObjConstraint.isPresent()) { - final Optional currentPropConstraint = currentObjConstraint.get().getPropertyConstraint(propConstraint.getField().getName()); - - if (currentPropConstraint.isPresent() && currentPropConstraint.get().compareTo(propConstraint) != 0) { - throw new ChampSchemaViolationException("Cannot update already existing property on object type " + objConstraint.getType() + ": " + propConstraint); - } - } - - final String newPropertyKeyName = propConstraint.getField().getName(); - - if (mgmt.getPropertyKey(newPropertyKeyName) != null) continue; //Check Titan to see if another node created this property key - - mgmt.makePropertyKey(newPropertyKeyName) - .dataType(propConstraint.getField().getJavaType()) - .cardinality(getTitanCardinality(propConstraint.getCardinality())) - .make(); - } - } - - for (ChampRelationshipConstraint relConstraint : schema.getRelationshipConstraints().values()) { - - final Optional currentRelConstraint = currentSchema.getRelationshipConstraint(relConstraint.getType()); - - for (ChampPropertyConstraint propConstraint : relConstraint.getPropertyConstraints()) { - - if (currentRelConstraint.isPresent()) { - final Optional currentPropConstraint = currentRelConstraint.get().getPropertyConstraint(propConstraint.getField().getName()); - - if (currentPropConstraint.isPresent() && currentPropConstraint.get().compareTo(propConstraint) != 0) { - throw new ChampSchemaViolationException("Cannot update already existing property on relationship type " + relConstraint.getType()); - } - } - - final String newPropertyKeyName = propConstraint.getField().getName(); - - if (mgmt.getPropertyKey(newPropertyKeyName) != null) continue; //Check Titan to see if another node created this property key - - mgmt.makePropertyKey(newPropertyKeyName) - .dataType(propConstraint.getField().getJavaType()) - .cardinality(getTitanCardinality(propConstraint.getCardinality())) - .make(); - } - - final EdgeLabel edgeLabel = mgmt.getEdgeLabel(relConstraint.getType()); - - if (edgeLabel != null) mgmt.makeEdgeLabel(relConstraint.getType()) - .directed() - .make(); - } - - mgmt.commit(); - - super.storeSchema(schema); - } catch (SchemaViolationException | ChampSchemaViolationException e) { - mgmt.rollback(); - throw new ChampSchemaViolationException(e); - } - } -} diff --git a/src/main/java/org/onap/aai/champ/model/ChampObject.java b/src/main/java/org/onap/aai/champ/model/ChampObject.java deleted file mode 100644 index 9593ef1..0000000 --- a/src/main/java/org/onap/aai/champ/model/ChampObject.java +++ /dev/null @@ -1,239 +0,0 @@ -/** - * ============LICENSE_START========================================== - * org.onap.aai - * =================================================================== - * Copyright © 2017 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017 Amdocs - * =================================================================== - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END============================================ - * ECOMP is a trademark and service mark of AT&T Intellectual Property. - */ -package org.onap.aai.champ.model; - -import java.util.HashMap; -import java.util.Map; -import java.util.Map.Entry; - -import org.onap.aai.champ.model.fluent.object.CreateChampObjectable; -import org.onap.aai.champ.model.fluent.object.impl.CreateChampObjectableImpl; - -import java.util.Optional; - -import com.fasterxml.jackson.annotation.JsonIgnore; -import com.fasterxml.jackson.annotation.JsonProperty; - -public final class ChampObject implements ChampElement { - - private final String type; - private final Optional key; - private final Map properties; - - public static CreateChampObjectable create() { - return new CreateChampObjectableImpl(); - } - - private ChampObject() { - throw new RuntimeException("Attempted to call private AAIObject() constructor"); - } //Not instantiable - - private ChampObject(Builder builder) { - this.type = builder.type; - this.key = builder.key; - this.properties = builder.properties; - } - - @SuppressWarnings("unchecked") - public Optional getProperty(String key) { - if (!properties.containsKey(key)) return Optional.empty(); - - return Optional.of((T) properties.get(key)); - } - - public String getType() { return type; } - - @JsonIgnore - public Optional getKey() { return key; } - public Map getProperties() { return properties; } - - @JsonProperty("key") - public Object getKeyValue() { - return key.orElse(""); - - } - - public static class Builder { - private final String type; - private final Map properties = new HashMap (); - - private Optional key = Optional.empty(); - - public Builder(String type) { - if (type == null) throw new IllegalArgumentException("Type cannot be null"); - - this.type = type; - } - - public Builder(ChampObject object) { - type = object.getType(); - key = object.getKey(); - properties(object.getProperties()); - } - - public Builder key(Object key) { - if (key == null) throw new IllegalArgumentException("Key cannot be set to null"); - - this.key = Optional.of(key); - return this; - } - - public Builder property(String key, Object value) { - if (key == null) throw new IllegalArgumentException("Property key cannot be null"); - if (value == null) throw new IllegalArgumentException("Property value cannot be null"); - - if (ReservedPropertyKeys.contains(key)) throw new IllegalArgumentException("Property key " + key + " is reserved"); - - properties.put(key, value); - return this; - } - - public Builder properties(Map properties) { - for (Entry property : properties.entrySet()) { - property(property.getKey(), property.getValue()); - } - - return this; - } - - public ChampObject build() { - return new ChampObject(this); - } - } - - @Override - public boolean equals(Object object) { - if (this == object) return true; - - if (object instanceof ChampObject) { - final ChampObject champObj = (ChampObject) object; - - if (getKey().isPresent() && champObj.getKey().isPresent()) { - - if (getKey().get().equals(champObj.getKey().get())) return true; - - } else if (!getKey().isPresent() && !champObj.getKey().isPresent()) { - if (getType().equals(champObj.getType()) && - getProperties().equals(champObj.getProperties())) return true; - } - } - - return false; - } - - @Override - public int hashCode() { - if (getKey().isPresent()) return getKey().get().hashCode(); - - final int returnValue = 31 * (getType().hashCode() + getProperties().hashCode()); - return returnValue; - } - - @Override - public String toString() { - return "{key: " + (getKey().isPresent() ? getKey().get() : "") - + ", type: " + getType() - + ", properties: " + getProperties() + "}"; - } - - public enum ReservedPropertyKeys { - CHAMP_OBJECT_TYPE ("aai_node_type"), - CHAMP_OBJECT_KEY ("key"); - - private final String text; - - private ReservedPropertyKeys(final String text) { - this.text = text; - } - - @Override - public String toString() { - return text; - } - - public static boolean contains(String key) { - for (ReservedPropertyKeys choice : ReservedPropertyKeys.values()) { - if (choice.toString().equals(key)) return true; - } - - return false; - } - } - - public enum IgnoreOnReadPropertyKeys { - CHAMP_IMPORT_ASSIGNED_ID ("importAssignedId"); - - private final String text; - - private IgnoreOnReadPropertyKeys(final String text) { - this.text = text; - } - - @Override - public String toString() { - return text; - } - - public static boolean contains(String key) { - for (IgnoreOnReadPropertyKeys choice : IgnoreOnReadPropertyKeys.values()) { - if (choice.toString().equals(key)) return true; - } - - return false; - } - } - - public enum ReservedTypes { - ANY ("ANY"); - - private final String text; - - private ReservedTypes(final String text) { - this.text = text; - } - - @Override - public String toString() { - return text; - } - } - - @Override - public boolean isObject() { - return true; - } - - @Override - public ChampObject asObject() { - return this; - } - - @Override - public boolean isRelationship() { - return false; - } - - @Override - public ChampRelationship asRelationship() { - throw new UnsupportedOperationException("Cannot call asRelationship() on ChampObject"); - } -} diff --git a/src/test/java/org/onap/aai/champ/concurrency/ConcurrencyTest.java b/src/test/java/org/onap/aai/champ/concurrency/ConcurrencyTest.java deleted file mode 100644 index f33266d..0000000 --- a/src/test/java/org/onap/aai/champ/concurrency/ConcurrencyTest.java +++ /dev/null @@ -1,72 +0,0 @@ -/** - * ============LICENSE_START========================================== - * org.onap.aai - * =================================================================== - * Copyright © 2017 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017 Amdocs - * =================================================================== - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END============================================ - * ECOMP is a trademark and service mark of AT&T Intellectual Property. - */ -package org.onap.aai.champ.concurrency; - -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; - -import org.junit.Test; -import org.onap.aai.champ.ChampAPI; -import org.onap.aai.champ.ChampGraph; -import org.onap.aai.champ.core.ChampObjectTest; -import org.onap.aai.champ.core.ChampRelationshipTest; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class ConcurrencyTest { - - private static final Logger LOGGER = LoggerFactory.getLogger(ConcurrencyTest.class); - - @Test - public void runConcurrentTest() { - for (ChampGraph.Type apiType : ChampGraph.Type.values()) { - final ChampAPI api = ChampAPI.Factory.newInstance(apiType); - runConcurrencyTest(api); - api.shutdown(); - } - } - - private void runConcurrencyTest(ChampAPI api) { - final int numThreads = 10; - final ExecutorService es = Executors.newFixedThreadPool(numThreads); - - for (int i = 0; i < numThreads * 2; i++) { - es.submit(new Runnable() { - @Override - public void run() { - final ChampGraph graph = api.getGraph(ConcurrencyTest.class.getSimpleName()); - ChampObjectTest.testChampObjectCrud(graph); - ChampRelationshipTest.testChampRelationshipCrud(graph); - } - }); - } - - try { - es.shutdown(); - es.awaitTermination(60, TimeUnit.SECONDS); - } catch (InterruptedException e) { - LOGGER.warn("Interrupted while waiting for concurrency test to finish", e); - return; - } - } -} diff --git a/src/test/java/org/onap/aai/champ/core/BaseChampAPITest.java b/src/test/java/org/onap/aai/champ/core/BaseChampAPITest.java deleted file mode 100644 index af737bc..0000000 --- a/src/test/java/org/onap/aai/champ/core/BaseChampAPITest.java +++ /dev/null @@ -1,50 +0,0 @@ -/** - * ============LICENSE_START========================================== - * org.onap.aai - * =================================================================== - * Copyright © 2017 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017 Amdocs - * =================================================================== - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END============================================ - * ECOMP is a trademark and service mark of AT&T Intellectual Property. - */ -package org.onap.aai.champ.core; - -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class BaseChampAPITest { - - private static final Logger LOGGER = LoggerFactory.getLogger(BaseChampAPITest.class); - - protected static void cleanUp(String graphName) { - LOGGER.warn("cleanUp is disabled for unit tests - you can enable it by commenting out the code below this log message, please don't commit it though"); - - /* - LOGGER.debug("Cleaning up graph {}", graphName); - - try { - final TitanGraph graph = TitanFactory.build() - .set("storage.backend", "cassandra") - .set("storage.hostname", "localhost") - .set("storage.cassandra.keyspace", graphName) - .open(); - graph.close(); - TitanCleanup.clear(graph); - } catch (IllegalArgumentException e) { - LOGGER.warn("Could not clean up graph - unable to instantiate"); - } - */ - } -} diff --git a/src/test/java/org/onap/aai/champ/core/ChampAPITest.java b/src/test/java/org/onap/aai/champ/core/ChampAPITest.java deleted file mode 100644 index d0097d9..0000000 --- a/src/test/java/org/onap/aai/champ/core/ChampAPITest.java +++ /dev/null @@ -1,239 +0,0 @@ -/** - * ============LICENSE_START========================================== - * org.onap.aai - * =================================================================== - * Copyright © 2017 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017 Amdocs - * =================================================================== - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END============================================ - * ECOMP is a trademark and service mark of AT&T Intellectual Property. - */ -package org.onap.aai.champ.core; - -import static org.junit.Assert.assertTrue; - -import org.junit.Test; -import org.onap.aai.champ.ChampAPI; -import org.onap.aai.champ.ChampGraph; -import org.onap.aai.champ.model.ChampObjectConstraint; -import org.onap.aai.champ.model.ChampRelationshipConstraint; - -public class ChampAPITest { - - @Test - public void testChampAPIInstantiation() { - - for (ChampGraph.Type type : ChampGraph.Type.values()) { - - final ChampAPI api = ChampAPI.Factory.newInstance(type); - - assertTrue(type == ChampGraph.Type.valueOf(type.name())); - assertTrue(api.getType() == type); - - api.getGraph("foo"); - api.shutdown(); - - try { - api.getGraph("foo"); - throw new AssertionError("Able to call getGraph(String name) after shutdown()"); - } catch (IllegalStateException e) { - //Expected - } - } - } - - @Test - public void testChampGraphInstantiation() throws Exception { - for (ChampGraph.Type type : ChampGraph.Type.values()) { - final ChampGraph graph = ChampGraph.Factory.newInstance(type, "foo"); - - graph.shutdown(); - - try { - graph.deleteObject(null); - throw new AssertionError("Able to call API method after shutdown was initiated"); - } catch (IllegalStateException e) { - //Expected - } - - try { - graph.deleteObjectIndex(null); - throw new AssertionError("Able to call API method after shutdown was initiated"); - } catch (IllegalStateException e) { - //Expected - } - - try { - graph.deletePartition(null); - throw new AssertionError("Able to call API method after shutdown was initiated"); - } catch (IllegalStateException e) { - //Expected - } - - try { - graph.deleteRelationship(null); - throw new AssertionError("Able to call API method after shutdown was initiated"); - } catch (IllegalStateException e) { - //Expected - } - - try { - graph.deleteRelationshipIndex(null); - throw new AssertionError("Able to call API method after shutdown was initiated"); - } catch (IllegalStateException e) { - //Expected - } - - try { - graph.deleteSchema(); - throw new AssertionError("Able to call API method after shutdown was initiated"); - } catch (IllegalStateException e) { - //Expected - } - - try { - graph.queryObjects(null); - throw new AssertionError("Able to call API method after shutdown was initiated"); - } catch (IllegalStateException e) { - //Expected - } - - try { - graph.queryRelationships(null); - throw new AssertionError("Able to call API method after shutdown was initiated"); - } catch (IllegalStateException e) { - //Expected - } - - try { - graph.retrieveObject(null); - throw new AssertionError("Able to call API method after shutdown was initiated"); - } catch (IllegalStateException e) { - //Expected - } - - try { - graph.retrieveObjectIndex(null); - throw new AssertionError("Able to call API method after shutdown was initiated"); - } catch (IllegalStateException e) { - //Expected - } - - try { - graph.retrieveObjectIndices(); - throw new AssertionError("Able to call API method after shutdown was initiated"); - } catch (IllegalStateException e) { - //Expected - } - - try { - graph.retrieveRelationship(null); - throw new AssertionError("Able to call API method after shutdown was initiated"); - } catch (IllegalStateException e) { - //Expected - } - - try { - graph.retrieveRelationshipIndex(null); - throw new AssertionError("Able to call API method after shutdown was initiated"); - } catch (IllegalStateException e) { - //Expected - } - - try { - graph.retrieveRelationshipIndices(); - throw new AssertionError("Able to call API method after shutdown was initiated"); - } catch (IllegalStateException e) { - //Expected - } - - try { - graph.retrieveRelationships(null); - throw new AssertionError("Able to call API method after shutdown was initiated"); - } catch (IllegalStateException e) { - //Expected - } - - try { - graph.retrieveSchema(); - throw new AssertionError("Able to call API method after shutdown was initiated"); - } catch (IllegalStateException e) { - //Expected - } - - try { - graph.storeObject(null); - throw new AssertionError("Able to call API method after shutdown was initiated"); - } catch (IllegalStateException e) { - //Expected - } - - try { - graph.storeObjectIndex(null); - throw new AssertionError("Able to call API method after shutdown was initiated"); - } catch (IllegalStateException e) { - //Expected - } - - try { - graph.storePartition(null); - throw new AssertionError("Able to call API method after shutdown was initiated"); - } catch (IllegalStateException e) { - //Expected - } - - try { - graph.storeRelationship(null); - throw new AssertionError("Able to call API method after shutdown was initiated"); - } catch (IllegalStateException e) { - //Expected - } - - try { - graph.storeRelationshipIndex(null); - throw new AssertionError("Able to call API method after shutdown was initiated"); - } catch (IllegalStateException e) { - //Expected - } - - try { - graph.storeSchema(null); - throw new AssertionError("Able to call API method after shutdown was initiated"); - } catch (IllegalStateException e) { - //Expected - } - - try { - graph.updateSchema(new ChampObjectConstraint.Builder("").build()); - throw new AssertionError("Able to call API method after shutdown was initiated"); - } catch (IllegalStateException e) { - //Expected - } - - try { - graph.updateSchema(new ChampRelationshipConstraint.Builder("").build()); - throw new AssertionError("Able to call API method after shutdown was initiated"); - } catch (IllegalStateException e) { - //Expected - } - - try { - graph.shutdown(); - throw new AssertionError("Able to call API method after shutdown was initiated"); - } catch (IllegalStateException e) { - //Expected - } - } - } -} diff --git a/src/test/java/org/onap/aai/champ/core/ChampObjectTest.java b/src/test/java/org/onap/aai/champ/core/ChampObjectTest.java deleted file mode 100644 index fea167b..0000000 --- a/src/test/java/org/onap/aai/champ/core/ChampObjectTest.java +++ /dev/null @@ -1,331 +0,0 @@ -/** - * ============LICENSE_START========================================== - * org.onap.aai - * =================================================================== - * Copyright © 2017 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017 Amdocs - * =================================================================== - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END============================================ - * ECOMP is a trademark and service mark of AT&T Intellectual Property. - */ -package org.onap.aai.champ.core; - -import static org.junit.Assert.assertTrue; - -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Optional; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import org.junit.Test; -import org.onap.aai.champ.ChampAPI; -import org.onap.aai.champ.ChampGraph; -import org.onap.aai.champ.exceptions.ChampMarshallingException; -import org.onap.aai.champ.exceptions.ChampObjectNotExistsException; -import org.onap.aai.champ.exceptions.ChampSchemaViolationException; -import org.onap.aai.champ.exceptions.ChampUnmarshallingException; -import org.onap.aai.champ.model.ChampCardinality; -import org.onap.aai.champ.model.ChampField; -import org.onap.aai.champ.model.ChampObject; -import org.onap.aai.champ.model.ChampSchema; - -public class ChampObjectTest extends BaseChampAPITest { - - @Test - public void testHashCode() { - final ChampObject foo1 = ChampObject.create() - .ofType("foo") - .withoutKey() - .withProperty("property", "value") - .withProperty("prop", 1) - .build(); - - final ChampObject foo2 = ChampObject.create() - .ofType("foo") - .withoutKey() - .withProperty("property", "value") - .withProperty("prop", 1) - .build(); - - final ChampObject foo1Copy = ChampObject.create() - .from(foo1) - .withoutKey() - .build(); - - final ChampObject foo2Copy = ChampObject.create() - .from(foo2) - .withoutKey() - .build(); - - assertTrue(foo1.hashCode() == foo2.hashCode()); - assertTrue(foo1.hashCode() == foo1.hashCode()); - assertTrue(foo2.hashCode() == foo2.hashCode()); - assertTrue(foo1.hashCode() == foo1Copy.hashCode()); - assertTrue(foo2.hashCode() == foo2Copy.hashCode()); - - assertTrue(Collections.singleton(foo1).contains(foo1)); - assertTrue(Collections.singleton(foo1).contains(foo1Copy)); - } - - @Test - public void runTest() { - for (ChampGraph.Type apiType : ChampGraph.Type.values()) { - final String graphName = ChampObjectTest.class.getSimpleName(); - switch (apiType) { - case TITAN: - cleanUp(graphName); - break; - default: - break; - } - - final ChampAPI api = ChampAPI.Factory.newInstance(apiType); - ChampObjectTest.testChampObjectCrud(api.getGraph(graphName)); - testChampObjectReservedProperties(api.getGraph(graphName)); - api.shutdown(); - } - } - - public static void testChampObjectCrud(ChampGraph graph) { - final ChampObject bookooObject = ChampObject.create() - .ofType("foo") - .withoutKey() - .withProperty("property1", "value1") - .withProperty("integer", 1) - .withProperty("long", 1L) - .withProperty("double", 1.2) - .withProperty("float", 2.3F) - .withProperty("string", "foo") - .withProperty("boolean", true) - .withProperty("list", Collections.singletonList("list")) - .withProperty("set", Collections.singleton("set")) - .build(); - - final ChampObject storedBookooObject; - - try { - - graph.storeSchema(ChampSchema.create() - .withObjectConstraint() - .onType("foo") - .withPropertyConstraint() - .onField("list") - .ofType(ChampField.Type.STRING) - .cardinality(ChampCardinality.LIST) - .optional() - .build() - .withPropertyConstraint() - .onField("set") - .ofType(ChampField.Type.STRING) - .cardinality(ChampCardinality.SET) - .optional() - .build() - .build() - .build()); - - storedBookooObject = graph.storeObject(bookooObject); - - assertTrue(storedBookooObject.getProperty("property1").get().equals("value1")); - assertTrue(storedBookooObject.getProperty("integer").get().equals(1)); - assertTrue(storedBookooObject.getProperty("long").get().equals(1L)); - assertTrue(storedBookooObject.getProperty("double").get().equals(1.2)); - assertTrue(storedBookooObject.getProperty("float").get().equals(2.3F)); - assertTrue(storedBookooObject.getProperty("string").get().equals("foo")); - assertTrue(storedBookooObject.getProperty("boolean").get().equals(true)); - assertTrue(storedBookooObject.getProperty("list").get().equals(Collections.singletonList("list"))); - assertTrue(storedBookooObject.getProperty("set").get().equals(Collections.singleton("set"))); - - final Optional retrievedBookooObject = graph.retrieveObject(storedBookooObject.getKey().get()); - final Stream emptyStream = graph.queryObjects(new HashMap () {{ - put(ChampObject.ReservedPropertyKeys.CHAMP_OBJECT_TYPE.toString(), "foo"); - put("long", 2L); - }}); - - assertTrue(emptyStream.limit(1).count() == 0); - - final Stream oneStream = graph.queryObjects(new HashMap () {{ - put(ChampObject.ReservedPropertyKeys.CHAMP_OBJECT_TYPE.toString(), "foo"); - put("long", 1L); - }}); - final List oneObject = oneStream.limit(2).collect(Collectors.toList()); - assertTrue(oneObject.size() == 1); - assertTrue(oneObject.get(0).equals(storedBookooObject)); - - final List queryByKey = graph.queryObjects(Collections.singletonMap(ChampObject.ReservedPropertyKeys.CHAMP_OBJECT_KEY.toString(), storedBookooObject.getKey().get())) - .limit(2) - .collect(Collectors.toList()); - - assertTrue(queryByKey.size() == 1); - assertTrue(queryByKey.get(0).equals(storedBookooObject)); - - if (!retrievedBookooObject.isPresent()) throw new AssertionError("Failed to retrieve stored object " + bookooObject); - if (!storedBookooObject.equals(retrievedBookooObject.get())) throw new AssertionError("Retrieved object does not equal stored object"); - - final ChampObject updatedBookoo = graph.storeObject(ChampObject.create() - .from(storedBookooObject) - .withKey(storedBookooObject.getKey().get()) - .withProperty("long", 2L) - .build()); - - final Optional retrievedUpdBookooObject = graph.retrieveObject(updatedBookoo.getKey().get()); - - assertTrue(updatedBookoo.getProperty("property1").get().equals("value1")); - assertTrue(updatedBookoo.getProperty("integer").get().equals(1)); - assertTrue(updatedBookoo.getProperty("long").get().equals(2L)); - assertTrue(updatedBookoo.getProperty("double").get().equals(1.2)); - assertTrue(updatedBookoo.getProperty("float").get().equals(2.3F)); - assertTrue(updatedBookoo.getProperty("string").get().equals("foo")); - assertTrue(updatedBookoo.getProperty("boolean").get().equals(true)); - assertTrue(updatedBookoo.getProperty("list").get().equals(Collections.singletonList("list"))); - assertTrue(updatedBookoo.getProperty("set").get().equals(Collections.singleton("set"))); - - if (!retrievedUpdBookooObject.isPresent()) throw new AssertionError("Failed to retrieve stored object " + bookooObject); - if (!updatedBookoo.equals(retrievedUpdBookooObject.get())) throw new AssertionError("Retrieved object does not equal stored object"); - - //validate the replaceObject method - final ChampObject replacedBookoo = graph.replaceObject(ChampObject.create() - .ofType("foo") - .withKey(storedBookooObject.getKey().get()) - .withProperty("property1", "value2") - .withProperty("list", Collections.singletonList("list")) - .withProperty("set", Collections.singleton("set")) - .build()); - - final Optional retrievedReplacedBookooObject = graph.retrieveObject(replacedBookoo.getKey().get()); - - assertTrue(replacedBookoo.getProperties().size()==3); - assertTrue(replacedBookoo.getProperty("property1").get().equals("value2")); - assertTrue(replacedBookoo.getProperty("list").get().equals(Collections.singletonList("list"))); - assertTrue(replacedBookoo.getProperty("set").get().equals(Collections.singleton("set"))); - - - if (!retrievedReplacedBookooObject.isPresent()) throw new AssertionError("Failed to retrieve stored object " + replacedBookoo); - if (!replacedBookoo.equals(retrievedReplacedBookooObject.get())) throw new AssertionError("Retrieved object does not equal stored object"); - - - - - - graph.deleteObject(storedBookooObject.getKey().get()); - if (graph.retrieveObject(storedBookooObject.getKey().get()).isPresent()) throw new AssertionError("Object not successfully deleted"); - - assertTrue(graph.queryObjects(Collections.emptyMap()).count() == 0); - assertTrue(graph.queryRelationships(Collections.emptyMap()).count() == 0); - } catch (ChampSchemaViolationException e) { - throw new AssertionError("Schema mismatch while storing object", e); - } catch (ChampMarshallingException e) { - throw new AssertionError("Marshalling exception while storing object", e); - } catch (ChampUnmarshallingException e) { - throw new AssertionError("Unmarshalling exception while retrieving object", e); - }catch (ChampObjectNotExistsException e) { - throw new AssertionError("Missing object on delete/update", e); - } - - try { - graph.deleteObject(storedBookooObject.getKey().get()); - throw new AssertionError("Delete succeeded when it should have failed"); - } catch (ChampObjectNotExistsException e) { - //Expected - } - - try { - graph.storeObject(ChampObject.create() - .ofType("foo") - .withKey("non-existent object key") - .build()); - throw new AssertionError("Expected ChampObjectNotExistsException but object was successfully stored"); - } catch (ChampObjectNotExistsException e) { - //Expected - } catch (ChampMarshallingException e) { - throw new AssertionError(e); - } catch (ChampSchemaViolationException e) { - throw new AssertionError(e); - } - - try { - // validate the replaceObject method when Object key is not passed - graph.replaceObject( - ChampObject.create().ofType("foo").withoutKey().withProperty("property1", "value2").build()); - } catch (ChampObjectNotExistsException e) { - // Expected - } catch (ChampMarshallingException e) { - throw new AssertionError(e); - } catch (ChampSchemaViolationException e) { - throw new AssertionError(e); - } - - } - - public void testChampObjectReservedProperties(ChampGraph graph) { - - for (ChampObject.ReservedPropertyKeys key : ChampObject.ReservedPropertyKeys.values()) { - try { - ChampObject.create() - .ofType(ChampObject.ReservedTypes.ANY.toString()) - .withoutKey() - .withProperty(key.toString(), "") - .build(); - throw new AssertionError("Allowed reserved property key to be used during object creation"); - } catch (IllegalArgumentException e) { - //Expected - } - } - } - - @Test - public void testFluentObjectCreation() { - final Object value1 = new Object(); - final String value2 = "value2"; - final float value3 = 0.0f; - - final ChampObject champObject1 = ChampObject.create() - .ofType("foo") - .withoutKey() - .withProperty("key1", value1) - .withProperty("key2", value2) - .withProperty("key3", value3) - .build(); - - assertTrue(champObject1.getKey().equals(Optional.empty())); - assertTrue(champObject1.getKey().isPresent() == false); - assertTrue(champObject1.getType().equals("foo")); - assertTrue(champObject1.getProperty("key1").get() instanceof Object); - assertTrue(champObject1.getProperty("key1").get().equals(value1)); - assertTrue(champObject1.getProperty("key2").get() instanceof String); - assertTrue(champObject1.getProperty("key2").get().equals(value2)); - assertTrue(champObject1.getProperty("key3").get() instanceof Float); - assertTrue(champObject1.getProperty("key3").get().equals(value3)); - - final ChampObject champObject2 = ChampObject.create() - .ofType("foo") - .withKey(1) - .withProperty("key1", value1) - .withProperty("key2", value2) - .withProperty("key3", value3) - .build(); - - assertTrue(champObject2.getType().equals("foo")); - assertTrue(champObject2.getKey().isPresent() == true); - assertTrue(champObject2.getKey().get() instanceof Integer); - assertTrue(champObject2.getKey().get().equals(1)); - assertTrue(champObject2.getProperty("key1").get() instanceof Object); - assertTrue(champObject2.getProperty("key1").get().equals(value1)); - assertTrue(champObject2.getProperty("key2").get() instanceof String); - assertTrue(champObject2.getProperty("key2").get().equals(value2)); - assertTrue(champObject2.getProperty("key3").get() instanceof Float); - assertTrue(champObject2.getProperty("key3").get().equals(value3)); - } -} diff --git a/src/test/java/org/onap/aai/champ/core/ChampPartitionTest.java b/src/test/java/org/onap/aai/champ/core/ChampPartitionTest.java deleted file mode 100644 index 42894f4..0000000 --- a/src/test/java/org/onap/aai/champ/core/ChampPartitionTest.java +++ /dev/null @@ -1,195 +0,0 @@ -/** - * ============LICENSE_START========================================== - * org.onap.aai - * =================================================================== - * Copyright © 2017 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017 Amdocs - * =================================================================== - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END============================================ - * ECOMP is a trademark and service mark of AT&T Intellectual Property. - */ -package org.onap.aai.champ.core; - -import static org.junit.Assert.assertTrue; - -import java.util.Collections; -import java.util.Optional; - -import org.junit.Test; -import org.onap.aai.champ.ChampAPI; -import org.onap.aai.champ.ChampGraph; -import org.onap.aai.champ.exceptions.ChampMarshallingException; -import org.onap.aai.champ.exceptions.ChampObjectNotExistsException; -import org.onap.aai.champ.exceptions.ChampRelationshipNotExistsException; -import org.onap.aai.champ.exceptions.ChampSchemaViolationException; -import org.onap.aai.champ.exceptions.ChampUnmarshallingException; -import org.onap.aai.champ.model.ChampObject; -import org.onap.aai.champ.model.ChampPartition; -import org.onap.aai.champ.model.ChampRelationship; - -public class ChampPartitionTest extends BaseChampAPITest { - - @Test - public void runTests() { - for (ChampGraph.Type apiType : ChampGraph.Type.values()) { - final ChampAPI api = ChampAPI.Factory.newInstance(apiType); - final String graphName = ChampPartitionTest.class.getSimpleName(); - - switch (apiType) { - case IN_MEMORY: - break; - case TITAN: - cleanUp(graphName); - break; - default: - break; - } - - ChampPartitionTest.testChampPartitionCrud(api.getGraph(graphName)); - api.shutdown(); - } - } - - @Test - public void testHashCode() { - - final ChampObject foo = ChampObject.create() - .ofType("foo") - .withoutKey() - .build(); - final ChampObject bar = ChampObject.create() - .ofType("bar") - .withoutKey() - .build(); - final ChampRelationship baz = ChampRelationship.create() - .ofType("baz") - .withoutKey() - .withSource() - .from(foo) - .build() - .withTarget() - .from(bar) - .build() - .build(); - - final ChampPartition partition = ChampPartition.create() - .withObject(foo) - .withObject(bar) - .withRelationship(baz) - .build(); - - assertTrue(partition.getChampObjects().contains(foo)); - assertTrue(partition.getChampObjects().contains(bar)); - assertTrue(partition.getChampRelationships().contains(baz)); - } - - @Test - public void testBuilder() { - final ChampObject foo = new ChampObject.Builder("foo").build(); - final ChampObject bar = new ChampObject.Builder("bar").build(); - final ChampRelationship uses = new ChampRelationship.Builder(foo, bar, "uses") - .build(); - final ChampPartition a = new ChampPartition.Builder() - .object(foo) - .objects(Collections.singleton(bar)) - .relationship(uses) - .relationships(Collections.singleton(uses)) - .build(); - assertTrue(a.getChampObjects().size() == 2); - assertTrue(a.getChampObjects().contains(foo)); - assertTrue(a.getChampObjects().contains(bar)); - - assertTrue(a.getChampRelationships().size() == 1); - assertTrue(a.getChampRelationships().contains(uses)); - } - - public static void testChampPartitionCrud(ChampGraph graph) { - - final ChampObject foo = ChampObject.create() - .ofType("foo") - .withoutKey() - .withProperty("prop1", "value1") - .build(); - final ChampObject bar = ChampObject.create() - .ofType("bar") - .withoutKey() - .withProperty("prop2", "value2") - .build(); - - final ChampRelationship baz = ChampRelationship.create() - .ofType("baz") - .withoutKey() - .withSource() - .from(foo) - .build() - .withTarget() - .from(bar) - .build() - .withProperty("prop3", "value3") - .build(); - - final ChampPartition partition = ChampPartition.create() - .withObject(foo) - .withObject(bar) - .withRelationship(baz) - .build(); - - assertTrue(partition.getIncidentRelationships(foo).contains(baz)); - assertTrue(partition.getIncidentRelationships(bar).contains(baz)); - assertTrue(partition.getIncidentRelationshipsByType(foo).get("baz").contains(baz)); - - try { - final ChampPartition storedPartition = graph.storePartition(partition); - - ChampPartitionTest.retrievePartitionElements(graph, storedPartition, true); - - graph.deletePartition(storedPartition); - - ChampPartitionTest.retrievePartitionElements(graph, storedPartition, false); - - } catch (ChampMarshallingException e) { - throw new AssertionError(e); - } catch (ChampObjectNotExistsException e) { - throw new AssertionError(e); - } catch (ChampSchemaViolationException e) { - throw new AssertionError(e); - } catch (ChampRelationshipNotExistsException e) { - throw new AssertionError(e); - } - } - - private static void retrievePartitionElements(ChampGraph graph, ChampPartition partition, boolean expectFound) { - for (ChampObject object : partition.getChampObjects()) { - try { - final Optional retrievedObject = graph.retrieveObject(object.getKey().get()); - - if (!expectFound && retrievedObject.isPresent()) throw new AssertionError("Expected object to not be found, but it was found"); - if (expectFound && !retrievedObject.isPresent()) throw new AssertionError("Expected object to be found, but it was not found"); - } catch (ChampUnmarshallingException e) { - throw new AssertionError(e); - } - } - - for (ChampRelationship relationship : partition.getChampRelationships()) { - try { - final Optional retrievedRelationship = graph.retrieveRelationship(relationship.getKey().get()); - - if (!expectFound && retrievedRelationship.isPresent()) throw new AssertionError("Expected relationship to not be found, but it was found"); - if (expectFound && !retrievedRelationship.isPresent()) throw new AssertionError("Expected relationship to be found, but it was not found"); - } catch (ChampUnmarshallingException e) { - throw new AssertionError(e); - } - } - } -} diff --git a/src/test/java/org/onap/aai/champ/core/ChampRelationshipIndexTest.java b/src/test/java/org/onap/aai/champ/core/ChampRelationshipIndexTest.java deleted file mode 100644 index 58c7d79..0000000 --- a/src/test/java/org/onap/aai/champ/core/ChampRelationshipIndexTest.java +++ /dev/null @@ -1,175 +0,0 @@ -/** - * ============LICENSE_START========================================== - * org.onap.aai - * =================================================================== - * Copyright © 2017 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017 Amdocs - * =================================================================== - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END============================================ - * ECOMP is a trademark and service mark of AT&T Intellectual Property. - */ -package org.onap.aai.champ.core; - -import static org.junit.Assert.assertTrue; - -import java.util.Collection; -import java.util.Optional; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import org.junit.Test; -import org.onap.aai.champ.ChampAPI; -import org.onap.aai.champ.ChampGraph; -import org.onap.aai.champ.exceptions.ChampIndexNotExistsException; -import org.onap.aai.champ.exceptions.ChampMarshallingException; -import org.onap.aai.champ.exceptions.ChampObjectNotExistsException; -import org.onap.aai.champ.exceptions.ChampRelationshipNotExistsException; -import org.onap.aai.champ.exceptions.ChampSchemaViolationException; -import org.onap.aai.champ.exceptions.ChampUnmarshallingException; -import org.onap.aai.champ.model.ChampField; -import org.onap.aai.champ.model.ChampRelationship; -import org.onap.aai.champ.model.ChampRelationshipIndex; - -public class ChampRelationshipIndexTest extends BaseChampAPITest { - - @Test - public void runTest() { - for (ChampGraph.Type apiType : ChampGraph.Type.values()) { - final String graphName = ChampRelationshipIndexTest.class.getSimpleName(); - - switch (apiType) { - case IN_MEMORY: - break; - case TITAN: - cleanUp(graphName); - break; - default: - break; - } - - final ChampAPI api = ChampAPI.Factory.newInstance(apiType); - testChampRelationshipIndexCrud(api.getGraph(graphName)); - api.shutdown(); - } - } - - private void testChampRelationshipIndexCrud(ChampGraph graph) { - - final ChampField relationshipField = new ChampField.Builder("propertyName").build(); - final ChampRelationshipIndex relationshipIndex = new ChampRelationshipIndex.Builder("fooEdgeIndex", "foo", relationshipField).build(); - - //Test on an empty graph - testChampRelationshipIndexStorage(graph, relationshipIndex); - testChampRelationshipIndexDelete(graph, relationshipIndex); - - //Test with existing data in graph - try { - graph.storeRelationship(ChampRelationship.create() - .ofType("uses") - .withoutKey() - .withSource() - .ofType("foo") - .withoutKey() - .build() - .withTarget() - .ofType("bar") - .withoutKey() - .build() - .build()); - testChampRelationshipIndexStorage(graph, relationshipIndex); - testChampRelationshipIndexDelete(graph, relationshipIndex); - } catch (ChampMarshallingException e) { - throw new AssertionError(e); - } catch (ChampSchemaViolationException e) { - throw new AssertionError(e); - } catch (ChampObjectNotExistsException e) { - throw new AssertionError(e); - } catch (ChampRelationshipNotExistsException e) { - throw new AssertionError(e); - } catch (ChampUnmarshallingException e) { - throw new AssertionError(e); - } - } - - private void testChampRelationshipIndexDelete(ChampGraph graph, ChampRelationshipIndex relationshipIndex) { - - if (!graph.capabilities().canDeleteRelationshipIndices()) { - try { - graph.deleteRelationshipIndex("someindex"); - throw new AssertionError("Graph claims it doesn't support relationship index delete, but it failed to throw UnsupportedOperationException"); - } catch (UnsupportedOperationException e) { - //Expected - } catch (ChampIndexNotExistsException e) { - throw new AssertionError("Graph claims it doesn't support relationship index delete, but it failed to throw UnsupportedOperationException"); - } - } else { - try { - graph.deleteRelationshipIndex(relationshipIndex.getName()); - - final Optional retrieveRelationshipIndex = graph.retrieveRelationshipIndex(relationshipIndex.getName()); - - if (retrieveRelationshipIndex.isPresent()) throw new AssertionError("Retrieve relationship index after deleting it"); - - final Stream relationshipIndices = graph.retrieveRelationshipIndices(); - final Collection allRelationshipIndices = relationshipIndices.collect(Collectors.toList()); - - if (allRelationshipIndices.contains(relationshipIndex)) throw new AssertionError("Retrieve all relationship indices contains previously deleted index"); - if (allRelationshipIndices.size() != 0) throw new AssertionError("Wrong number of relationship indices returned by retrieve all indices"); - } catch (ChampIndexNotExistsException e) { - throw new AssertionError(e); - } - - try { - graph.deleteRelationshipIndex(relationshipIndex.getName()); - throw new AssertionError("Failed to throw exception on non-existent object index"); - } catch (ChampIndexNotExistsException e) { - //Expected - } - } - } - - private void testChampRelationshipIndexStorage(ChampGraph graph, ChampRelationshipIndex relationshipIndex) { - - graph.storeRelationshipIndex(relationshipIndex); - graph.storeRelationshipIndex(relationshipIndex); //Test storing duplicate relationship index - - assertTrue(!graph.retrieveObjectIndex(relationshipIndex.getName()).isPresent()); //Make sure this wasn't stored as an object index - - final Optional retrieveRelationshipIndex = graph.retrieveRelationshipIndex(relationshipIndex.getName()); - - if (!retrieveRelationshipIndex.isPresent()) throw new AssertionError("Failed to retrieve relationship index after storing it"); - if (!relationshipIndex.equals(retrieveRelationshipIndex.get())) throw new AssertionError("Non-equal relationship index returned from API after storing it"); - - final Stream relationshipIndices = graph.retrieveRelationshipIndices(); - final Collection allRelationshipIndices = relationshipIndices.collect(Collectors.toList()); - - if (!allRelationshipIndices.contains(relationshipIndex)) throw new AssertionError("Retrieve all relationship indices did not return previously stored relationship index"); - if (allRelationshipIndices.size() != 1) throw new AssertionError("Wrong number of relationship indices returned by retrieve all indices"); - - assertTrue(!graph.retrieveRelationshipIndex("nonExistentIndexName").isPresent()); - } - - @Test - public void testFluentRelationshipIndexCreation() { - final ChampRelationshipIndex relationshipIndex = ChampRelationshipIndex.create() - .ofName("fooNameIndex") - .onType("foo") - .forField("name") - .build(); - - assertTrue(relationshipIndex.getName().equals("fooNameIndex")); - assertTrue(relationshipIndex.getType().equals("foo")); - assertTrue(relationshipIndex.getField().getName().equals("name")); - } -} diff --git a/src/test/java/org/onap/aai/champ/core/ChampRelationshipTest.java b/src/test/java/org/onap/aai/champ/core/ChampRelationshipTest.java deleted file mode 100644 index 3d95268..0000000 --- a/src/test/java/org/onap/aai/champ/core/ChampRelationshipTest.java +++ /dev/null @@ -1,261 +0,0 @@ -/** - * ============LICENSE_START========================================== - * org.onap.aai - * =================================================================== - * Copyright © 2017 AT&T Intellectual Property. All rights reserved. - * Copyright © 2017 Amdocs - * =================================================================== - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END============================================ - * ECOMP is a trademark and service mark of AT&T Intellectual Property. - */ -package org.onap.aai.champ.core; - -import static org.junit.Assert.assertTrue; - -import java.util.Collections; -import java.util.Optional; -import java.util.stream.Collectors; - -import org.junit.Test; -import org.onap.aai.champ.ChampAPI; -import org.onap.aai.champ.ChampGraph; -import org.onap.aai.champ.exceptions.ChampMarshallingException; -import org.onap.aai.champ.exceptions.ChampObjectNotExistsException; -import org.onap.aai.champ.exceptions.ChampRelationshipNotExistsException; -import org.onap.aai.champ.exceptions.ChampSchemaViolationException; -import org.onap.aai.champ.exceptions.ChampUnmarshallingException; -import org.onap.aai.champ.model.ChampObject; -import org.onap.aai.champ.model.ChampRelationship; -import org.onap.aai.champ.model.ChampRelationship.ReservedPropertyKeys; -import org.onap.aai.champ.model.ChampRelationship.ReservedTypes; - -public class ChampRelationshipTest extends BaseChampAPITest { - - @Test - public void runTest() { - for (ChampGraph.Type apiType : ChampGraph.Type.values()) { - final String graphName = ChampRelationshipTest.class.getSimpleName(); - - switch (apiType) { - case IN_MEMORY: - break; - case TITAN: - cleanUp(graphName); - break; - default: - break; - } - - final ChampAPI api = ChampAPI.Factory.newInstance(apiType); - ChampRelationshipTest.testChampRelationshipCrud(api.getGraph(graphName)); - api.shutdown(); - } - } - - public static void testChampRelationshipCrud(ChampGraph graph) { - final ChampObject source = ChampObject.create() - .ofType("foo") - .withoutKey() - .withProperty("property1", "value1") - .build(); - - final ChampObject target = ChampObject.create() - .ofType("foo") - .withoutKey() - .build(); - - try { - final ChampObject storedSource = graph.storeObject(source); - final ChampObject storedTarget = graph.storeObject(target); - - final ChampRelationship relationship = new ChampRelationship.Builder(storedSource, storedTarget, "relationship") - .property("property-1", "value-1") - .property("property-2", 3) - .build(); - - final ChampRelationship storedRelationship = graph.storeRelationship(relationship); - final Optional retrievedRelationship = graph.retrieveRelationship(storedRelationship.getKey().get()); - - if (!retrievedRelationship.isPresent()) throw new AssertionError("Failed to retrieve stored relationship " + storedRelationship); - if (!storedRelationship.equals(retrievedRelationship.get())) throw new AssertionError("Retrieved relationship does not equal stored object"); - - assertTrue(retrievedRelationship.get().getProperty("property-1").get().equals("value-1")); - assertTrue(retrievedRelationship.get().getProperty("property-2").get().equals(3)); - - if (!graph.retrieveRelationships(storedRelationship.getSource()).collect(Collectors.toList()).contains(storedRelationship)) - throw new AssertionError("Failed to retrieve relationships for source object"); - - final ChampRelationship updatedRelationship = ChampRelationship.create() - .from(retrievedRelationship.get()) - .withKey(retrievedRelationship.get().getKey().get()) - .withProperty("property-2", 4) - .build(); - - final ChampRelationship storedUpdRel = graph.storeRelationship(updatedRelationship); - final Optional retrievedUpdRel = graph.retrieveRelationship(storedUpdRel.getKey().get()); - - assertTrue(retrievedUpdRel.isPresent()); - assertTrue(retrievedUpdRel.get().equals(storedUpdRel)); - assertTrue(retrievedUpdRel.get().getProperty("property-1").get().equals("value-1")); - assertTrue(retrievedUpdRel.get().getProperty("property-2").get().equals(4)); - - - // validate the replaceRelationship method - final ChampRelationship replacedRelationship = new ChampRelationship.Builder(storedSource, storedTarget, "relationship") - .key(retrievedRelationship.get().getKey().get()) - .property("property-2", 4) - .build(); - - final ChampRelationship replacedRel = graph.replaceRelationship(replacedRelationship); - final Optional retrievedReplacedRel = graph - .retrieveRelationship(replacedRel.getKey().get()); - - assertTrue(replacedRel.getProperties().size()==1); - assertTrue(replacedRel.getProperty("property-2").get().equals(4)); - - assertTrue(retrievedReplacedRel.get().getProperties().size()==1); - assertTrue(retrievedReplacedRel.get().getProperty("property-2").get().equals(4)); - - if (!retrievedReplacedRel.isPresent()) throw new AssertionError("Failed to retrieve stored relationship " + replacedRel); - if (!replacedRel.equals(retrievedReplacedRel.get())) throw new AssertionError("Retrieved relationship does not equal stored object"); - - - graph.deleteRelationship(retrievedRelationship.get()); - - if (graph.retrieveRelationship(relationship.getKey()).isPresent()) throw new AssertionError("Relationship not successfully deleted"); - - try { - graph.deleteRelationship(retrievedRelationship.get()); - throw new AssertionError("Failed to throw exception for missing relationship"); - } catch (ChampRelationshipNotExistsException e) { - //Expected - } - - assertTrue(graph.queryRelationships(Collections.emptyMap()).count() == 0); - assertTrue(graph.queryObjects(Collections.emptyMap()).count() == 2); - } catch (ChampSchemaViolationException e) { - throw new AssertionError("Schema mismatch while storing object", e); - } catch (ChampMarshallingException e) { - throw new AssertionError("Marshalling exception while storing object", e); - } catch (ChampUnmarshallingException e) { - throw new AssertionError("Unmarshalling exception while retrieving relationship", e); - } catch (ChampRelationshipNotExistsException e) { - throw new AssertionError("Attempted to delete non-existent relationship", e); - } catch (ChampObjectNotExistsException e) { - throw new AssertionError("Object does not exist after storing it", e); - } - - try { - graph.retrieveRelationships(ChampObject.create().ofType("").withoutKey().build()); - throw new AssertionError("Failed to handle missing object while retrieving relationships"); - } catch (ChampUnmarshallingException e) { - throw new AssertionError(e); - } catch (ChampObjectNotExistsException e) { - //Expected - } - //Negative test cases for replace relationship - - try{ - graph.replaceRelationship(new ChampRelationship.Builder(ChampObject.create() - .ofType("foo") - .withoutKey() - .build(), ChampObject.create() - .ofType("foo") - .withoutKey() - .build(), "relationship") - .key("1234") - .property("property-2", 4) - .build()); - } - catch (ChampUnmarshallingException e) { - throw new AssertionError(e); - } catch (ChampMarshallingException e) { - throw new AssertionError(e); - } catch (ChampSchemaViolationException e) { - throw new AssertionError(e); - } catch (ChampRelationshipNotExistsException e) { - throw new AssertionError(e); - } catch(IllegalArgumentException e){ - //expected - } - - try{ - graph.replaceRelationship(new ChampRelationship.Builder(ChampObject.create() - .ofType("foo") - .withKey("123") - .build(), ChampObject.create() - .ofType("foo") - .withKey("456") - .build(), "relationship") - .property("property-2", 4) - .build()); - } - catch (ChampUnmarshallingException e) { - throw new AssertionError(e); - } catch (ChampMarshallingException e) { - throw new AssertionError(e); - } catch (ChampSchemaViolationException e) { - throw new AssertionError(e); - } catch (ChampRelationshipNotExistsException e) { - //expected - } catch(IllegalArgumentException e){ - throw new AssertionError(e); - } - - - } - - @Test - public void testFluentRelationshipCreation() { - final Object value1 = new Object(); - final String value2 = "value2"; - final float value3 = 0.0f; - - final ChampRelationship champRelationship = ChampRelationship.create() - .ofType("foo") - .withoutKey() - .withSource() - .ofType("bar") - .withoutKey() - .build() - .withTarget() - .ofType("baz") - .withKey(1) - .build() - .withProperty("key1", value1) - .withProperty("key2", value2) - .withProperty("key3", value3) - .build(); - - assertTrue(champRelationship.getKey().equals(Optional.empty())); - assertTrue(champRelationship.getType().equals("foo")); - assertTrue(champRelationship.getProperty("key1").get() instanceof Object); - assertTrue(champRelationship.getProperty("key1").get().equals(value1)); - assertTrue(champRelationship.getProperty("key2").get() instanceof String); - assertTrue(champRelationship.getProperty("key2").get().equals(value2)); - assertTrue(champRelationship.getProperty("key3").get() instanceof Float); - assertTrue(champRelationship.getProperty("key3").get().equals(value3)); - } - - @Test - public void testChampRelationshipEnums() { - for (ReservedPropertyKeys key : ChampRelationship.ReservedPropertyKeys.values()) { - assertTrue(ChampRelationship.ReservedPropertyKeys.valueOf(key.name()) == key); - } - - for (ReservedTypes type : ChampRelationship.ReservedTypes.values()) { - assertTrue(ChampRelationship.ReservedTypes.valueOf(type.name()) == type); - } - } -} diff --git a/version.properties b/version.properties index abe15cf..9c95207 100644 --- a/version.properties +++ b/version.properties @@ -4,11 +4,11 @@ # because they are used in Jenkins, whose plug-in doesn't support major_version=1 -minor_version=1 +minor_version=2 patch_version=0 base_version=${major_version}.${minor_version}.${patch_version} # Release must be completed with GIT information # in Jenkins release_version=${base_version} -snapshot_version=${base_version}-SNAPSHOT \ No newline at end of file +snapshot_version=${base_version}-SNAPSHOT -- 2.16.6